PCM全稱Pulse-Code Modulation,翻譯一下是脈沖調(diào)制編碼。
在音視頻中,PCM是一種用數(shù)字表示采樣模擬信號(hào)的方法。
要將一段音頻模擬信號(hào)轉(zhuǎn)換為數(shù)字表示,包含如下三個(gè)步驟:
Sampling(采樣)處理,實(shí)際上就是讓采樣數(shù)據(jù)能夠完全表示原始信號(hào),且采樣數(shù)據(jù)能夠通過重構(gòu)還原成原始信號(hào)的過程,如上圖。
將采樣后的圖拿出來單獨(dú)解釋:
每秒鐘的樣本數(shù)也被稱之為采樣率(Sample rate)。在Sampling圖示案例中,采樣率為每秒34次。意味著在一秒的時(shí)間內(nèi),原始信號(hào)被采樣了34次(也就是藍(lán)色垂直線段的數(shù)量)。
通常,采樣率的單位用Hz表示,例如1Hz表示每秒鐘對(duì)原始信號(hào)采樣一次,1KHz表示每秒鐘采樣1000次。1MHz表示每秒鐘采樣1百萬(wàn)次。
根據(jù)場(chǎng)景的不同,采樣率也有所不同,采樣率越高,聲音的還原程度越高,質(zhì)量就越好,同時(shí)占用空間會(huì)變大。
例如:通話時(shí)的采樣率為8KHz,常用的媒體采樣率有44KHz,對(duì)于一些藍(lán)光影片采樣率高達(dá)1MHz。
一些工作的需要,需要保存成FLV文件,而在保存的過程中,48000的采樣率并不符合用FLV的封裝標(biāo)準(zhǔn)(最高44100),所以有時(shí)候需要通過調(diào)用如ffmpeg來重采樣pcm,并保存文件。
再比如說,不同質(zhì)量要求下,對(duì)音頻的采樣率有一定標(biāo)準(zhǔn),為了滿足標(biāo)準(zhǔn),就需要調(diào)整。不過一般是由高往低調(diào)整,很少由低往高調(diào)整
原始信號(hào)采樣后,需要通過量化來描述采樣數(shù)據(jù)的大小。如圖:
在圖例中,如果說采樣是畫垂直線段的話,那么量化就是畫水平線,用于衡量每次采樣的數(shù)字指標(biāo)。如圖:
為了更好的描述量化過程,先來介紹一下bit-depth(位深):用來描述存儲(chǔ)數(shù)字信號(hào)值的bit數(shù)。較常用的模擬信號(hào)位深有:
在當(dāng)前例子中,如果用為8-bit位深來描述的話,就如下圖所示:
圖中,第9次采樣的平頂樣本對(duì)應(yīng)的level用十進(jìn)制表示為255,也就是二進(jìn)制的1111 1111。
采樣數(shù)據(jù)經(jīng)過編碼后產(chǎn)生的二進(jìn)制數(shù)據(jù),就是PCM數(shù)據(jù)。PCM數(shù)據(jù)可以直接存儲(chǔ)在介質(zhì)上,也可以在經(jīng)過編解碼處理后進(jìn)行存儲(chǔ)或傳輸。
采樣率(Sample rate):每秒鐘采樣多少次,以Hz為單位。
位深度(Bit-depth):表示用多少個(gè)二進(jìn)制位來描述采樣數(shù)據(jù),一般為16bit。
字節(jié)序:表示音頻PCM數(shù)據(jù)存儲(chǔ)的字節(jié)序是大端存儲(chǔ)(big-endian)還是小端存儲(chǔ)(little-endian),為了數(shù)據(jù)處理效率的高效,通常為小端存儲(chǔ)。
聲道數(shù)(channel number):當(dāng)前PCM文件中包含的聲道數(shù),是單聲道(mono)、雙聲道(stereo),此外還有5.1聲道(常用于影院立體環(huán)繞聲)等。
采樣數(shù)據(jù)是否有符號(hào)(Sign):要表達(dá)的就是字面上的意思,需要注意的是,使用有符號(hào)的采樣數(shù)據(jù)不能用無符號(hào)的方式播放。
以FFmpeg中常見的PCM數(shù)據(jù)格式s16le為例:它描述的是有符號(hào)16位小端PCM數(shù)據(jù)。
s表示有符號(hào),16表示位深,le表示小端存儲(chǔ)。
本節(jié)介紹PCM在內(nèi)存中的存儲(chǔ)
些圖像化的描述,那么一段PCM格式的數(shù)據(jù)流怎么表示的呢?
以8-bit有符號(hào)為例,長(zhǎng)得像這樣:
+---------+-----------+-----------+----
binary | 0010 0000 | 1010 0000 | ...
decimal | 32 | -96 | ...
+---------+-----------+-----------+----
每個(gè)分割符"|"分割字節(jié)。因?yàn)槭?-bit有符號(hào)表示的采樣數(shù)據(jù),所以采樣的范圍為-128~128。
圖示中表示的是兩個(gè)連續(xù)采樣數(shù)據(jù)的二進(jìn)制和十進(jìn)制表示的值。
如果我們有一個(gè)PCM文件,在代碼中,我們可以通過以下方式來讀取這樣的PCM數(shù)據(jù)流(Stream)。
FILE *file
int8_t *buffer;
file = fopen("PCM file path");
buffer = malloc(fileSize);
fread(buffer, sizeof(int8_t), fileSize / sizeof(int8_t), file);
偽代碼僅僅表示一種加載方式。但在代碼中,一開始就將整個(gè)文件加載到了內(nèi)存中,這是不對(duì)的。因?yàn)槲覀兊囊纛l數(shù)據(jù)量往往會(huì)比較大,一次性全部加載增加了內(nèi)存負(fù)擔(dān),而且并不必要。
通常我們會(huì)為buffer分配一個(gè)固定的長(zhǎng)度,例如2048字節(jié),通過循環(huán)的方式一邊從文件中加載PCM數(shù)據(jù),一邊播放。
加載好PCM數(shù)據(jù)后,需要送到音頻設(shè)備驅(qū)動(dòng)程序中播放,這時(shí)我們應(yīng)該能聽到聲音。與PCM數(shù)數(shù)據(jù)一同到達(dá)驅(qū)動(dòng)程序的通常還有采樣率(sample rate),用來告訴驅(qū)動(dòng)每秒鐘應(yīng)該播放多少個(gè)采樣數(shù)據(jù)。如果傳遞給驅(qū)動(dòng)程序的采樣率大于PCM實(shí)際采樣率,那么聲音的播放速度將比實(shí)際速度快,反之亦然。
OK,對(duì)于PCM數(shù)據(jù)流的存儲(chǔ)而言,上面僅僅只是單聲道。對(duì)于多聲道的PCM數(shù)據(jù)而言,通常會(huì)交錯(cuò)排列,就像這樣:
+---------+-----------+-----------+-----------+-----------+----
FL | FR | FL | FR | FL |
+---------+-----------+-----------+-----------+-----------+----
對(duì)于8-bit有符號(hào)的PCM數(shù)據(jù)而言,上圖表示第一個(gè)字節(jié)存放第一個(gè)左聲道數(shù)據(jù)(FL),第二個(gè)字節(jié)放第一個(gè)右聲道數(shù)據(jù)(FL),第三個(gè)字節(jié)放第二個(gè)左聲道數(shù)據(jù)(FL)…
不同的驅(qū)動(dòng)程序?qū)τ诙嗦暤罃?shù)據(jù)的排列方式可能稍有區(qū)別,下面是常用的聲道排列地圖:
2: FL FR (stereo)
3: FL FR LFE (2.1 surround)
4: FL FR BL BR (quad)
5: FL FR FC BL BR (quad + center)
6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR)
7: FL FR FC LFE BC SL SR (6.1 surround)
8: FL FR FC LFE BL BR SL SR (7.1 surround)
聯(lián)系客服