音視頻學習(十一、PCM格式介紹)

我們原始的音頻數據就是PCM格式,通過咪頭採樣會來的數據也是PCM格式,所以有必要多普及一下音頻的基礎知識。我基礎也不好,這是轉載了一篇寫的比較不錯的博客,大家一起學習。

這是一篇轉載的文章,轉載的鏈接:PCM數據格式介紹

11.1 音頻基礎

聲音是由物體的振動產生的,這種振動引起了周圍空氣壓強的震盪,我們稱這種震盪的函數表現形式爲波形。
在這裏插入圖片描述
聲音的頻率就是週期的倒數,表示聲音在1秒鐘內的週期數,單位是hz,48Khz,就是表示1秒鐘震盪了18k次。

現實生活中我們聽到的聲音是連續的,但是在計算機中只能處理數字信號,不能處理模擬信號,所以我們只能通過採樣的方式,把模擬信號轉化成數字信號,
在這裏插入圖片描述
假設 44100HZ 16bit stereo: 每秒鐘有 44100 次採樣, 採樣數據用 16 位(2字節)記錄, 雙聲道(立體聲),採集4分鐘的數據:44100162460=338688000bit=40M,這個數據就是沒經過壓縮的音頻數據,我們叫做PCM數據。

11.2 PCM介紹

PCM全稱Pulse-Code Modulation,翻譯一下是脈衝調製編碼。

其實大可以不用關心英文釋義,之所以這麼命名是因爲一些歷史原因。

在音視頻中,PCM是一種用數字表示採樣模擬信號的方法。

要將一段音頻模擬信號轉換爲數字表示,包含如下三個步驟:

  1. Sampling(採樣)
  2. Quantization(量化)
  3. Coding(編碼)

通常,我們可以通過一條曲線在座標中顯示連續的模擬信號,如下圖所示:
在這裏插入圖片描述
爲了更容易理解PCM,取其中一段來說明。
在這裏插入圖片描述

假設這表示一段一秒的音頻模擬信號。
在這裏插入圖片描述

11.2.1 Sampling(採樣)

Sampling(採樣)處理,實際上就是讓採樣數據能夠完全表示原始信號,且採樣數據能夠通過重構還原成原始信號的過程,如上圖。

