pcm混音的一種方式


轉載

混音:

Mix的意思是混音,無論在自然界,還是在音頻處理領域這都是非常普遍的現象。自然界里你能同時聽到鳥鳴和水聲,這是因為鳥鳴和水聲的波形在空氣中形成了疊加,耳朵聽到后能區分鳥鳴和水聲這兩種波形。
在數字音頻領域也是一樣,比如你也可以一邊打CS一邊聽歌,這是因為計算機把兩個聲音波形做了疊加。但是不同的是,計算機中的疊加,很容易造成越界。
比如
          int plus1(int num0, int num1){
                                                        return num0+num1;
                                                        }
如果賦值int num0=0x70000000和int num1=0x70000000,運行后的result是0xE0000000,變換為十進制為-536870912。兩個正數相加得到了負數,結果自然是錯的。
我們知道,一個char的補碼所能表示的數值范圍是[-128, 127],寫成16進制是[0x80,0x7F]。而一個int的補碼的范圍是[0x80000000,0x7FFFFFFF]。超出這個范圍就是溢出。
如何防止溢出呢?最簡單的做法是拓寬存儲數據的容器,比如:
                    long long plus1(int num0, int num1){
                                                                   return (long long)num0+(long long)num1;
                                                                           }
賦值int num0=0x70000000和int num1=0x70000000,運行后的result是0xE0000000,變換為十進制為3758096384。這次沒有溢出。

 


 公式
怎么能做到不溢出呢?考慮這個公式
          Z=A+B−AB,
如果A和B都在[0,1]范圍內,那么:
    0<=(1-A)(1-B)=1-A-B+AB<=1,那么
          0<=Z<=1
這樣,如果我們把A,B看做是兩個輸入波形,Z看做是一個輸出波形的話,Z的上界和下界也在A和B的上界和下界內。也就是說,Z是不會溢出的。
對於3個輸入信號來說,按照(1-A)(1-B)(1-C)運算,易得
      Z=A+B+C−AB−AC−BC+ABC.
而對於取值范圍不在[0,1]的信號,可以先轉化為[0,1]來做。
比如A,B均在[0,255]范圍內,則A/255在[0,1]內,則
          Z/255=A/255+B/255-(A/255)*(B/255),那么
                  Z=A+B-AB/255
對於有符號的數,取值范圍在[-128,127],則A’=(A+128)/255取值在[0,1]內,則
Z’=A’+B’−A’*B’,代入可得
(Z+128)/255=(A+128)/255+(B+128)/255-(A+128)/255*(B+128)/255,則
Z=A+B-(A+128)(B+128)/255+128
這種算法可以認為是簡單的對輸入信號進行了相加,並為了避免溢出,壓縮了兩個信號的和的波形。但是這種算法有個致命的缺點,那就是當兩個信號相加沒有溢出時,這種算法仍然壓縮了波形,導致音質受損。而且過多的加減乘除的運算,會提升整個系統的功耗和復雜性,也會在四舍五入中降低數據的精度。
說句題外話,為了避免運算中聲音信號精度的丟失,目前業界高端音頻處理系統里都是用32位float采樣來進行運算的,而輸出的時候轉化為16bit。
————————————————
版權聲明:本文為CSDN博主「我把葡萄釀成酒」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ffmpeg4976/article/details/45599467


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM