pcm格式封裝wav

PCM

PCM編碼是直接存儲聲波採樣被量化後所產生的非壓縮數據,故被視爲單純的無損耗編碼格式,其優點是可獲得高質量的音頻信號。
PCM是模擬音頻信號經模數轉換(A/D變換)直接形成的二進制序列,該文件沒有附加的文件頭和文件結束標誌。
PCM
要將這樣的信號轉爲 PCM 時,需要將聲音量化,我們一般從如下幾個維度描述一段聲音:

1.聲道數  2.採樣位數  3.採樣頻率  4.時長

採樣頻率:即取樣頻率,指每秒鐘取得聲音樣本的次數。採樣頻率越高,聲音的質量也就越好,聲音的還原也就越真實,但同時它佔的資源比較多。由於人耳的分辨率很有限,太高的頻率並不能分辨出來。在16位聲卡中有22KHz、44KHz等幾級,其中,22KHz相當於普通FM廣播的音質,44KHz已相當於CD音質了,目前的常用採樣頻率都不超過48KHz。
採樣位數:即採樣值或取樣值(就是將採樣樣本幅度量化)。它是用來衡量聲音波動變化的一個參數,也可以說是聲卡的分辨率。它的數值越大,分辨率也就越高,所發出聲音的能力越強。
聲道數:很好理解,有單聲道和立體聲之分,單聲道的聲音只能使用一個喇叭發聲(有的也處理成兩個喇叭輸出同一個聲道的聲音),立體聲的PCM 可以使兩個喇叭都發聲(一般左右聲道有分工) ,更能感受到空間效果。
時長: 採樣時長

WAV

WAV爲微軟公司(Microsoft)開發的一種聲音文件格式,它符合RIFF(Resource Interchange File Format)文件規範,用於保存Windows平臺的音頻信息資源,被Windows平臺及其應用程序所廣泛支持,該格式也支持MSADPCM,CCITT A LAW等多種壓縮運算法,支持多種音頻數字,取樣頻率和聲道,標準格式化的WAV文件和CD格式一樣,也是44.1K的取樣頻率,16位量化數字,因此在聲音文件質量和CD相差無幾。
WAVE是錄音時用的標準的WINDOWS文件格式,文件的擴展名爲“WAV”,數據本身的格式爲PCM或壓縮型,屬於無損音樂格式的一種。
Wav File符合 RIFF(Resource Interchange File Format)規範。所有的WAV都有一個文件頭,這個文件頭音頻流的編碼參數。數據塊的記錄方式是little-endian字節順序,標誌符並不是字符串而是單獨的符號。
基於PCM編碼的WAV格式是最基本的WAV格式,被聲卡直接支持,能直接存儲採樣的聲音數據,所存儲的數據能直接通過聲卡播放,還原的波形曲線與原始聲音波形十分接近,播放的聲音質量是一流的,在Windows平臺下被支持得最好,常常被用作在其它編碼的文件之間轉換的中間文件。PCM的缺點是文件體積過大,不適合長時間記錄。正因爲如此,又出現了多種在PCM編碼的基礎上經改進發展起來的編碼格式,如:DPCM,ADPCM編碼等。

WAV和PCM的關係

前面也介紹到了,PCM 數據本身只是一個裸碼流,它是由聲道、採樣位數、採樣頻率、時長共同決定的,因此我們至少要知道其中的三個才能將 PCM 所代表的數據提取出來。因此,純PCM數據是無法播放的,因此還需要一段描述數據。計算機系統中的一個比較常見的做法是將PCM碼流和描述信息封裝在一起,形成一個音頻文件。這樣就可以直接播放了。一種常見的方式是使用wav格式定義的規範將PCM碼流和描述信息封裝起來。查看 PCM 和對應wav文件的 hex(16進制)文件,可以發現,wav文件只是在PCM文件的開頭多了44字節,來表徵其聲道數、採樣頻率和採樣位數等信息。這個其實和bmp非常類似。

經常見到這樣的描述: 44100HZ 16bit stereo 或者 22050HZ 8bit mono 等等.
44100HZ 16bit stereo: 每秒鐘有 44100 次採樣, 採樣數據用 16 位(2字節)記錄, 雙聲道(立體聲);
22050HZ 8bit mono: 每秒鐘有 22050 次採樣, 採樣數據用 8 位(1字節)記錄, 單聲道;
每個採樣數據記錄的是振幅, 採樣精度取決於儲存空間的大小:
1 字節(也就是8bit) 只能記錄 256 個數, 也就是隻能將振幅劃分成 256 個等級;
2 字節(也就是16bit) 可以細到 65536 個數, 這已是 CD 標準了;
4 字節(也就是32bit) 能把振幅細分到 4294967296 個等級, 實在是沒必要了.
如果是雙聲道(stereo), 採樣就是雙份的, 文件也差不多要大一倍。

WAV格式頭實現

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * WavHeader輔助類,用於生成頭部信息
 */
public class WavHeader {
    public final char fileID[] = {'R', 'I', 'F', 'F'};
    public int fileLength = 0;
    public char wavTag[] = {'W', 'A', 'V', 'E'};
    public char FmtHdrID[] = {'f', 'm', 't', ' '};
    public int FmtHdrLeth = 16;
    public short FormatTag = 1;
    public short Channels = 1;
    public int SamplesPerSec = 44100;
    public int AvgBytesPerSec = 88200;
    public short BlockAlign = 2;
    public short BitsPerSample = 16;
    public char DataHdrID[] = {'d','a','t','a'};
    public int DataHdrLeth = 0;
    public byte[] getHeader() throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        WriteChar(bos, fileID);
        WriteInt(bos, fileLength);
        WriteChar(bos, wavTag);
        WriteChar(bos, FmtHdrID);
        WriteInt(bos,FmtHdrLeth);
        WriteShort(bos,FormatTag);
        WriteShort(bos,Channels);
        WriteInt(bos,SamplesPerSec);
        WriteInt(bos,AvgBytesPerSec);
        WriteShort(bos,BlockAlign);
        WriteShort(bos,BitsPerSample);
        WriteChar(bos,DataHdrID);
        WriteInt(bos,DataHdrLeth);
        bos.flush();
        byte[] r = bos.toByteArray();
        bos.close();
        return r;
    }
    private void WriteShort(ByteArrayOutputStream bos, int s) throws IOException {
        byte[] mybyte = new byte[2];
        mybyte[1] =(byte)( (s << 16) >> 24 );
        mybyte[0] =(byte)( (s << 24) >> 24 );
        bos.write(mybyte);
    }

    private void WriteInt(ByteArrayOutputStream bos, int n) throws IOException {
        byte[] buf = new byte[4];
        buf[3] =(byte)( n >> 24 );
        buf[2] =(byte)( (n << 8) >> 24 );
        buf[1] =(byte)( (n << 16) >> 24 );
        buf[0] =(byte)( (n << 24) >> 24 );
        bos.write(buf);
    }
    private void WriteChar(ByteArrayOutputStream bos, char[] id) {
        for (int i=0; i<id.length; i++) {
            char c = id[i];
            bos.write(c);
        }
    }
}

參考鏈接:
https://www.jianshu.com/p/638fa13082eb
https://www.cnblogs.com/ranson7zop/p/7657874.html
https://www.cnblogs.com/wanggang123/p/5589488.html
https://blog.csdn.net/zhuweigangzwg/article/details/51499123

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