將採樣後的圖拿出來單獨解釋:
在這裏插入圖片描述

  1. 紅色曲線:表示原始信號。
  2. 藍色垂直線段:表示當前時間點對原始信號的一次採樣。採樣是一系列基於振幅(amplitude和相同時間間隔的樣本。這也是爲什麼採樣過程被稱爲PAM的原因。
  3. PAM:(Pulse Amplitude Modulation)是一系列離散樣本之的結果。

11.2.2 採樣率(Sample rate)

每秒鐘的樣本數也被稱之爲採樣率(Sample rate)。在Sampling圖示案例中,採樣率爲每秒34次。意味着在一秒的時間內,原始信號被採樣了34次(也就是藍色垂直線段的數量)。

通常,採樣率的單位用Hz表示,例如1Hz表示每秒鐘對原始信號採樣一次,1KHz表示每秒鐘採樣1000次。1MHz表示每秒鐘採樣1百萬次。

根據場景的不同,採樣率也有所不同,採樣率越高,聲音的還原程度越高,質量就越好,同時佔用空間會變大。

例如:通話時的採樣率爲8KHz,常用的媒體採樣率有44KHz,對於一些藍光影片採樣率高達1MHz。
在這裏插入圖片描述

11.2.3 Quantization(量化)

原始信號採樣後,需要通過量化來描述採樣數據的大小。如圖:
在這裏插入圖片描述
量化處理過程,就是將時間連續的信號,處理成時間離散的信號,並用實數表示。這些實數將被轉換爲二進制數用於模擬信號的存儲和傳輸。

在圖例中,如果說採樣是畫垂直線段的話,那麼量化就是畫水平線,用於衡量每次採樣的數字指標。如圖:
在這裏插入圖片描述
圖中,每條橫線表示一個等級(level)。

爲了更好的描述量化過程,先來介紹一下bit-depth(位深):用來描述存儲數字信號值的bit數。較常用的模擬信號位深有:

8-bit:2^8 = 256 levels,有256個等級可以用於衡量真實的模擬信號。
16-bit:2^16 = 65,536 levels,有65,536個等級可以用於衡量真實的模擬信號。
24-bit:2^24 = 16,666,216 levels,有16,666,216個等級可以用於衡量真實的模擬信號。
顯而易見,位深越大,對模擬信號的描述將越真實,對聲音的描述更加準確。

在當前例子中,如果用爲8-bit位深來描述的話,就如下圖所示:
在這裏插入圖片描述
量化的過程就是將一個平頂樣本四捨五入到一個可用最近level描述的過程。如圖中黑色加粗梯形折線。量化過程中,我們將盡量讓每個採樣和一個level匹配,因爲每個level都是表示一個bit值。

圖中,第9次採樣的平頂樣本對應的level用十進制表示爲255,也就是二進制的1111 1111。

11.2.4 Encoding(編碼)

在這裏插入圖片描述
在編碼這一步,我們會將時間線上的每個sample數據轉化爲對應的二進制數據。

採樣數據經過編碼後產生的二進制數據,就是PCM數據。PCM數據可以直接存儲在介質上,也可以在經過編解碼處理後進行存儲或傳輸。

11.2.5 PCM數據常用量化指標

採樣率(Sample rate):每秒鐘採樣多少次,以Hz爲單位。詳見:**採樣率(Sample rate)**一節。

位深度(Bit-depth):表示用多少個二進制位來描述採樣數據,一般爲16bit。詳見:**Quantization(量化)**一節。

字節序:表示音頻PCM數據存儲的字節序是大端存儲(big-endian)還是小端存儲(little-endian),爲了數據處理效率的高效,通常爲小端存儲。

聲道數(channel number):當前PCM文件中包含的聲道數,是單聲道(mono)、雙聲道(stereo)?此外還有5.1聲道等。

聲道佈局:立體聲,低音炮(2.1聲道),5.1環繞立體聲

採樣數據是否有符號(Sign):要表達的就是字面上的意思,需要注意的是,使用有符號的採樣數據不能用無符號的方式播放。

以FFmpeg中常見的PCM數據格式s16le爲例:它描述的是有符號16位小端PCM數據。

s表示有符號,16表示位深,le表示小端存儲。

比特率:沒有壓縮的音頻數據的比特率 = 採樣頻率 * 採樣精度 * 通道數。

碼率:壓縮後的音頻數據的比特率,常見的碼率有:
在這裏插入圖片描述
:音頻的幀的概念沒有視頻幀那麼清晰,幾乎所有視頻編碼格式都可以簡單的認爲一幀就是編碼後的一張圖像。
幀長:
(1)可以指每幀採樣數播放的時間,mp3 48K,1152個採樣點,每幀則爲24ms;aac則是每幀是1024個採樣點。攢夠一幀的數據才送去做編碼。
(2)也可以指壓縮後每幀的數據長度,所以需要注意。

每幀持續時間(秒)=每幀採樣點數/採樣頻率(hz)

11.2.6 PCM數據流

如果是單聲道的音頻文件,採樣數據按時間的先後順序依次存入(有的時候也會採用LRLRLR方式存儲,只是另一個聲道的數據爲0),如果是雙聲道的話就按照LRLRLR的方式存儲,存儲的時候還和機器的大小端有關。大端模式如下圖所示:
在這裏插入圖片描述

如果我們有一個PCM文件,在代碼中,我們可以通過以下方式來讀取這樣的PCM數據流(Stream)。

FILE *file
int8_t *buffer;
file = fopen("PCM file path");
buffer = malloc(fileSize);
fread(buffer, sizeof(int8_t), fileSize / sizeof(int8_t), file);

僞代碼僅僅表示一種加載方式。但在代碼中,一開始就將整個文件加載到了內存中,這是不對的。因爲我們的音頻數據量往往會比較大,一次性全部加載增加了內存負擔,而且並不必要。

通常我們會爲buffer分配一個固定的長度,例如2048字節,通過循環的方式一邊從文件中加載PCM數據,一邊播放。

加載好PCM數據後,需要送到音頻設備驅動程序中播放,這時我們應該能聽到聲音。與PCM數數據一同到達驅動程序的通常還有采樣率(sample rate),用來告訴驅動每秒鐘應該播放多少個採樣數據。如果傳遞給驅動程序的採樣率大於PCM實際採樣率,那麼聲音的播放速度將比實際速度快,反之亦然。

存儲方式可能還有交錯和非交錯的方式:
在這裏插入圖片描述

不同的驅動程序對於多聲道數據的排列方式可能稍有區別,下面是常用的聲道排列地圖:

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)

