PCM编码格式

article/2025/9/30 19:25:53

目录

一、PCM音频编码格式

1. 相关英文单词

2. PCM数据结构

2.1 单声道数据

2.2 多声道数据

2.3 小结

二、WAV音频文件格式


一、PCM音频编码格式

1. 相关英文单词

Amplitude:幅度

PAM:Pulse Amplitude Modulation 脉冲幅度调制(数字信号过程采样)

Stereo:立体声(双声道),Mono:单声道

PCM:Pulse Code Modulation

Sampling:采样        Quantization:量化           Code:编码

Nyquist Sampling theorem:奈奎斯特采样定理

Analog Signal:模拟信号   Digital Signal:数字信号

Sample rate:采样率(每秒钟的样本点数)sampleing bit depth:采样位深度

Channel:通道数/声道数

(1)PCM是最原始的音频编码格式,并不是文件格式,WAV/MP3等才是文件格式。

(2)采样率:每秒钟的采样次数/每秒钟的样本点数,即一秒钟能采集到多少个离散的数值点,比如:16KHz=16000Hz,意思就是16000个采样点/s,采样率是保证音质的一个重要参数。

(3)采样位深度是每一个采样点的值的bit数,很容易理解,bit越多,能表示的数范围就越广,更加能表示模拟信号,可以直观理解,如果采样率和位深都很大,采样的离散序列就可以近似等于模拟信号。

8bit:256个值,从0~255

16bit:65536个值,从0~65535

24bit:………………………………

32bit:………………………………….

2. PCM数据结构

(1)关于音频数据流

编码之后的PCM数据流是一串0和1的组合:0011000010101100……

所以,就要根据一些相关信息来解析数据。假如采样位深是8bit,且是有符号的数据。那么数据解析如下:

0011 0000    1010 1100……

第一个字节,除掉最高位符号位后,值就是+48

第二个字节,除掉最高位符号位后,值就是-44

在范围-128~127之内。

一般来说,常用的是16bit的位深,在C语言中用short类型(两字节)的数据来表示即可。

2.1 单声道数据

实例:读取一个32KHz,单声道,16bit的PCM音频文件数据到内存,并再次写入新文件。

int main(int argc, char** argv)
{int i, j, count;FILE *fpin = NULL;FILE *fpout = NULL;fpin = fopen("input.pcm", "rb"); //单声道fpout = fopen("output.pcm", "wb");fseek(fpin, 0, SEEK_END);long inputdata_length = ftell(fpin);inputdata_length /= 2;printf("input_file_len:% ld\n", inputdata_length);short *stream_in = (short *)malloc(inputdata_length * sizeof(short));//读出数据流(0/1数据流--->字节数据)rewind(fpin);count = fread(stream_in, sizeof(short), inputdata_length, fpin);printf("count=%d\n", count);//将数据写入文件fwrite(stream_in, sizeof(short), inputdata_length, fpout);fclose(fpin);fclose(fpout);free(stream_in);printf("process finished.\r\n");return 0;
}

注:

(1)音频数据一般都有符号,可以直接打印出每一个采样点的音频数据:printf(“stream_in[%d]=%hd\n”, 100, stream_in[100]);

(2) 16bit的深度,所以缓存空间的数据类型定义成short,刚好合适

(3) 代码运行结束,生成的文件大小没变,可使用cooledit pro打开对比查看波形图

2.2 多声道数据

(1)数据排布

对于多声道的数据流,声道数据会交叉排列。当然,这跟底层驱动程序相关,比如一些ADC采集模块,stereo数据排布就是这样的。

第1个byte(左声道)/第2个byte(右)/第3个byte(左)/第4个byte(左)……

(2)关于字节序

数据是大端存储结构还是小端存储结构,一般使用的是小端存储结构(Little Endian)。如下图:

 实例:分离双声道PCM文件数据(LE/44100Hz/16bi/立体声)

int main(int argc, char** argv)
{int i, j, count;FILE *fpin = NULL;FILE *fp_l = NULL;FILE *fp_r = NULL;fpin = fopen("44100_2ch_stereo.pcm", "rb");fp_l = fopen("left.pcm", "wb");fp_r = fopen("right.pcm", "wb");fseek(fpin, 0, SEEK_END);int inputdata_length = ftell(fpin);inputdata_length = inputdata_length/2;  //16bitprintf("input_file_len:% d\n", inputdata_length);short *stream_in = (short *)malloc(inputdata_length * sizeof(short));short *stream_l  = (short *)malloc((inputdata_length/2) * sizeof(short));short *stream_r  = (short *)malloc((inputdata_length/2) * sizeof(short));//读出数据流(数据流--->字节数据)rewind(fpin);count = fread(stream_in, sizeof(short), inputdata_length, fpin);printf("count=%d\n", count);//分离左右声道数据int loop=inputdata_length/2;short *dat_ptr=stream_in;for(int i=0; i<loop; i=i+2) {stream_l[i]=*dat_ptr;stream_l[i+1]=*(dat_ptr+1);dat_ptr=dat_ptr+2;stream_r[i]=*dat_ptr;stream_r[i+1]=*(dat_ptr+1);dat_ptr=dat_ptr+2;}//将左右声道数据写入文件fwrite(stream_l, sizeof(short), inputdata_length/2, fp_l);fwrite(stream_r, sizeof(short), inputdata_length/2, fp_r);fclose(fpin);fclose(fp_l);fclose(fp_r);free(stream_in);free(stream_l);free(stream_r);printf("process finished.\r\n");return 0;
}

