基於WebRTC實現iOS端音頻降噪功能


https://www.jianshu.com/p/c8d79056c6fc?tdsourcetag=s_pcqq_aiomsg

 

WebRTC下載要很麻煩,並且學會使用一個庫也要花費不少時間,另一方面導入一個第三方庫app的體積會加大,因此用了一位大神從WebRTC提出來的模塊,但因為是c的所以還要轉一次。

WebRTC降噪有兩部分代碼,一套是定點算法(noise_suppression_x.h),一套是浮點算法(noise_suppression.h)。相對來說浮點算法精度更高,但是耗系統資源更多,特別是浮點計算能力較弱的低端ARM CPU上。

音頻處理的時候webrtc一次僅能處理10ms數據,小於10ms的數據不要傳入,如果是傳入小於10ms的數據最后傳入也是按照10ms的數據傳出,此時會出現問題。另外支持采樣率也只有8K,16K,32K三種,不論是降噪模塊,或者是回聲消除增益等等均是如此。對於8000采樣率,16bit的音頻數據,10ms的時間采樣點就是80個,一個采樣點16bit也就是兩個字節,那么需要傳入WebRtcNsx_Process的數據就是160字節。對於8000和16000采樣率的音頻數據在使用時可以不管高頻部分,只需要傳入低頻數據即可,但是對於32K采樣率的數據就必須通過濾波接口將數據分為高頻和低頻傳入,傳入降噪后再組合成音頻數據。大於32K的音頻文件就必須要通過重采樣接口降頻到對應的采樣率再處理。

部分代碼

- (void)viewDidLoad { [super viewDidLoad]; NSString *inpath = @"/Users/apple/Desktop/a.wav"; NSString *outpath = @"/Users/apple/Desktop/b.wav"; const char *in_file = [inpath UTF8String]; const char *out_file = [outpath UTF8String]; char in_f[1024]; //把從src地址開始且含有'\0'結束符的字符串復制到以dest開始的地址空間,返回值的類型為char* strcpy(in_f,in_file); char out_f[1024]; strcpy(out_f,out_file); [self noise_suppression:in_f and:out_f]; } - (void)noise_suppression:(char *)in_file and:(char *)out_file { //音頻采樣率 uint32_t sampleRate = 0; //總音頻采樣數 uint64_t inSampleCount = 0; int16_t *inBuffer = [self wavRead_int16:in_file :&sampleRate :&inSampleCount]; //如果加載成功 if (inBuffer != nullptr) { double startTime = now(); [self nsProcess:inBuffer :sampleRate :(int)inSampleCount :kModerate]; double time_interval = calcElapsed(startTime, now()); printf("time interval: %d ms\n ", (int) (time_interval * 1000)); [self wavWrite_int16:out_file :inBuffer :sampleRate :inSampleCount]; free(inBuffer); } } //寫wav文件 - (void)wavWrite_int16:(char *)filename :(int16_t *)buffer :(size_t)sampleRate :(size_t)totalSampleCount { drwav_data_format format = {}; format.container = drwav_container_riff; // <-- drwav_container_riff = normal WAV files, drwav_container_w64 = Sony Wave64. format.format = DR_WAVE_FORMAT_PCM; // <-- Any of the DR_WAVE_FORMAT_* codes. format.channels = 1; format.sampleRate = (drwav_uint32)sampleRate; format.bitsPerSample = 16; drwav *pWav = drwav_open_file_write(filename, &format); if (pWav) { drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer); drwav_uninit(pWav); if (samplesWritten != totalSampleCount) { fprintf(stderr, "ERROR\n"); exit(1); } } } //讀取wav文件 - (int16_t *)wavRead_int16:(char *)filename :(uint32_t *)sampleRate :(uint64_t *)totalSampleCount{ unsigned int channels; int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount); if (buffer == nullptr) { printf("ERROR."); } return buffer; } -(int)nsProcess:(int16_t *)buffer :(uint32_t)sampleRate :(int)samplesCount :(enum nsLevel)level { if (buffer == nullptr) return -1; if (samplesCount == 0) return -1; size_t samples = MIN(160, sampleRate / 100); if (samples == 0) return -1; uint32_t num_bands = 1; int16_t *input = buffer; size_t nTotal = (samplesCount / samples); NsHandle *nsHandle = WebRtcNs_Create(); int status = WebRtcNs_Init(nsHandle, sampleRate); if (status != 0) { printf("WebRtcNs_Init fail\n"); return -1; } status = WebRtcNs_set_policy(nsHandle, level); if (status != 0) { printf("WebRtcNs_set_policy fail\n"); return -1; } for (int i = 0; i < nTotal; i++) { int16_t *nsIn[1] = {input}; //ns input[band][data] int16_t *nsOut[1] = {input}; //ns output[band][data] WebRtcNs_Analyze(nsHandle, nsIn[0]); WebRtcNs_Process(nsHandle, (const int16_t *const *) nsIn, num_bands, nsOut); input += samples; } WebRtcNs_Free(nsHandle); return 1; } 

oc代碼

參考:單獨編譯和使用webrtc音頻降噪模塊
參考:音頻降噪算法

 
 
22人點贊
 
iOS
 
 


作者:長空幻月
鏈接:https://www.jianshu.com/p/c8d79056c6fc
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

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



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