1. What is PCM?
PCM(Pulse-code-)是模擬信號以固定的采樣頻率轉換成數字信號后的表現形式。
Rate :
采樣頻率單位為:Hz。采樣頻率越高,音頻質量越好,占用空間也越大。
Sign :
音頻數據是否是有符號的。通常情況下都是有符號的。若是將有符號的數據當做無符號的數據來處理將會使聲音聽來很刺
Size :
表示每一個采樣數據的大小。通常該值為16-bit。
Byte :
字節序指的是-還是big-。表示音頻數據的存儲字節序。通常均為-。
of :
標識音頻是單聲道(mono,1 )還是立體聲(,2 )。
通過以上五個數據我們就可以描述一個PCM數據,播放一個PCM數據需要的就是以上五個數據。
2. What does a PCM look like?
單聲道:
+------+------+------+------+------+------+------+------+------+
| 500 | 300 | -100 | -20 | -300 | 900 | -200 | -50 | 250 |
+------+------+------+------+------+------+------+------+------+
每個整數占據2個字節(16-bit),9個采樣也就是18字節的數據。每個采樣的整數大小最小為 -32768,最大為 32768 。根據采樣數據的位置和值畫一個圖的話,就會得到像播放器上那樣的波浪形圖。
我們可以像下面偽代碼示例這樣將數據讀入一個C語言數組 :
FILE *pcmfile

int16_t *pcmdata;
pcmfile = fopen(your pcm data file);
pcmdata = malloc(size of the file);
fread(pcmdata, sizeof(int16_t), size of file / sizeof(int16_t), pcmfile);
如果我們將這些數據送入聲卡,我們就可以聽到聲音。當然我們需要告訴聲卡這些數據的采樣率。若我們告知聲卡的采樣率大于數據本身的采樣率,那么這些數據的播放速度會高于其原始的速度。就是快放的功能。
立體聲:
+----------+----------+---------+----------+---------+----------+---------+----------+----------+
| LFrame1 | RFrame1 | LFrame2 | RFrame2 | LFrame3 | RFrame3 | LFrame4 | RFrame4 | LFrame5 |
+----------+----------+---------+----------+---------+----------+---------+----------+----------+
每一個frame是一個16-bit的采樣點。左右聲道的數據交叉存放。
3. Basic Audio –
現在讓我們來看一下一些真實的波形圖。最簡單的就是正弦波了。
我們將波形的振幅擴大五倍常見音頻數據庫,圖形如下:
所以如果要增加PCM數據的音量,只需要將每一個采樣的數據乘以一個系數就行了。如果我們的PCM數據有2048個字節,則包含了1024個采樣。我們用如下的偽代碼來擴大音量 :
int16_t pcm[1024] = read in some pcm data;
for (ctr = 0; ctr < 1024; ctr++) {
pcm[ctr] *= 2;
}
音量控制就是這么簡單,但是要注意兩點:
若采樣點的數據乘以擴大系數之后的值 小于 -32768 或 大于 32768 ,則此處采樣的數值只能取 -32768 或 32768
int16_t pcm[1024] = read in some pcm data;
int32_t pcmval;
for (ctr = 0; ctr < 1024; ctr++) {
pcmval = pcm[ctr] * 2;
if (pcmval < 32767 && pcmval > -32768) {
pcm[ctr] = pcmval
} else if (pcmval > 32767) {
pcm[ctr] = 32767;

} else if (pcmval < -32768) {
pcm[ctr] = -32768;
}
}
我們將采樣點的數據乘以2并不代表將聲音的音量擴大了兩倍,事實上也的確如此。聲音音量的增益系數與音量的關系如圖:
以上內容翻譯自:
4. How to PCM Rate
根據定義, Rate表示每秒鐘的采樣個數,所以若是要改變音頻的采樣頻率,我們只需要對采樣點做適當的丟棄或者復制就可以。
比如:原始音頻為opus編碼,單聲道,采樣率為48kHz,采樣點大小為16-bit。如何得到編碼為speex,采樣率為16kHz,采樣大小為16-bit的音頻?
我們需要以下幾步:
將opus解碼為PCM格式數據(叫做PCM1)常見音頻數據庫,此時的PCM1的采樣率為48kHz將PCM1的數據中第 3*n(n為從0開始的自然數) 個位置的采樣點,丟棄3*n+1 和3*n+2位置的采樣點。得到PCM2,此時的PCM2采樣率為48kHz / 3 = 16kHz將PCM2編碼為speex數據