1.引言?
將多個Wave文件或多路Wave數據同時在Wave設備上輸出,就可同時聽到多個不同的聲音,達到混音的效果。如果是將多個不同端點的話音數據經局域網絡傳輸到達某一個端點再經該端點的Wave設備輸出,就能同時聽到多個人的話音,從而實現局域網絡中多方的話音交談。?
在網絡上實現話音交談,特別強調實時性,要儘量保證話音的平滑、連續,因此爲了保證話音數據連續,減少話音數據存儲帶來的延時,在具體實現中,話音的錄製和播放都不採用文件的形式,錄製和播放的話音數據都存在緩衝區中。在Windows系統中,一般情況下,高層Wave接口函數無法直接播放緩衝區中的話音數據,而必須用底層函數來實現,常用的是Windows API中的Wave函數。將Wave數據在Wave設備上輸出使用的是WaveOutWrite函數,但是該函數不支持多路Wave數據的同時播放,爲了能達到多路Wave數據同時播放的效果,對緩衝區中多路Wave數據進行必要的預處理後,再提交給Wave輸出設備播放。實現原理如圖1所示。?
圖1 多路Wave混音的實現原理
2.實現原理?
實時地混音,就是將多路Wave數據進行相互疊加處理到另一個目的緩衝區,最終將該目的的緩衝區提交給Wave輸出設備。?
將每一路Wave數據作爲一個單獨通道,分別從每個通道取一數據片段,把取得的幾個數據片段相互疊加,然後存進另外一個目的緩衝區中。爲了便於處理,緩衝區通常採用數組的形式存放Wave數據。
如果話音數據,採用採樣頻率1025Hz,8位單聲道的數據格式,那麼一秒的話音數據量爲11025個字節。?
爲了達到實時的效果,目的緩衝區通常都設置比較小,大約可存放1/8秒的話音數據量,對於前述的話音格式,目的緩衝區的大小爲11025/8=1375個字節。?
下面具體看一下Wave數據以數組形式存放時的混音過程。如圖2所示。
圖2 多路Wave數據的疊加過程
假設有4路Wave數據,目的緩衝區的大小爲1378,混音子函數調用爲 Mixer(lpDest,rgpCDdata,4,1378)。?
下面給出混音子函數的實現。其中lpDest爲目的緩衝區,rgWaveSrc爲多路Wave數據源,iNumWaves爲Wave數據源的通道數,wLen爲目的緩衝區長度。?
Void mixit(LPSAMPLE lpDest,LPSAMPLE rgWaveSrc[],intiNumWaves,WORDwLen)?
{?int,,iSum;?
WORD ctr;
ctr=0?
While(wLen)?
{?
iSum=128;/?*靜音時數值爲128?*/?
for(I=0;I<iNumWaves;I )?
iSum=iSum *(rgWaveSrc[] ctr)-128;?
PEG(int)0,iSum,(int)225);/*對轉換結果處理?*/?
*lpDest =iSum;?
ctr ;?
wLen--;?
}?
}
注意一點的是對於單聲道數據一個字節表示一個採樣值,採樣值在0-255之間,各個通道的對應Wave數據相加後,就會溢出,還需要將相加結果轉換成0-255之間的數值。?
將該目的緩衝區中的Wave數據經WaveOutWrite函數輸出,就能同時聽到四個不同的聲音,當Wave輸出設備播放完目的緩衝區中的數據便返回,請求用戶提供更多的Wave輸出數據,因爲Wave輸出設備只能輸出提交給它的Wave數據;另外,對Wave數據進行混音還需要一定的時間,因此當提交一個目的緩衝區中的數據給Wave輸出設備後,就必須馬上混疊另一段Wave數據來提交給Wave輸出設備,作爲下一個輸出的數據緩衝區,避免聲音輸出的.中斷,後一個目的緩衝區提交後被輸出設備放入輸出隊列中,當第一個目的緩衝區中輸出完畢後再輸出它的數據,當輸出設備在輸出第二個目的緩衝區的數據時,又能將第三段數據混合進第一個目的緩衝區中,然後重新提交,直到提交完所有的Wave數據,那時就將停止輸出。在實際應用中目的緩衝區的數要多個,一般爲3至4個,圖3給出了混音、提交的完整過程。