http://blog.csdn.net/ljxt523/article/details/52068241
1. What is PCM?
PCM(Pulse-code-modulation)是模擬信號以固定的采樣頻率轉換成數字信號后的表現形式。
Sample Rate :
采樣頻率單位為:Hz。采樣頻率越高,音頻質量越好,占用空間也越大。
Sign :
音頻數據是否是有符號的。通常情況下都是有符號的。若是將有符號的數據當做無符號的數據來處理將會使聲音聽來很刺
Sample Size :
表示每一個采樣數據的大小。通常該值為16-bit。
Byte Ordering :
字節序指的是little-endian還是big-endian。表示音頻數據的存儲字節序。通常均為little-endian。
Number of Channels :
標識音頻是單聲道(mono,1 channel)還是立體聲(stereo,2 channels)。
通過以上五個數據我們就可以描述一個PCM數據,播放一個PCM數據需要的就是以上五個數據。
2. What does a PCM stream look like?
單聲道:
-
+------+------+------+------+------+------+------+------+------+
-
| 500 | 300 | -100 | -20 | -300 | 900 | -200 | -50 | 250 |
-
+------+------+------+------+------+------+------+------+------+
- 1
- 2
- 3
每個整數占據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);
- 1
- 2
- 3
- 4
- 5
如果我們將這些數據送入聲卡,我們就可以聽到聲音。當然我們需要告訴聲卡這些數據的采樣率。若我們告知聲卡的采樣率大於數據本身的采樣率,那么這些數據的播放速度會高於其原始的速度。就是快放的功能。
立體聲:
-
+----------+----------+---------+----------+---------+----------+---------+----------+----------+
-
| LFrame1 | RFrame1 | LFrame2 | RFrame2 | LFrame3 | RFrame3 | LFrame4 | RFrame4 | LFrame5 |
-
+----------+----------+---------+----------+---------+----------+---------+----------+----------+
- 1
- 2
- 3
每一個frame是一個16-bit的采樣點。左右聲道的數據交叉存放。
3. Basic Audio Effects – Volume Control
現在讓我們來看一下一些真實的波形圖。最簡單的就是正弦波了。
我們將波形的振幅擴大五倍,圖形如下:
所以如果要增加PCM數據的音量,只需要將每一個采樣的數據乘以一個系數就行了。如果我們的PCM數據有2048個字節,則包含了1024個采樣。我們用如下的偽代碼來擴大音量 :
-
int16_t pcm[ 1024] = read in some pcm data;
-
for (ctr = 0; ctr < 1024; ctr++) {
-
pcm[ctr] *= 2;
-
}
- 1
- 2
- 3
- 4
音量控制就是這么簡單,但是要注意兩點:
- 若采樣點的數據乘以擴大系數之后的值 小於 -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;
-
}
-
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 我們將采樣點的數據乘以2並不代表將聲音的音量擴大了兩倍,事實上也的確如此。聲音音量的增益系數與音量的關系如圖:
以上內容翻譯自:http://www.ypass.net/blog/2010/01/pcm-audio-part-3-basic-audio-effects-volume-control/
4. How to change PCM Sample Rate
根據定義,Sample 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數據