文件大小和数据量减小一半,左右声道均选择44100Hz的采样率进行播放,声音正常。

 

2.3 小结

(1)s16le

s-----signed,就是有符号数据,根据采样位深度,可以知道数值范围,所以在音频处理的时候,需要注意数据是否溢出

16----采样位深16bit

 le----小端存储

(2)PC的声卡一般是16bit或者24bit

(3)PCM不是音频文件格式,因此一般的音乐播放软件无法打开,需要保存为wav或者其他格式(加个文件头)才行。

二、WAV音频文件格式

关于wav音频文件格式不放在这里解析,算法处理过程中(实际上算法一般都是针对PCM原始编码格式进行),需要注意下面几点即可:

  1. 构成:文件头+数据部分。
  2. 文件头占44个字节,后面就是数据部分,读取音频数据时,要注意偏移。
  3. 音频部分的编码可以是PCM,也可以是其他格式。

实例:读取wav音频文件数据,伪代码如下

/* 01. 读取音频数据 */

fp_in = fopen("clean.wav", "rb");

fseek(fp_in, 0, SEEK_END);

long clean_len = ftell(fp_in);

clean_len = clean_len -44; //减掉文件头

clean_len /= 2;

printf("clean voice len:% ld\n", clean_len);

short *clean_buf = (short *)malloc(clean_len * sizeof(short)); //申请音频数据存储空间

rewind(fp_in);

//先偏移,跳过文件头再读数据

fseek(fp_in, 44, SEEK_SET);

count = fread(clean_buf, sizeof(short), clean_len, fp_in);

/* 02. 分帧,加窗,傅里叶变换到频域,计算 */

/* 03. 还原到时域 */

/* 04. 写入新文件(注意文件头部信息的写入) */


http://chatgpt.dhexx.cn/article/Cg5vDWLM.shtml

相关文章

音频处理——详解PCM数据格式

目录 知识储备什么是PCM采样采样率重采样 量化编码PCM常用指标 PCM数据流 知识储备 音频处理——音频编码原理简介 音频处理——音频处理的基本概念 什么是PCM PCM全称Pulse-Code Modulation&#xff0c;翻译一下是脉冲调制编码。 在音视频中&#xff0c;PCM是一种用数字表…

PCM格式介绍

转自&#xff1a;http://www.cnblogs.com/cheney23reg/archive/2010/08/08/1795067.html http://wiki.multimedia.cx/index.php?titlePCM PCM数据格式 PCM(Pulse Code Modulation)也被称为 脉码编码调制。PCM中的声音数据没有被压缩&#xff0c;如果是单声道的文件&#xff…

PCM文件格式简介(比较专业)

PCM文件&#xff1a;模拟音频信号经模数转换&#xff08;A/D变换&#xff09;直接形成的二进制序列&#xff0c;该文件没有附加的文件头和文件结束标志。Windows的Convert工具可以把PCM音频格式的文件转换成Microsoft的WAV格式的文件。 脉冲编码调制PCM文件格式简介 将音频数…

PCM数据格式介绍

目录 什么是PCM Sampling&#xff08;采样&#xff09; 采样率(Sample rate) Quantization&#xff08;量化&#xff09; Encoding&#xff08;编码&#xff09; PCM数据常用量化指标 PCM数据流 音量控制 采样率调整 什么是PCM PCM全称Pulse-Code Modulation&#xff…

PCM音频数据格式介绍

1. What is PCM? PCM(Pulse-code-modulation)是模拟信号以固定的采样频率转换成数字信号后的表现形式。 Sample Rate : 采样频率单位为&#xff1a;Hz。采样频率越高&#xff0c;音频质量越好&#xff0c;占用空间也越大。 Sign : 音频数据是否是有符号的。通常情况下都是有…

单调栈图文详解(附Java模板)

啥是"单调栈"&#xff0c;它能解决什么样的问题&#xff1f; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 数据结构与算法专栏的文章图文并茂&#x1f995;生动形象&#…

算法之单调栈常见题目

什么时候需要使用单调栈&#xff1f; 通常是一维数组&#xff0c;要寻找任意一个右边或者左边第一个比自己大或小的元素的位置&#xff0c;此时我们就想到可以使用单调栈了。 单调栈的本质是空间换时间&#xff0c;因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高…

单调栈及单调栈的应用

