天天看點

Windows基礎-實時錄音程式(WaveXXX)寫在前面 使用MMAPI(WaveXxxAPI) 使用MCI(字元串指令)

錄音無非兩種需求: 

       1. 非實時獲得音頻,也就是停止錄音了你才需要處理它; 

       2. 實時擷取音頻,比如QQ電話這種這邊講話那邊馬上就聽到的。 

       後者實作起來比較啰嗦,但也很定式。既然啰嗦那就乖乖地寫成類吧,管别的大仙怎麼說你low呢 ( ͡° ͜ʖ ͡°) 。 

Windows基礎-實時錄音程式(WaveXXX)寫在前面 使用MMAPI(WaveXxxAPI) 使用MCI(字元串指令)

Windows API 可用的實作方式

用處

Windows Multimedia API(WaveXxxAPI)

定式且啰嗦地實作音頻流的實時擷取。

Media Control Interface (MCI)

讓你簡單地用字元串指令實作錄音和放音

——MMAPI可以讓你通路音頻裝置的緩沖區,發揮比較自由,接近系統底層。 

——MCI是發送字元串指令給這個界面,内部的無法幹涉,記得《少年電腦世界》之類的雜志教你打開關閉光驅什麼的就是用寫一行 

          <code>mciSendString("set cdaudio door open",NULL,0,NULL);//關閉把open改為close</code>。 

          注意:MCI簡稱媒體控制接口,較為高層,為的是讓你不用關心裝置的具體操作,快速上手,簡單地操作多媒體裝置。WaveXxxAPI是接近底層的應用程式接口,為的是靈活地控制裝置,但裝置的操作還是比較定式的,靈活在于裝置狀态配置和資料處理的時機,是以M$給你了兩個控制方式。

       用MMAPI的估計都是想實時獲得音頻資料的,MMAPI可以把音頻流緩沖起來并一塊一塊地發送給你,在這裡我們暫把這種固定大小的音頻裸資料簡稱為AudioFrame(資料塊,代碼中别名叫ChunkData)。這一塊資料需要你一次性處理完(你甚至需要轉移這個資料到另一個線程以保證緩沖區讀寫的穩定性),資料有多少位元組可以根據實際情況來設定。在性能和延遲之間均衡考慮一下,200ms的資料可以應付大多數情況。 

       PS:用過Kinect V2麥克風的同學對此應該比有印象,AudioFrame顧名思義,音頻幀。

       MMAPI的操作十分定式: 

       開始錄音的流程為:以一種格式打開波形輸入裝置,發送WIM_OPEN消息給回調函數,準備緩沖區,添加緩沖區到裝置,告訴裝置錄音開始; 

       錄音期間循環發送WIM_DATA給回調函數; 

       結束錄音的流程為:告訴裝置錄音結束并發送WIM_DATA給回調函數讓它處理最後的資料,重置錄音裝置,釋放緩沖區,至此可以重新設定緩沖區到裝置并開始新的錄音,關閉裝置并發送WIM_CLOSE給回調函數。 

       關于MMAPI的回調函數: 

       這個回調函數是來處理消息的,一開始收到WIM_OPEN,最後收到WIM_CLOSE唯一頻繁收到的消息是WIM_DATA,得到這個消息時我們需要轉移緩沖區裡的資料并把緩沖區壓入到裝置緩沖隊列中,你可以了解為自動pop手動push。 

       我寫的類裡面的回調函數是屬于這個回調函數的,阻塞的話還是會直接影響MMAPI的回調函數 

       這裡用到雙緩沖乃至多緩沖技術: 

       假設一個實時接水的任務,聽起來奇怪但與MMAPI的處理流程相似,這裡需要你用杯子連續接水,杯子相當于你開辟的緩沖區: 

       根據上面的​流程,你的身份是MMAPI的回調函數,在飲水機面前要拿着杯子執行這個任務:任務的基本名額是滴水不漏地連續用杯子把水接到一個存儲區域裡,你要接指定量的水,還要負責轉移走這杯水。為了能騰出時間把水倒在存儲區域裡,你肯定需要用不止一個杯子輪流接水。飲水機有一個功能:每當杯子灌滿後,飲水機會通知你,并自動去接下一個杯子,如果後面沒有杯子則終止任務。(不會講故事的我啊TT,這個奇葩例子能看懂就行)可以見得:1.你會被及時地通知去轉移資料2.緩沖區用完了要及時放回緩沖區隊列後端以保證任務能夠繼續3.如果轉移并處理資料的時間不是很穩定,你可能需要準備多個緩沖區而不是單純增加緩沖區容量,為的是確定任務中能夠預留足夠多的容忍時間供你使用。 

       這裡的多緩沖技術淺顯地解釋就是多個緩沖區排成一個隊列(或者了解為放成一摞)來抵消這個任務中那些耗時不穩定的處理過程對整個實時處理任務的連續性帶來的負面影響。其實生活中有很多事情也是用到多緩沖這個概念。

    這一部分我把自己寫的類裡面的函數拿了出來,完整代碼請見連結,免下載下傳積分。

    需要添加:

    檢查一下是否有音頻輸入裝置:

     寫一個WaveXxxAPI的回調函數:

     配置Wave波形格式:

     嘗試打開輸入裝置并準備緩沖區:

     這時我們可以幹其他的事情,因為錄音階段所有的資料都由剛設定的回調函數處理:

     停止錄制:

     我們還可以寫入wav檔案儲存起來

    自己很倉促地寫了一個WaveRecorder類,想直接用的可以回到頂部下載下傳,可以滿足大多數人的需求,但裡面用到了STL。 

    MMAPI的實時擷取音頻資料的實作就寫到這

MCI看起來比較文藝(笑),用起來也是簡單到幾句話而已,雖然是非實時的,但是行數跟MMAPI差距也太大了吧!

Windows基礎-實時錄音程式(WaveXXX)寫在前面 使用MMAPI(WaveXxxAPI) 使用MCI(字元串指令)

繼續閱讀