11.2.7 音量控制

音量的表示實際上就是量化過程中每個採樣數據的level值,只要適當的增大或者縮小採樣的level就可以達到更改音量的目的。

但需要說明的是,並是不將level值*2就能得到兩倍於原聲音的音量。

因爲如下兩個原因:

  1. 數據溢出:
    我們都知道每個採樣數據的取值範圍是有限制的,例如一個signed 8-bit樣本,取值範圍爲-128~128,值爲125時,放大兩倍後的值爲250,超過了可描述的範圍,此時發生了數據溢出。這個時候就需要我們做策略性的裁剪處理,使放大後的值符合當前格式的取值區間。

如下僞代碼描述了signed 8-bit格式的聲音放大兩倍的裁剪處理:

int16_t pcm[1024] = read in some pcm data;
int32_t pcmval;
for (ctr = 0; ctr < 1024; ctr++) {
    pcmval = pcm[ctr] * 2;
    if (pcmval < 128 && pcmval > -128) {
        pcm[ctr] = pcmval
    } else if (pcmval > 128) {
        pcm[ctr] = 128;
    } else if (pcmval < -128) {
        pcm[ctr] = -128;
    }
}
  1. 對數描述:
    平時表示聲音強度我們都是用分貝(db)作單位的,聲學領域中,分貝的定義是聲源功率與基準聲功率比值的對數乘以10的數值。根據人耳的心理聲學模型,人耳對聲音感知程度是對數關係,而不是線性關係。人類的聽覺反應是基於聲音的相對變化而非絕對的變化。對數標度正好能模仿人類耳朵對聲音的反應。所以用分貝作單位描述聲音強度更符合人類對聲音強度的感知。前面我們直接將聲音乘以某個值,也就是線性調節,調節音量時會感覺到剛開始音量變化很快,後面調的話好像都沒啥變化,使用對數關係調節音量的話聲音聽起來就會均勻增大。

如下圖所示,橫軸表示音量調節滑塊,縱座標表示人耳感知到的音量,圖中取了兩塊橫軸變化相同的區域,音量滑塊滑動變化一樣,但是人耳感覺到的音量變化是不一樣的,在左側也就是較安靜的地方,感覺到音量變化大,在右側聲音較大區域人耳感覺到的音量變化較小。
在這裏插入圖片描述

這就需要對音量值的乘數係數合理取值。具體如何取值,請參考非常專業的一篇文章:PCM音量控制

11.2.8 採樣率調整

採樣率的定義爲:每秒鐘採樣次數。而降低增加採樣率只需要以固定的頻率複製或者丟棄採樣數據即可。

如10Hz表示每秒鐘採樣10次,我們只需要將2*n(n爲從0開始的值)處的採樣數據捨棄,就可以得到10/2 = 5Hz的採樣數據。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章