日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

MMIO----Wav格式文件解析

發布時間:2023/12/15 综合教程 39 生活家
生活随笔 收集整理的這篇文章主要介紹了 MMIO----Wav格式文件解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

DirectSound只支持Wav格式的音頻文件,在創建次緩沖區之前需要先確定播放的Wav音頻數據的格式。如果是從本地Wav文件播放,則需要先讀出它的數據格式。

1. Wav音頻格式布局

Wav是WAVE音頻格式文件的后綴名,WAVE音頻格式全稱是Waveform Audio File Format,又叫波形文件。這是一種微軟和IBM合理推出的音頻比特流文件格式,是RIFF(Resource Interchange File Format)文件格式的一種特殊應用。

RIFF使用一種叫做Chunk的數據塊來存儲各種信息,主要分為兩部分:RIFF ChunkOther Chunk

RIFF Chunk:

Chunk id: chunk標識符,值為FOURCC('R', 'I', 'F', 'F')組成的一個32位的無符號整數。
file size: 4字節大小,file typedata部分的數據大小總和。
file type: 用FOURCC標識的文件類型,對于Wav文件來說值為FOURCC('W', 'A', 'V', 'E')。
data: 該部分包含剩余的chunk塊。

Other Chunk按順序包含3個部分:

Chunk id:這是每個chunk的標識符,是由4個字符組成一個FOURCC。
Chunk size:4字節值,表明該chunk塊數據部分的大小。
Chunk data:數據部分,該數據可能為空,并且實際的數據會被填充到2字節邊界

對于Wav音頻文件來說,常見并被稱為標準格式的Wav格式的只包含“RIFF”、“fmt”和“data” chunk 塊(今天我們不討論格式標準,因此不深入探討這方面),只有“data”子塊中的data部分包含實際的音頻數據,可以被用來播放。實際上整個RIFF文件只由一個“RIFF”塊組成,而該“RIFF”又包含其他子塊(例如“fmt”、“data”塊)。由于Wav文件可能包含其他子塊,因此在解析的時候不能假定這些字塊的順序。

2.Wav音頻數據格式

Wav音頻的數據格式信息包含在“fmt”塊中,“fmt”字塊的data部分就包含數據的格式信息。Wav文件多包含的是PCM( Pulse -code modulation)原始音頻數據,即未經壓縮的數據,但其實它可以包含多種數據格式,包括原始的和經過壓縮的:

PCM

ADPCM

GSM

MP3

CELP

SBC

Truespeech

我們這里只處理PCM原始數據,因為DirectSound只支持它。我們看下圖:

在Windows平臺上開發時,系統已經為我們定義好了數據格式用來存儲Wav格式信息WAVEFORMATEX,可以看到這個結構體的字段除cbSize以外都是按順序和“fmt”塊中data部分的格式信息字段一一對應的,這極大地方便了我們對格式信息的處理。

3. 讀取Wav音頻格式信息

HMMIO mmioOpen(LPTSTR szFilename, LPMMIOINFO lpmmioinfo, DWORD dwOpenFlags);
MMRESULT mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT wFlags);
MMRESULT mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, LPMMCKINFO lpckParent, UINT wFlags);
LONG mmioRead(HMMIO hmmio, HPSTR pch, LONG cch);
...

微軟提供了mmio系列的函數來幫助我們操作RIFF文件,首先我們調用mmioOpen打開一個Wav文件并防止被其他程序寫入:

HMMIO mmioHandle = mmioOpenW(tempFilePath, NULL,
                            MMIO_READ |
                            MMIO_DENYWRITE |
                            MMIO_ALLOCBUF);
if (mmioHandle == NULL) {
    throw std::exception("mmioOpon error!");
}

然后我們調用mmioDescend函數下降到RIFF塊,通過在MMCKINFO結構體中設置file type為FOURCC('W', 'A', 'V', 'E'),我們表明我們想下降到的RIFF塊里的文件類型是“WAVE”:

MMCKINFO riffChunkInfo;
riffChunkInfo.fccType = mmioFOURCC('W', 'A', 'V', 'E');
DWORD as;
if ((as = mmioDescend(mmioHandle, &riffChunkInfo, NULL, MMIO_FINDRIFF))
        !=
    MMSYSERR_NOERROR) {

    throw std::exception("mmioDescend error!");
}

因為“fmt”塊是RIFF的子塊,因此我們緊接著下降到“fmt”子塊:

MMCKINFO fmtSubChunkInfo;
fmtSubChunkInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
if (mmioDescend(mmioHandle, &fmtSubChunkInfo, &riffChunkInfo, MMIO_FINDCHUNK)
        !=
    MMSYSERR_NOERROR) {

    throw std::exception("mmioDescend error!");
}

然后我們調用mmioRead函數來讀取格式信息到一個WAVEFORMATEX結構體中。調用mmioRead時,我們需要自己提供存放讀取信息的地址,像這里我們提供的是一個棧上的變量地址:

//  `fmt` chunk contains wave audio format described by WAVEFORMAT or WAVEFORMATEX
if (mmioRead(mmioHandle, (HPSTR)&m_waveFormat, fmtSubChunkInfo.cksize)
        <= 0) {

    throw std::exception("mmioRead read fmt chunk error!");
}

4. 運行結果

完整代碼見鏈接

總結

以上是生活随笔為你收集整理的MMIO----Wav格式文件解析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。