什么是单调栈 单调递增栈&#xff1a;单调递增栈就是从栈底到栈顶数据是从大到小单调递减栈&#xff1a;单调递减栈就是从栈底到栈顶数据是从小到大 解决那类问题 要知道单调栈的适用于解决什么样的问题&#xff0c;我们首先需要知道单调栈的作用。单调栈分为单调递增栈和单调…

理解单调栈与单调队列

单调栈 单调栈&#xff1a;栈内的元素按照某种方式排序下单调递增或单调递减&#xff0c;如果新入栈的元素破坏的单调性&#xff0c;就弹出栈内元素&#xff0c;直到满足单调性。 单调栈分为单调递增栈和单调递减栈&#xff1a; 单调递增栈&#xff1a;栈中数据入栈或出栈的…

【栈 单调栈】浅谈单调栈与单调栈的理解

单调栈 定义&#xff1a; 单调栈&#xff0c;顾名思义&#xff0c;是栈内元素保持一定单调性&#xff08;单调递增或单调递减&#xff09;的栈。这里的单调递增或递减是指的从栈顶到栈底单调递增或递减。既然是栈&#xff0c;就满足后进先出的特点。与之相对应的是单调队列。 …

单调栈(一)

单调栈基本概念及实现 方案1&#xff1a;对于每一个数&#xff0c;遍历其左右位置&#xff0c;时间复杂度为O(N^2) 方案2&#xff1a;单调栈&#xff0c;每个元素入栈一次出栈一次&#xff0c;时间复杂度为O(N) &#xff08;一&#xff09;数组中没有重复值 示例&#xff1a;[…

第九章:单调栈与单调队列

单调栈与单调队列 一、单调栈1、什么是单调栈&#xff1f;2、单调栈的模板&#xff08;1&#xff09;问题&#xff1a;&#xff08;2&#xff09;分析&#xff1a; 二、单调队列1、什么是单调队列2、单调队列模板&#xff08;1&#xff09;问题&#xff08;2&#xff09;分析 一…

单调栈算法详解

单调栈算法详解 单调栈使用模板 stack<int> st; //此处一般需要给数组最后添加结束标志符&#xff0c;具体下面例题会有详细讲解 for (遍历这个数组){if (栈空 || 栈顶元素大于等于当前比较元素){入栈;}else{while (栈不为空 && 栈顶元素小于当前元素){栈顶元素…

单调队列和单调栈详解

这里是我的blog&#xff1a;有更多算法分享。排版可能也会更好看一点v https://endlesslethe.com/monotone-queue-and-stack-tutorial.html 前言 单调栈和单调队列算是栈和队列的高级应用吧&#xff0c;在公司面试中应该是不怎么会出现的&#xff08;除非算法岗&#xff1f;…

什么是单调栈

什么是单调栈 单调栈就是单调递增或者单调递减的栈&#xff0c;也就是栈底到栈顶递增或递减&#xff0c;根据单调栈的的这种结构&#xff0c;可以很容易想到运用单调栈可以很容易的把O(n)的时间复杂度优化到O(n),如果使用数组的话&#xff0c;相对的空间复杂度也不会太高 示例 …

Java实现之单调栈

目录 一.单调栈 二.每日温度 1.题目描述 2.问题分析 3.代码实现 三.下一个更大元素 I 1.题目描述 2.问题分析 3.代码实现 四.下一个更大元素 II 1.题目描述 2.问题分析 3.代码实现 一.单调栈 通常是一维数组&#xff0c;要寻找任一个元素的右边或者左边第一个比自…

[数据结构]单调栈

单调栈 这是笔者的第一篇博客&#xff0c;由于笔者自身水平的限制。用词可能不够准确&#xff0c;句子不太通顺&#xff0c;代码水平可能也不太行&#xff0c;敬请指出&#xff0c;感激不尽&#xff01; 我们都知道栈&#xff08;Stack&#xff09;是一种先入后出的数据结构&am…

单调栈和单调队列

本文摘自博客&#xff0c;欢迎前往博客以获得更好的体验。 单调栈 从名字上就听的出来&#xff0c;单调栈中存放的数据应该是严格单调有序的&#xff0c;具有以下两个性质。 满足从栈顶到栈底的元素具有严格的单调递增或单调递减性&#xff1b;满足栈的后进先出特性&#xff…

数据结构之单调栈(含代码实现)

目录 1.单调栈的基本概念 &#xff1a; 2.单调栈的应用 2.1单调栈 2.2单调栈进阶 2.3最大矩形面积 2.4最大矩形 2.5统计全为1的子矩阵数量 ​ 1.单调栈的基本概念 &#xff1a; 相信大家对栈都非常的熟悉&#xff1f;栈有一个非常鲜明的特点&#xff1a;先进后出 而所谓 单调栈…

C++之单调栈

单调栈的性质 单调栈是一种特殊的栈&#xff0c;特殊之处在于栈内的元素都保持一个单调性。 假设下图是一个栈内元素的排列情况(单调递增的栈)&#xff1a; 此时插入情况有两种&#xff1a; &#xff08;1&#xff09;插入元素大于栈顶元素&#xff1a; 因为7 > 6&#xf…