音频参数
经常见到这样的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等.
- 44100HZ 16bit stereo:
每秒钟有 44100 次采样, 采样数据用 16 位(2字节)记录, 双声道(立体声);
- 22050HZ 8bit mono:
每秒钟有 22050 次采样, 采样数据用 8 位(1字节)记录, 单声道;
什么是PCM音频数据
PCM(Pulse Code Modulation)也被称为脉冲编码调制。
PCM音频数据是未经压缩的音频采样数据裸流,它是由模拟信号经过采样、量化、编码转换成的标准的数字音频数据。
PCM数据存储格式
![IMAGE](/resources/11B3818749C213BABD9FB07B16F5509B.jpg)
PCM数据存储格式
本文中声音样值的采样频率一律是44100Hz,采样格式一律为16LE。
“16”代表采样位数是16bit。由于1Byte=8bit,所以一个声道的一个采样值占用2Byte。
“LE”代表Little Endian,代表2 Byte采样值的存储方式为高位存在高地址中。
立体声的左右声道的数据是一样的吗?
原来一直理解立体声的左右声道是一样的,但是通过查看实际的数据,发现并不一样。比如:
![IMAGE](/resources/7631E378E2ABDF34AF6EF1544B3A8474.jpg)
PCM文件的16进制数据
从以上可以看出,刚开始的4个字节是同一个采样点,其中0x04e8是左声道,0x01c9是右声道,发现是不一样的。
通过cool edit pro查看波形:
![IMAGE](/resources/41721FD9DF8C5BD9BFDB3B54BF7C01FD.jpg)
左右声道对比
可以看出左右声道,虽然波形相似,但是的确存在不同。
PCM Examples
以下代码可读取pcm文件,并演示了打印采样点的值和将立体声分离成左声道和右声道。
1 2 3 4 5 6 7 8 9 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
| #include "stdafx.h" #include <fstream> #include <iostream> using namespace std;
int _tmain(int argc, _TCHAR* argv[]) { char szFileName[256] = {0}; sprintf_s(szFileName, ".\\44100_stereo_s16le.pcm");
ifstream inFile(szFileName, ios::in | ios::binary | ios::ate); long nFileSizeInBytes = inFile.tellg();
char *pszPCMBuffer = new char[nFileSizeInBytes];
inFile.seekg(0, ios::beg); inFile.read(pszPCMBuffer, nFileSizeInBytes); inFile.close();
cout<<"FileName: " << szFileName <<", nFileSizeInBytes: " << nFileSizeInBytes <<endl; cout << "Read file to a buffer Done!!!\n\n";
short szItem[1024] = {0}; memcpy(szItem, pszPCMBuffer, 256);
for (int i = 0; i < 128; i++) { printf("%6d ", szItem[i]);
if ((i + 1) % 8 == 0) { cout<<endl; } }
FILE *fpLeft = fopen("44100_mono_s16le_l.pcm","wb+"); FILE *fpRight = fopen("44100_mono_s16le_r.pcm","wb+");
printf("\n Split stereo to left and right ...\n");
for (int nPos = 0; nPos < nFileSizeInBytes; ) { if ((nPos / 2) % 2 == 0) { if (fpLeft) { fwrite(pszPCMBuffer + nPos, 1, 2, fpLeft); } } else { if (fpRight) { fwrite(pszPCMBuffer + nPos, 1, 2, fpRight); } }
nPos += 2; }
if (fpLeft) { fclose(fpLeft); fpLeft = NULL; }
if (fpRight) { fclose(fpRight); fpRight = NULL; } printf("\n Split stereo to left and right Done. \n");
if (pszPCMBuffer) { delete [] pszPCMBuffer; pszPCMBuffer = NULL; }
getchar();
return 0; }
|
References:
http://blog.csdn.net/ownwell/article/details/8114121
http://blog.csdn.net/leixiaohua1020/article/details/50534316
https://www.cnblogs.com/CoderTian/p/6657844.html
作者:FlyingPenguin
链接:https://www.jianshu.com/p/e568f94cdf6a
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。