基本思想是把時域信號轉換到頻域進行處理,處理完畢後再轉回時域信號,具體算法可以參考:
https://blog.csdn.net/godloveyuxu/article/details/69225790
使用C#對語音信號降噪處理比較困難,查閱資料知道可以使用Webrtc或者speex進行降噪,不過核心思想都是把C++轉成dll庫供C#調用,由於對C++不是很熟悉,折騰了好久都沒有實現,如果想了解一下,下面的文章可以參考一下:
Webrtc:https://www.cnblogs.com/Hard/p/csharp-use-webrtc-noisesuppression.html
speex::https://blog.csdn.net/u012931018/article/details/16927583
https://www.cnblogs.com/zhuweisky/archive/2010/09/16/1827896.html
speex源碼:http://zxy15914507674.gitee.io/shared_resource_name/speex-1.2beta3-win32.zip
國內在多人語音聊天中,能使用C#進行二次開發的公司有傲瑞科技http://www.oraycn.com/Download_Free.aspx,但是要收錢
最後考慮使用python的librosa模塊實現,採用WCF和XML-RPC的方式進行調用(本文並沒有實現)
本文大部分內容轉自:https://blog.csdn.net/Boogyman/article/details/103264392
測試環境:
window server 2012
Anaconda
步驟:
下面代碼中的測試文件可以從這裏下載:http://zxy15914507674.gitee.io/shared_resource_name/librosa資源文件.rar
1 安裝librosa模塊,參考:https://blog.csdn.net/zzc15806/article/details/79603994
由於我使用的的Anaconda,所以使用命令
conda install -c conda-forge librosa
進行安裝
2 當報NoBackendError這樣的錯誤時,還需要安裝ffmpeg模塊,輸入下面的命令
conda install ffmpeg -c conda-forge
3 輸入代碼如下:
import numpy as np
import librosa
import scipy
from scipy import io
class SpecSub(object):
def __init__(self, input_wav):
self.data, self.fs = librosa.load(input_wav, sr=None, mono=True)
self.noise_frame = 3 # 使用前三幀作爲噪聲估計
self.frame_duration = 200/1000 # 200ms 幀長
self.frame_length = np.int(self.fs * self.frame_duration)
self.fft = 2048 # 2048點fft
def main(self):
noise_data = self.get_noise_data()
oris = librosa.stft(self.data, n_fft=self.fft) # Short-time Fourier transform,
mag = np.abs(oris) # get magnitude
angle = np.angle(oris) # get phase
ns = librosa.stft(noise_data, n_fft=self.fft)
mag_noise = np.abs(ns)
mns = np.mean(mag_noise, axis=1) # get mean
sa = mag - mns.reshape((mns.shape[0], 1)) # reshape for broadcast to subtract
sa0 = sa * np.exp(1.0j * angle) # apply phase information
y = librosa.istft(sa0) # back to time domain signal
scipy.io.wavfile.write('./output.wav', self.fs, (y * 32768).astype(np.int16)) # save signed 16-bit WAV format
def get_noise_data(self):
noise_data = self.data[0:self.frame_length]
for i in range(1, self.noise_frame):
noise_data = noise_data + self.data[i*self.frame_length:(i+1)*self.frame_length]
noise_data = noise_data / self.noise_frame
return noise_data
ss = SpecSub('./test.wav')
ss.main()
print('done')
輸出的效果還算不錯,但發現1M不到的音頻文件降噪後變成3M多的音頻文件,在實時語音聊天中,這明顯不符合要求,而且該模塊讀入的是待處理的音頻文件,而不是字節流,這意味着C#發送過來的音頻數據(字節數組形式的數組)只能還原爲音頻文件才能給python進行處理,這明顯是不行的,不知你有什麼好的辦法,請多多指教。