音视频开发-PCM 原理与 AI 模块实战

1. 引言

音视频开发是移动应用、嵌入式系统和多媒体平台的核心技术方向。无论是语音通话、音乐播放、语音识别还是智能音箱,都离不开音频数据的采集、处理与播放。而这一切的起点,就是音频原始数据 PCM(脉冲编码调制)。本文将从 PCM 原理出发,系统讲解音频数据的生成过程、核心参数与存储格式,并结合 AI 模块(语音识别、AI 降噪等)的实战应用,帮助读者建立从底层数据到上层智能处理的完整认知。

2. PCM 音频原始数据

2.1 PCM 数据的生成过程

PCM 全称是脉冲编码调制(Pulse Code Modulation),是未经过压缩的音频数据。它由模拟信号经过 采样、量化、编码 三大步骤转换而来:
#mermaid-svg-r2RRNApwZbZuF4Cc{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-r2RRNApwZbZuF4Cc .error-icon{fill:#552222;}#mermaid-svg-r2RRNApwZbZuF4Cc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-r2RRNApwZbZuF4Cc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-r2RRNApwZbZuF4Cc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-r2RRNApwZbZuF4Cc .marker.cross{stroke:#333333;}#mermaid-svg-r2RRNApwZbZuF4Cc svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-r2RRNApwZbZuF4Cc p{margin:0;}#mermaid-svg-r2RRNApwZbZuF4Cc .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc .cluster-label text{fill:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc .cluster-label span{color:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc .cluster-label span p{background-color:transparent;}#mermaid-svg-r2RRNApwZbZuF4Cc .label text,#mermaid-svg-r2RRNApwZbZuF4Cc span{fill:#333;color:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc .node rect,#mermaid-svg-r2RRNApwZbZuF4Cc .node circle,#mermaid-svg-r2RRNApwZbZuF4Cc .node ellipse,#mermaid-svg-r2RRNApwZbZuF4Cc .node polygon,#mermaid-svg-r2RRNApwZbZuF4Cc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-r2RRNApwZbZuF4Cc .rough-node .label text,#mermaid-svg-r2RRNApwZbZuF4Cc .node .label text,#mermaid-svg-r2RRNApwZbZuF4Cc .image-shape .label,#mermaid-svg-r2RRNApwZbZuF4Cc .icon-shape .label{text-anchor:middle;}#mermaid-svg-r2RRNApwZbZuF4Cc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-r2RRNApwZbZuF4Cc .rough-node .label,#mermaid-svg-r2RRNApwZbZuF4Cc .node .label,#mermaid-svg-r2RRNApwZbZuF4Cc .image-shape .label,#mermaid-svg-r2RRNApwZbZuF4Cc .icon-shape .label{text-align:center;}#mermaid-svg-r2RRNApwZbZuF4Cc .node.clickable{cursor:pointer;}#mermaid-svg-r2RRNApwZbZuF4Cc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-r2RRNApwZbZuF4Cc .arrowheadPath{fill:#333333;}#mermaid-svg-r2RRNApwZbZuF4Cc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-r2RRNApwZbZuF4Cc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-r2RRNApwZbZuF4Cc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-r2RRNApwZbZuF4Cc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-r2RRNApwZbZuF4Cc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-r2RRNApwZbZuF4Cc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-r2RRNApwZbZuF4Cc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-r2RRNApwZbZuF4Cc .cluster text{fill:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc .cluster span{color:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-r2RRNApwZbZuF4Cc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-r2RRNApwZbZuF4Cc rect.text{fill:none;stroke-width:0;}#mermaid-svg-r2RRNApwZbZuF4Cc .icon-shape,#mermaid-svg-r2RRNApwZbZuF4Cc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-r2RRNApwZbZuF4Cc .icon-shape p,#mermaid-svg-r2RRNApwZbZuF4Cc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-r2RRNApwZbZuF4Cc .icon-shape .label rect,#mermaid-svg-r2RRNApwZbZuF4Cc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-r2RRNApwZbZuF4Cc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-r2RRNApwZbZuF4Cc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-r2RRNApwZbZuF4Cc :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 模拟音频信号
采样
量化
编码
PCM 数字信号

采样:把一段连续的模拟信号转换成离散的数字信号。采样率指每秒钟采样的个数。根据奈奎斯特采样定理:当采样率大于等于连续信号最高频率的 2 倍时,采样信号就能无差别还原出原始信号。人类听觉频率范围是 20Hz~20kHz,因此采样率需达到 40kHz 以上才能保证数据完整性。

量化:在坐标轴上把每一个离散采样点进行数字化操作,即把每个采样点用竖线表示出来,方便后续数字化存储。

编码:把每一个量化后的采样点以二进制形式存储起来。把所有采样点的编码数据连续拼接,就是一段完整的 PCM 数据,例如:

text 复制代码
011011110111101......

因此,音频原始数字信号的生成链路可概括为:

text 复制代码
采样 -> 量化 -> 编码 = PCM 数据

2.2 PCM 核心参数

2.2.1 采样率

采样率指每秒钟采样的个数,即 1 秒内采集声音的频率。例如 48000Hz 表示一秒钟采集 48000 个采样点。采样率越高,音频质量越好。PCM 常用采样率如下:

  • 192000Hz(192kHz):蓝光、高清电影 DVD。
  • 96000Hz(96kHz):蓝光、高清电影 DVD。
  • 48000Hz(48kHz):数字电视、DVD,最常用。
  • 44100Hz(44.1kHz):CD 音质。
  • 22000Hz(22kHz):无线广播。
2.2.2 采样深度(位深)

