一、最簡單的混音演算法 現在一般的軟體混音演算法是對輸入的音訊資料進行線性疊加, 即:
(1) 或者疊加以後再取平均值:
(2) 其中, m 為輸入音訊流的個數, n 為一幀的樣本數目, ·[i] 為一幀中的第i 個樣本, ·[j] 為第j 個音訊流, 所以, output[i] 為混音後的一幀中第i 個樣本, input[j][i] 為第j 個輸入音訊流當前幀的第i 個樣本(若經過編碼則輸入音訊流應在混音前通過解碼等還原成線性的PCM音訊流).通常的語音資料為16 bit(或者更少, 如8 bit), 即可以用C 語言中的short 類型表示, 其取值範圍是32768 ≤ 採樣值≤ 32767, 可以預想到多個音訊流直接線性疊加以後就有可能溢出, 所以式(1) 最後的結果可能會有溢出, 產生噪音.兩個連續平滑的波形疊加, 其結果也應該是平滑的. 所以產生噪音的地方就是由疊加溢出的地方引入的.我們需要採用濾波來處理這些溢出部分, 改善由於溢出所造成的品質下降.為了解決溢出的問題, 一個常用的方法就是使用更多的位數來表示音訊資料的一個樣本, 在混音完畢以後,再使用一些演算法來降低其振幅, 使其分佈在16 bit 所能表示的範圍之內, 這種方法叫做歸一化(Normalize). 通常使用32 bit 來表示線性疊加以後的資料, 也就是C 語言中的int 類型, 實現簡單, 運算也比較快, 更能滿足很多路音訊同時進行混音的需要. 式(2)對疊加的和值作平均, 解決了溢出的問題, 但是混音以後的聲音會總體衰減,特別是某一路音訊流的能量與其他路音訊流的能量反差很大的情況下, 音量非常小, 效果非常不理想. 進行濾波處理的另外一種常用方法就是“箝位”, 當發生上溢時, 箝位以後的值為所能表示的最大值, 當發生下溢時, 箝位後的值為所能表示的最小值, 如式(3) 所示:
(3) 其中, sample 為疊加以後的樣本值, 為 32 bit, MAX 是最大輸出值, 這裡為32767, MIN 為最小輸出值, 為32768. 現在很多現有的論文和系統都是採用箝位方法, 因為實現簡單, 快速, 效率很高. 但是可以看出, 這種箝位方法相當於在最大和最小的臨界值處切強行切斷波形, 非常生硬, 會造成較大的波形失真, 聽覺上引起如嘈雜, 出現突發刺耳的爆破音等.採用時域疊加作為基本的處理手段, 由於數位音訊信號存在量化上限和下限的問題,則因疊加運算肯定會造成結果溢出. 通常的處理手段是進行溢出檢測, 然後再進行飽和運算(如 4 式的方法), 即超過上限的結果被置為上限值, 超過下限的值置為下限值. 這種運算本身破壞了語音信號原有的時域特徵, 從而引入了雜訊. 這就是出現爆破聲和語音不連續現象的原因. 同時, 隨著參與混音的人數增加, 出現溢出的頻率也不斷上升, 所以這類方法存在一個上限, 而且這個上限值很低, 實驗證明, 採用這種時域直接疊加的方式進行混音, 一般不能突破 4 路輸入音訊流的限制, 否則將無法分辨語音流的內容了.
二、改進的混音演算法 混音的時候, 還需要遮罩某一路的本地音訊資料, 這樣就不會聽到本地的聲音, 只能聽到其他 n 1 路的聲音, 也就是說, 對於第 t 路音訊, 要發送給這個終端的混音後的資料如式(4):
(4) 以下提出的演算法主要思想就是使用一個衰減因數, 對音訊資料進行衰減, 衰減因數會隨著資料而變化. 當溢出時, 衰減因數比較小, 使溢出的音訊資料衰減以後處於臨界值以內, 當沒有溢出時, 衰減因數會慢慢增加, 儘量保持資料的平滑變化. 而不是對於整幀使用同一個衰減因數來進行, 這是不同于式(2) 和式(3) 的地方, 既保證了整體的聲強不至於衰減太快, 又保證了較小的失真度. 演算法如下所述:
留言列表