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); } } }