音訊重取樣的基本(我的學習筆記)
Part 1:
先介紹最基本的一些概念:
1、何為音訊:聲音的儲存,儲存形式以及播放;
2、取樣頻率(rate):在一段音訊上取樣的頻率,一般常用的為44.1kHz,音訊最大的頻寬20kHz,人耳能分辨的範圍是20Hz~20kHz;
3、失真:傳輸音訊資料過程中,由於將波音放大的時候造成資料缺失稱之為失真;
4、頻譜:頻率譜密度的簡稱,是頻率的分部曲線;
5、雙聲道:立體聲,如果左右兩個聲道波形一樣,可以人為製造一定的相位差,但差是個固定的,這為假立體聲,只有左右兩個聲道波形完全不一樣時才會形成立體聲;
6、錄單聲道:由於錄音時只有一個話筒,所以建議錄音設定引數channels為1,如果錄製雙聲道波形完全一樣,則會造成浪費硬碟儲存空間;
7、錄立體聲:使用兩隻話筒,通過不同位置進行採集;
8、在消除人聲也就是伴唱模式的時候,由於Bass和鼓的相位較小,所以消聲伴奏要做低頻補償;
Part 2:
PCM音訊資料的存數方式
1、pcm資料按照互相交錯格式儲存:LRLRLRLR...具體會有兩種:從小到大:little endian以及big endian從大到小,一般的wav格式檔案都是按照little endian方式儲存;
2、只有左耳有聲音情況是一個聲道的資料全是0,播放器可以將單聲道渲染為雙聲道,但並不是真正意義上的雙聲道;
3、取樣率跟儲存沒有區別,只有跟在儲存空間大小有關係;
4、音訊資料長度 = 秒數 X 取樣率 X 楨長度 / 8;
5、WAV格式檔案的大小計算公式:基於 44.1khz,16bit取樣精度:Size = 44.1khz * 16bit *2(雙聲道) * time(歌曲時長)
Part 3:
音訊裝置檔案簡介:
音訊程式設計介面實際上就是一組音訊裝置檔案,通過它們可以從音效卡中read/write,並控制音效卡設定聲道等引數;
1、/dev/sndstat: usage: cat dev/sndstat,彙報當前音效卡狀態,檢測音效卡,不適用於程式中;
2、/dev/dsp:是音效卡用語數字取樣(sampleing)和數字錄音(captrueing)檔案,以只讀方式發開的話是輸入聲音,只寫開啟是輸出聲音。無論是向音效卡寫入還是輸出聲音,裝置都具有預設的格式(format),預設為8rate、1ch、8khz,可以通過ioctl呼叫來改變這些引數值;
3、dev/audio:和2相同,同一個硬體上的不同軟體介面;
4、/dev/mixer:應用程式操作混音器的軟體介面,混音器將多個訊號組成或者疊加,對混音器的程式設計包括如何設定控制增益器的級別,在不同的音源間切換,除了open和close
呼叫,其它操作都是由ioctl呼叫完成的,而且允許多個應用程式同時方位。
5、對音效卡維護的核心緩衝區的修改:
int setting = 0xnnyy , ioctl(handle,SND_DSP_SETFRAGMENT,&setting);
6、dev/snd/controlC0:用於音效卡控制,如通道選擇、混音、麥克風等控制;
7、dev/snd/midiC0D0:用於播放midi音訊檔案;
8、dev/snd/pcmC0D0c:用語錄音的pcm裝置介面;
9、dev/snd/pcmC0D0p:用語播放的pcm裝置介面;
10、dev/snd/seq:音序器;
11、dec/snd/timer:定時器;
Part4:
1、音訊重取樣分為:取樣的位數、取樣的頻率;
2、聲音音質輸出的質量主要取決於音效卡模擬輸入輸出的品質,這跟CODEC轉換品質有著重大關係;(CO:音訊壓縮,DEC:解壓縮,CODEC:多媒體數字訊號解碼器)
3、SRC:改變訊號的取樣率,低取樣率往高取樣率轉換時就是一個重取樣的過程。
4、取樣位數決定取樣精度,如8bit是256個精度,16bit是64k個精度點。
5、WAV格式檔案的大小計算公式:基於 44.1khz,16bit取樣精度
Size = 44.1khz * 16bit *2(雙聲道) * time(歌曲時長)
6、一般由低位向高位進行重取樣的時候最好是整數倍之間進行重採,否則容易造成失真等情況,例如 20khz往上重取樣的時候可以選擇 44.1、88、、、
如果低版本為24向上取樣可選48、96、、、
Part5:
針對音訊重取樣API,這是我當時從其它網站找的相關開源演算法:
API
speex_resampler_process_int() 單聲道 16bit重取樣speex_resampler_process_float() 重取樣浮點序列 (沒用過)
speex_resampler_process_interleaved_float() 交叉的多通道浮點資料
demo
- sr=16000;//原始取樣率
- target_sr=44100;//重取樣後取樣率
- resampler = speex_resampler_init(1, sr, target_sr, 10, NULL);//初始化
- speex_resampler_skip_zeros(resampler);
- while (1)
- {
- readed=fread(input,2,1600,fdr);
- if (readed<=0)
- {
- break;
- }
- in_len=readed;
- out_len=6400;//輸出緩衝大小
- speex_resampler_process_int(resampler, 0, input, &in_len,output, &out_len); //output傳入緩衝大小,傳出實際大小
- fwrite(output,2,out_len,fdw);
- }
- speex_resampler_destroy(resampler);