采样深度表示每次采样的大小。例如采样深度为 16bit,则声音有 2 的 16 次方个振幅等级;32bit 则有 2 的 32 次方个振幅等级。振幅等级越多,声音质量越高。PCM 常见采样深度有 8bit、16bit、32bit 三种。

2.2.3 通道数

PCM 常见通道数有四种:

  • 单声道:只有一个声音通道,如电话、喇叭。
  • 双声道(立体声):两个独立声道,录制时声音分配到左右两个通道,听感更立体。
  • 四声道:前左、前右、后左、后右四个发声通道,听感如被声音包围。
  • 5.1 声道:广泛用于家庭影院,开发中较少使用。
2.2.4 PCM 比特率

比特率指每秒传输的比特数(bit),PCM 比特率计算公式为:

text 复制代码
比特率 = 采样率 × 采样深度 × 通道数

例如采样率 48000、采样深度 16bit、通道数 2,则比特率为:

text 复制代码
48000 × 16 × 2 = 1536000 bit/s
2.2.5 PCM 文件大小计算

假设一个 PCM 音频设备采样率 48000、采样精度 16bit、2 通道,采集 10 分钟数据,其大小为:

text 复制代码
48000 × 16 × 2 × 10 × 60 = 921600000 bit

将 bit 转换为字节:

text 复制代码
921600000 / 8 / 1024 / 1024 ≈ 109 MB

可见 PCM 数据体积较大,这也是实际工程中常需压缩编码(如 AAC、Opus)的原因。

2.3 PCM 存储格式

PCM 单双声道的存储布局不同,这里重点讲解双声道。双声道有两种存储方式:

  • 交错模式(Interleaved):先记录第一帧的左声道样本和右声道样本,再记录第二帧,依次交替。
  • 非交错模式(Non-Interleaved):先记录一个周期内所有帧的左声道样本,再记录所有右声道样本。
text 复制代码
交错模式:L R L R L R L R
非交错模式:L L L L L R R R R R

3. RV1126 AI 音频模块实战

cpp 复制代码
#include <assert.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include "rkmedia_api.h"
#define AUDIO_PATH "default"
#define AI_CHN 0

//获取PCM数据的线程
void * get_ai_pcm_thread(void * args)
{
    pthread_detach(pthread_self());
    FILE * pcm_file = fopen("test_ai.pcm", "w+");
    MEDIA_BUFFER mb ;

    while (1)
    {
        //获取PCM数据的线程
        mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_AI, AI_CHN, -1);
        if(!mb)
        {
            printf("RK_MPI_SYS_GetMediaBuffer Failed....\n");
            break;
        }
        
        printf("get_pcm_data success...\n");
        fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, pcm_file);
        RK_MPI_MB_ReleaseBuffer(mb);
    }
}


int main(int argc, char *argv[])
{
    int ret;
    AI_CHN_ATTR_S ai_chn_s;
    ai_chn_s.pcAudioNode = AUDIO_PATH; //音频路径,默认default
    ai_chn_s.u32SampleRate = 48000; //音频采样率
    ai_chn_s.u32Channels = 2;   //音频通道数
    ai_chn_s.u32NbSamples = 1024; //音频采样个数,这里固定1024
    ai_chn_s.enSampleFormat = RK_SAMPLE_FMT_S16;//将音频通道的采样格式设置为 16位有符号PCM
    ai_chn_s.enAiLayout = AI_LAYOUT_NORMAL;  //NORMAL
    ret = RK_MPI_AI_SetChnAttr(AI_CHN, &ai_chn_s);  //设置AI模块
    if(ret)
    {
        printf("Set Ai_Chn_Attr Failed....\n");
    }
    else
    {
        printf("Set Ai_Chn_Attr Success....\n");
    }

    ret = RK_MPI_AI_EnableChn(AI_CHN);  //使能AI模块
    if(ret)
    {
        printf("Enable Ai_Chn_Attr Failed....\n");
    }

    ret = RK_MPI_AI_StartStream(AI_CHN); //启动音频AI模块
    if(ret)
    {
        printf("RK_MPI_AI_StartStream Failed....\n");
    }

    pthread_t pid;
    pthread_create(&pid, NULL, get_ai_pcm_thread, NULL); 

    while (1)
    {
        sleep(2);
    }

    RK_MPI_AI_DisableChn(AI_CHN);


    return 0;
}
相关推荐
有毒的教程1 天前
AI文生视频转场提示词(直接复制,分类型|适配MiniMax H3 / 可灵 / Runway)
人工智能·音视频
浪淘沙jkp1 天前
ComfyUI全方位指南(5)LTX-2.5 ComfyUI图生视频,文生视频可以你也可以的
音视频·comfyui
企业数字化笔记1 天前
视频上传怎么做才可靠?接收、存储、校验与管理的实现方案
音视频
EasyGBS1 天前
国标监控PS流是什么?GB28181视频平台EasyGBS视频封装全链路讲解
服务器·音视频·gb28181
深圳市青牛科技实业有限公司1 天前
GC5358|24bit‑96kHz 立体声 ADC,高性能音频模数转换优选
音视频
企业数字化笔记1 天前
视频音频怎么稳定抽取?从媒体探测到可用音频资产的实现方案
音视频·媒体
byte轻骑兵1 天前
VCP核心缩写概览
人工智能·音视频·le audio·低功耗蓝牙音频
2601_962380761 天前
历史解说与民俗科普视频的AI自动配素材实现教程
人工智能·音视频
台风护盾1 天前
多个MP3怎么合并成一个文件?聊聊音频拼接的采样对齐、接缝咔哒声和一条稳的流水线
音视频·音频处理·音频拼接·多段音频拼接·合并mp3
allnlei2 天前
Opus In-Band FEC 详解:原理、实现与开源方案
ffmpeg·音视频·gstreamer