學(xué)習(xí)整理的相關(guān)章節(jié)鏈接:
基礎(chǔ)篇_1.音視頻學(xué)習(xí)框架
基礎(chǔ)篇_2. 顏色空間模型 RBG监右、YUV泛啸、HSV
基礎(chǔ)篇_3.圖像編碼之Bmp
基礎(chǔ)篇_4.音頻基礎(chǔ)概念
基礎(chǔ)篇_5.音頻數(shù)據(jù)采集
基礎(chǔ)篇_6.音頻編碼PCM
基礎(chǔ)篇_7.音頻編碼WAV
基礎(chǔ)篇_8.音頻編碼MP3\AAC
1.什么是PCM音頻數(shù)據(jù)
PCM(Pulse Code Modulation)也被稱為脈沖編碼調(diào)制堪唐。在基礎(chǔ)篇_5.音頻數(shù)據(jù)采集我們有簡(jiǎn)要介紹過(guò)PCM音頻數(shù)據(jù)是未經(jīng)壓縮的音頻采樣數(shù)據(jù)裸流,它是由模擬信號(hào)經(jīng)過(guò)采樣赐纱、量化糊肤、編碼轉(zhuǎn)換成的標(biāo)準(zhǔn)的數(shù)字音頻數(shù)據(jù)助泽。
2.PCM音頻數(shù)據(jù)是如何存儲(chǔ)的
如果是單聲道的音頻文件啰扛,采樣數(shù)據(jù)按時(shí)間的先后順序依次存入(有的時(shí)候也會(huì)采用LRLRLR方式存儲(chǔ),只是另一個(gè)聲道的數(shù)據(jù)為0)嗡贺,如果是雙聲道的話就按照LRLRLR的方式存儲(chǔ)隐解,存儲(chǔ)的時(shí)候還和機(jī)器的大小端有關(guān)。大端模式如下圖所示:
3.PCM音頻數(shù)據(jù)中常用的專業(yè)術(shù)語(yǔ)
一般我們描述PCM音頻數(shù)據(jù)的參數(shù)的時(shí)候有如下描述方式
44100HZ 16bit stereo: 每秒鐘有 44100 次采樣, 采樣數(shù)據(jù)用 16 位(2字節(jié))記錄, 雙聲道(立體聲);
22050HZ 8bit mono:每秒鐘有 22050 次采樣, 采樣數(shù)據(jù)用 8 位(1字節(jié))記錄, 單聲道;
44100Hz指的是采樣率诫睬,它的意思是每秒取樣44100次厢漩。采樣率越大,存儲(chǔ)數(shù)字音頻所占的空間就越大岩臣。
16bit指的是采樣精度溜嗜,意思是原始模擬信號(hào)被采樣后,每一個(gè)采樣點(diǎn)在計(jì)算機(jī)中用16位(兩個(gè)字節(jié))來(lái)表示架谎。采樣精度越高越能精細(xì)地表示模擬信號(hào)的差異炸宵。
一般來(lái)說(shuō)PCM數(shù)據(jù)中的波形幅值越大,代表音量越大谷扣。
4.PCM音頻數(shù)據(jù)的處理
4.1.分離PCM音頻數(shù)據(jù)左右聲道的數(shù)據(jù)
因?yàn)镻CM音頻數(shù)據(jù)是按照LRLRLR的方式來(lái)存儲(chǔ)左右聲道的音頻數(shù)據(jù)的土全,所以我們可以通過(guò)將它們交叉的讀出來(lái)的方式來(lái)分離左右聲道的數(shù)據(jù)
int simplest_pcm16le_split(char *url){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_l.pcm","wb+");
FILE *fp2=fopen("output_r.pcm","wb+");
unsigned char *sample=(unsigned char *)malloc(4);
while(!feof(fp)){
fread(sample,1,4,fp);
//L
fwrite(sample,1,2,fp1);
//R
fwrite(sample+2,1,2,fp2);
}
free(sample);
fclose(fp);
fclose(fp1);
fclose(fp2);
return 0;
}
4.2.降低某個(gè)聲道的音量
因?yàn)閷?duì)于PCM音頻數(shù)據(jù)而言,它的幅值(即該采樣點(diǎn)采樣值的大谢嵯选)代表音量的大小裹匙,所以我們可以通過(guò)減小某個(gè)聲道的數(shù)據(jù)的值來(lái)實(shí)現(xiàn)降低某個(gè)聲道的音量
int simplest_pcm16le_halfvolumeleft(char *url){
FILE *fp=fopen(url,"rb+");
FILE *fp1=fopen("output_halfleft.pcm","wb+");
int cnt=0;
unsigned char *sample=(unsigned char *)malloc(4);
while(!feof(fp)){
short *samplenum=NULL;
fread(sample,1,4,fp);
samplenum=(short *)sample;
*samplenum=*samplenum/2;
//L
fwrite(sample,1,2,fp1);
//R
fwrite(sample+2,1,2,fp1);
cnt++;
}
printf("Sample Cnt:%d\n",cnt);
free(sample);
fclose(fp);
fclose(fp1);
return 0;
}