PCM音頻數據格式介紹


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?

單聲道:

  1.  
    +------+------+------+------+------+------+------+------+------+
  2.  
    | 500 | 300 | -100 | -20 | -300 | 900 | -200 | -50 | 250 |
  3.  
    +------+------+------+------+------+------+------+------+------+
  • 1
  • 2
  • 3

每個整數占據2個字節(16-bit),9個采樣也就是18字節的數據。每個采樣的整數大小最小為 -32768,最大為 32768 。根據采樣數據的位置和值畫一個圖的話,就會得到像播放器上那樣的波浪形圖。

我們可以像下面偽代碼示例這樣將數據讀入一個C語言數組 :

  1.  
    FILE *pcmfile
  2.  
    int16_t *pcmdata;
  3.  
    pcmfile = fopen(your pcm data file);
  4.  
    pcmdata = malloc( size of the file);
  5.  
    fread(pcmdata, sizeof(int16_t), size of file / sizeof(int16_t), pcmfile);
  • 1
  • 2
  • 3
  • 4
  • 5

如果我們將這些數據送入聲卡,我們就可以聽到聲音。當然我們需要告訴聲卡這些數據的采樣率。若我們告知聲卡的采樣率大於數據本身的采樣率,那么這些數據的播放速度會高於其原始的速度。就是快放的功能。

立體聲:

  1.  
    +----------+----------+---------+----------+---------+----------+---------+----------+----------+
  2.  
    | LFrame1 | RFrame1 | LFrame2 | RFrame2 | LFrame3 | RFrame3 | LFrame4 | RFrame4 | LFrame5 |
  3.  
    +----------+----------+---------+----------+---------+----------+---------+----------+----------+
  • 1
  • 2
  • 3

每一個frame是一個16-bit的采樣點。左右聲道的數據交叉存放。

3. Basic Audio Effects – Volume Control

現在讓我們來看一下一些真實的波形圖。最簡單的就是正弦波了。 
這里寫圖片描述

我們將波形的振幅擴大五倍,圖形如下: 
這里寫圖片描述

所以如果要增加PCM數據的音量,只需要將每一個采樣的數據乘以一個系數就行了。如果我們的PCM數據有2048個字節,則包含了1024個采樣。我們用如下的偽代碼來擴大音量 :

  1.  
    int16_t pcm[ 1024] = read in some pcm data;
  2.  
    for (ctr = 0; ctr < 1024; ctr++) {
  3.  
    pcm[ctr] *= 2;
  4.  
    }
  • 1
  • 2
  • 3
  • 4

音量控制就是這么簡單,但是要注意兩點:

  1. 若采樣點的數據乘以擴大系數之后的值 小於 -32768 或 大於 32768 ,則此處采樣的數值只能取 -32768 或 32768
  1.  
    int16_t pcm[ 1024] = read in some pcm data;
  2.  
    int32_t pcmval;
  3.  
    for (ctr = 0; ctr < 1024; ctr++) {
  4.  
    pcmval = pcm[ctr] * 2;
  5.  
    if (pcmval < 32767 && pcmval > -32768) {
  6.  
    pcm[ctr] = pcmval
  7.  
    } else if (pcmval > 32767) {
  8.  
    pcm[ctr] = 32767;
  9.  
    } else if (pcmval < -32768) {
  10.  
    pcm[ctr] = - 32768;
  11.  
    }
  12.  
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  1. 我們將采樣點的數據乘以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的音頻? 
我們需要以下幾步:

    1. 將opus解碼為PCM格式數據(叫做PCM1),此時的PCM1的采樣率為48kHz
    2. 將PCM1的數據中第 3*n(n為從0開始的自然數) 個位置的采樣點,丟棄3*n+1 和3*n+2位置的采樣點。得到PCM2,此時的PCM2采樣率為48kHz / 3 = 16kHz
    3. 將PCM2編碼為speex數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM