人聲消除的原理算法源碼及方案實現


原理

  在現在的喊麥上,人聲消除是常用的一個功能,筆者測試過幾款喊麥的系統,發現就人聲消除這塊,可以說效果是參差不齊。由於自己產品上也要有這個功能,就花了一些時間來研究了一下。下面就把研究的心得體會做個總結。
人聲的聲波波形在歌曲的兩個聲道是相同或者相似的,因此,我們可以采取兩個聲道相減的辦法來消除立體聲歌曲中的人聲。
一個標准的人聲消除過程如下:
步驟一:高通濾波器(High-pass filter)
步驟二:聲道混合(Channel Mixer)
步驟三:低通濾波器(Low-pass filter)
其實,高通和通過濾波器的作用就是盡量讓音樂的聲音保留。在實際的操作中,有些簡單的做法直接使用步驟2,省略到了步驟1和3,這樣做的好處是操作簡單,問題是人聲音消除的不是很干凈的。
我們一般把聲道混合分成四個參數,分別為:

  1. 新左聲道里原左聲道所占的百分數a1;
  2. 新左聲道里原右聲道所占的百分數a2;
  3. 新右聲道里原左聲道所占的百分數b1;
  4. 新右聲道里原右聲道所占的百分數b2;
    a1,a2,a3,a4這四個數的數值在-100到100之間。則新左聲道采樣值newLeft=a1Left/100+a2Right/100,新右聲道采樣值newRight=b1Left/100+b2Right/100。
    如果想消除80%的人聲,那么就將聲道混合的數值設定如下:
    100,-80, -80, 100;
    如果想消除50%的人聲,那么聲道混合的四個數值為:
    100, -50, -50, 100。
    如果想消除100%的人聲,那么聲道混合的四個數值為:
    100, -100, -100, 100。
    這樣,人聲消除就很清楚了,接下來就是算法實現了。

python源碼

  在這里,我用python做了一個簡單的仿真代碼,可以實現簡單的消除人聲的效果。具體代碼如下:

 1 import numpy as np
 2 from scipy.io import wavfile
 3 from scipy import signal
 4 
 5 def splitChannel(srcMusicFile):
 6    # read wav file
 7    sampleRate, musicData = wavfile.read(srcMusicFile)
 8 
 9    left = []
10    right = []
11    for item in musicData:
12        left.append(item[0])
13        right.append(item[1])
14 
15    mixed_data = np.array(left) - np.array(right)
16    wavfile.write('mixed_b.wav', sampleRate, mixed_data)
17 
18 splitChannel("test.wav")

通過播放原始音樂和處理后的音樂,發現人聲消除的效果還不錯。筆者發現,這個消除的效果要和音樂有關系,對於那些立體聲比較對稱的音樂來說,這種方法效果還是非常不錯的。針對有些特殊的音樂,這個就不那么好用了。市面上基本上使用的都是這種方法。
對於那些本想把音頻直接掛到博客園上,沒想到遇到了一些技術問題,只能把它們連同代碼一同放到github上了,有需要的朋友可以進去看一下。github地址:GitHub - DyLanCao/CoolAdudio: my open source audio edit software
輸出音頻:

方案實現

僅僅有仿真是遠遠不夠的,還要把方案做出了,筆者在國內一家藍牙芯片上,實現了該功能,效果初步測試和上面的仿真的基本能夠吻合。不過,要把效果做的更好,還要加一些料的。針對消不掉的人聲音,直接加vad檢測,針對檢測到的人聲做一下衰減,再過一下這個,效果那就是杠杠的了。案子涉及到產品保密,就不往網上掛了。有興趣的朋友可以通過QQ交流。

參考文檔


免責聲明!

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



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