PCM

PCM(Pulse Code Modulation,脉冲编码调制)是一种将模拟信号转换为数字信号的编码技术,也是现代数字通信和音频存储的核心基础。它的核心原理是通过采样、量化和编码三个步骤,将连续的模拟信号(如声音、图像)转变为离散的数字二进制码流,从而实现高效传输、存储和处理。

PCM的基本工作原理

  1. 采样(Sampling)
    以固定时间间隔(采样率,如44.1kHz)测量模拟信号的瞬时振幅值。根据奈奎斯特采样定理,采样率至少需达到信号最高频率的2倍,才能完整还原原始信号(例如人耳可听范围20Hz-20kHz,故CD音质采用44.1kHz采样率)。

  2. 量化(Quantization)
    将采样得到的连续振幅值近似为有限个离散电平(量化精度,如16bit、24bit)。量化位数越高,动态范围越广(16bit可表示65,536个电平),信号保真度越好,但数据量也越大。

  3. 编码(Encoding)
    将量化后的数值转换为二进制码(如16bit线性PCM),形成数字信号序列,便于存储或传输。

PCM的关键参数

  • 采样率(Sample Rate):每秒采样次数(如8kHz电话语音、48kHz高清音频)。
  • 位深度(Bit Depth):单个采样的量化精度(如16bit CD音质、24bit专业录音)。
  • 声道数(Channels):单声道(Mono)、立体声(Stereo)或多声道(如5.1环绕声)。

PCM的应用场景

  1. 数字音频

    • CD音质(44.1kHz/16bit立体声PCM)
    • WAV、AIFF等无损音频格式直接存储PCM数据。
    • 蓝牙音频传输(如SBC编解码器先解码为PCM再播放)。
  2. 通信系统

    • 传统电话语音(G.711标准采用8kHz/8bit PCM)。
    • VoIP、视频会议中的音频底层编码。
  3. 专业影音制作

    • 影视录音、音乐制作中常用高精度PCM(如96kHz/24bit)保证后期处理空间。
  4. 存储与传输

    • 多数有损压缩格式(如MP3、AAC)需先将PCM数据通过心理声学模型压缩。
    • HDMI、USB音频接口直接传输PCM数字信号。

PCM的优缺点

  • 优点
    • 保真度高,无损编码时可完全还原原始信号。
    • 处理简单,兼容性强,几乎所有数字系统均支持。
  • 缺点
    • 数据量大(1分钟CD音质PCM约10MB),需依赖压缩技术降低存储/传输负担。
    • 直接传输效率低,通常需结合有损或无损编码(如FLAC)。

PCM与其他编码技术的对比

  • 与DSD(Direct Stream Digital)
    PCM采用多比特量化,DSD使用1bit超高采样率(如2.8MHz),后者更接近模拟波形,但编辑灵活性较差(常用于SACD)。
  • 与压缩编码(MP3/AAC)
    PCM保留完整信息,压缩编码通过舍弃人耳不敏感的频段减少数据量。

总结

PCM是数字信号处理的基石,其标准化和通用性使其成为音频、通信等领域的核心编码方式。尽管数据量大,但通过高采样率和高位深配置(如192kHz/24bit),它能满足从消费级到专业级的高保真需求。现代技术(如MQA编码)仍在PCM基础上优化效率,确保其在未来持续发挥关键作用。

代码

guage-c
  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
// 测试的PCM数据采用采样率44.1k, 采用精度S16SYS, 通道数2 #include <stdio.h> #include <SDL2/SDL.h> #define PCM_BUFFER_SIZE (1024*2*2*2) // 已知通道数为2 采样深度为16bit(2字节) 每次读取两帧数据 每次采样1024个采样点 static Uint8* s_audio_pos = NULL; // 起始位置 static Uint8* s_audio_end = NULL; // 结束位置 static Uint8* s_audio_buf = NULL; // 数据 void fill_pcm_callback (void *userdata, Uint8 * stream, int len) { SDL_memset(stream, 0, len); if (s_audio_pos >= s_audio_end) { return; } int remain_buffer_len = s_audio_end - s_audio_buf; // 计算读取数据的大小 len = len < remain_buffer_len ? len : remain_buffer_len; SDL_MixAudio(stream, s_audio_pos, len, SDL_MIX_MAXVOLUME/6); // 将内存数据拷贝到音频数据流 printf("len=%d\n", len); s_audio_pos += len; // 偏移 } #undef main int main(int argc, char* argv[]) { int ret = -1; FILE* audio_fp = NULL; SDL_AudioSpec spec; const char* audio_path = "../44100_16bit_2ch.pcm"; size_t read_buf_len = 0; if(SDL_Init(SDL_INIT_AUDIO)) { fprintf(stderr, "Could not init sdl\n"); return ret; } audio_fp = fopen(audio_path, "rb"); if (!audio_fp) { fprintf(stderr, "Could not open audio file\n"); return -1; } s_audio_buf = (Uint8*)malloc(PCM_BUFFER_SIZE); spec.channels = 2; // 双通道 spec.callback = fill_pcm_callback; // 回调函数 spec.format = AUDIO_S16SYS; // 精度 spec.userdata = NULL; spec.silence = 0; spec.samples = 1024; // 采样点 spec.freq = 44100; // 频率 if(SDL_OpenAudio(&spec, NULL)) { fprintf(stderr, "Failed to open audio\n"); goto _FAIL; } SDL_PauseAudio(0); int data_count = 0; for(;;) { read_buf_len = fread(s_audio_buf, 1, PCM_BUFFER_SIZE, audio_fp); if (read_buf_len == 0) { break; } data_count += read_buf_len; s_audio_pos = s_audio_buf; s_audio_end = s_audio_buf + read_buf_len; while(s_audio_pos < s_audio_end) { SDL_Delay(10); } } SDL_CloseAudio(); _FAIL: if (audio_fp) { fclose(audio_fp); } if (s_audio_buf) { free(s_audio_buf); } SDL_Quit(); return 0; }

代码解释写在注释里啦!