前几天无意间看到一个项目rnnoise。

项目地址: https://github.com/xiph/rnnoise

基于RNN的音频降噪算法。

采用的是 GRU/LSTM 模型。

阅读下训练代码,可惜的是作者没有提供数据训练集。

不过基本可以断定他采用的数据集里,肯定有urbansound8k。

urbansound8k 数据集地址:

https://serv.cusp.nyu.edu/projects/urbansounddataset/urbansound8k.html

也可以考虑采用用作者训练的模型来构建数据集的做法,不过即费事,也麻烦。

经过实测,降噪效果很不错,特别是在背景噪声比较严重的情况下。

不过作者仅仅提供 pcm 的代码示例,并且还只支持48K采样率,

( 明显是为了兼容其另一个 项目  opus)

在很多应用场景下,这很不方便。

尽管稍微有点麻烦,但是事在人为,花了点时间,稍作修改。

具体修改如下:

1.支持wav格式

采用dr_wav(https://github.com/mackron/dr_libs/blob/master/dr_wav.h)

2.支持全部采样率

采样率的处理问题,采用简单粗暴法,

详情请移步博主另一篇小文《简洁明了的插值音频重采样算法例子 (附完整C代码)

3.增加CMake文件

4.增加测试用 示例音频sample.wav

取自(https://github.com/orctom/rnnoise-java)

贴上完整示例代码 :

  1. #include <stdio.h>
  2. #include "rnnoise.h"
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5.  
  6. #define DR_WAV_IMPLEMENTATION
  7.  
  8. #include "dr_wav.h"
  9.  
  10. void wavWrite_int16(char *filename, int16_t *buffer, int sampleRate, uint32_t totalSampleCount) {
  11. drwav_data_format format;
  12. format.container = drwav_container_riff;
  13. format.format = DR_WAVE_FORMAT_PCM;
  14. format.channels = ;
  15. format.sampleRate = (drwav_uint32) sampleRate;
  16. format.bitsPerSample = ;
  17. drwav *pWav = drwav_open_file_write(filename, &format);
  18. if (pWav) {
  19. drwav_uint64 samplesWritten = drwav_write(pWav, totalSampleCount, buffer);
  20. drwav_uninit(pWav);
  21. if (samplesWritten != totalSampleCount) {
  22. fprintf(stderr, "ERROR\n");
  23. exit();
  24. }
  25. }
  26. }
  27.  
  28. int16_t *wavRead_int16(char *filename, uint32_t *sampleRate, uint64_t *totalSampleCount) {
  29. unsigned int channels;
  30. int16_t *buffer = drwav_open_and_read_file_s16(filename, &channels, sampleRate, totalSampleCount);
  31. if (buffer == NULL) {
  32. fprintf(stderr, "ERROR\n");
  33. exit();
  34. }
  35. ) {
  36. drwav_free(buffer);
  37. buffer = NULL;
  38. *sampleRate = ;
  39. *totalSampleCount = ;
  40. }
  41. return buffer;
  42. }
  43.  
  44. void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {
  45. const char *end;
  46. const char *p;
  47. const char *s;
  48. ] && path[] == ':') {
  49. if (drv) {
  50. *drv++ = *path++;
  51. *drv++ = *path++;
  52. *drv = '\0';
  53. }
  54. } else if (drv)
  55. *drv = '\0';
  56. for (end = path; *end && *end != ':';)
  57. end++;
  58. for (p = end; p > path && *--p != '\\' && *p != '/';)
  59. if (*p == '.') {
  60. end = p;
  61. break;
  62. }
  63. if (ext)
  64. for (s = end; (*ext = *s++);)
  65. ext++;
  66. for (p = end; p > path;)
  67. if (*--p == '\\' || *p == '/') {
  68. p++;
  69. break;
  70. }
  71. if (name) {
  72. for (s = p; s < end;)
  73. *name++ = *s++;
  74. *name = '\0';
  75. }
  76. if (dir) {
  77. for (s = path; s < p;)
  78. *dir++ = *s++;
  79. *dir = '\0';
  80. }
  81. }
  82.  
  83. void resampleData(const int16_t *sourceData, int32_t sampleRate, uint32_t srcSize, int16_t *destinationData,
  84. int32_t newSampleRate) {
  85. if (sampleRate == newSampleRate) {
  86. memcpy(destinationData, sourceData, srcSize * sizeof(int16_t));
  87. return;
  88. }
  89. uint32_t last_pos = srcSize - ;
  90. uint32_t dstSize = (uint32_t) (srcSize * ((float) newSampleRate / sampleRate));
  91. ; idx < dstSize; idx++) {
  92. float index = ((float) idx * sampleRate) / (newSampleRate);
  93. uint32_t p1 = (uint32_t) index;
  94. float coef = index - p1;
  95. uint32_t p2 = (p1 == last_pos) ? last_pos : p1 + ;
  96. destinationData[idx] = (int16_t) ((1.0f - coef) * sourceData[p1] + coef * sourceData[p2]);
  97. }
  98. }
  99.  
  100. void f32_to_s16(int16_t *pOut, const float *pIn, size_t sampleCount) {
  101. if (pOut == NULL || pIn == NULL) {
  102. return;
  103. }
  104. ; i < sampleCount; ++i) {
  105. *pOut++ = (short) pIn[i];
  106. }
  107. }
  108.  
  109. void s16_to_f32(float *pOut, const int16_t *pIn, size_t sampleCount) {
  110. if (pOut == NULL || pIn == NULL) {
  111. return;
  112. }
  113. ; i < sampleCount; ++i) {
  114. *pOut++ = pIn[i];
  115. }
  116. }
  117.  
  118. void denoise_proc(int16_t *buffer, uint32_t buffen_len) {
  119. ;
  120. DenoiseState *st;
  121. st = rnnoise_create();
  122. float patch_buffer[frame_size];
  123. if (st != NULL) {
  124. uint32_t frames = buffen_len / frame_size;
  125. uint32_t lastFrame = buffen_len % frame_size;
  126. ; i < frames; ++i) {
  127. s16_to_f32(patch_buffer, buffer, frame_size);
  128. rnnoise_process_frame(st, patch_buffer, patch_buffer);
  129. f32_to_s16(buffer, patch_buffer, frame_size);
  130. buffer += frame_size;
  131. }
  132. ) {
  133. memset(patch_buffer, , frame_size * sizeof(float));
  134. s16_to_f32(patch_buffer, buffer, lastFrame);
  135. rnnoise_process_frame(st, patch_buffer, patch_buffer);
  136. f32_to_s16(buffer, patch_buffer, lastFrame);
  137. }
  138. }
  139. rnnoise_destroy(st);
  140. }
  141.  
  142. void rnnDeNoise(char *in_file, char *out_file) {
  143. uint32_t in_sampleRate = ;
  144. uint64_t in_size = ;
  145. int16_t *data_in = wavRead_int16(in_file, &in_sampleRate, &in_size);
  146. uint32_t out_sampleRate = ;
  147. uint32_t out_size = (uint32_t) (in_size * ((float) out_sampleRate / in_sampleRate));
  148. int16_t *data_out = (int16_t *) malloc(out_size * sizeof(int16_t));
  149. if (data_in != NULL && data_out != NULL) {
  150. resampleData(data_in, in_sampleRate, (uint32_t) in_size, data_out, out_sampleRate);
  151. denoise_proc(data_out, out_size);
  152. resampleData(data_out, out_sampleRate, (uint32_t) out_size, data_in, in_sampleRate);
  153. wavWrite_int16(out_file, data_in, in_sampleRate, (uint32_t) in_size);
  154. free(data_in);
  155. free(data_out);
  156. } else {
  157. if (data_in) free(data_in);
  158. if (data_out) free(data_out);
  159. }
  160. }
  161.  
  162. int main(int argc, char **argv) {
  163. printf("Audio Noise Reduction\n");
  164. printf("blog:http://tntmonks.cnblogs.com/\n");
  165. printf("e-mail:gaozhihan@vip.qq.com\n");
  166. )
  167. ;
  168.  
  169. ];
  170. ];
  171. ];
  172. ];
  173. ];
  174. ];
  175. splitpath(in_file, drive, dir, fname, ext);
  176. sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);
  177. rnnDeNoise(in_file, out_file);
  178. printf("press any key to exit.\n");
  179. getchar();
  180. ;
  181. }

不多写注释,直接看代码吧。

项目地址:https://github.com/cpuimage/rnnoise

示例具体流程为:

加载wav(拖放wav文件到可执行文件上)->重采样降噪->保存wav

若有其他相关问题或者需求也可以邮件联系俺探讨。

邮箱地址是: 
gaozhihan@vip.qq.com

基于RNN的音频降噪算法 (附完整C代码)的更多相关文章

  1. 音频降噪算法 附完整C代码

    降噪是音频图像算法中的必不可少的. 目的肯定是让图片或语音 更加自然平滑,简而言之,美化. 图像算法和音频算法 都有其共通点. 图像是偏向 空间 处理,例如图片中的某个区域. 图像很多时候是以二维数据 ...

  2. 基于傅里叶变换的音频重采样算法 (附完整c代码)

    前面有提到音频采样算法: WebRTC 音频采样算法 附完整C++示例代码 简洁明了的插值音频重采样算法例子 (附完整C代码) 近段时间有不少朋友给我写过邮件,说了一些他们使用的情况和问题. 坦白讲, ...

  3. mser 最大稳定极值区域(文字区域定位)算法 附完整C代码

    mser 的全称:Maximally Stable Extremal Regions 第一次听说这个算法时,是来自当时部门的一个同事, 提及到他的项目用它来做文字区域的定位,对这个算法做了一些优化. ...

  4. 单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件)

    单独编译和使用webrtc音频增益模块(附完整源码+测试音频文件) 单独编译和使用webrtc音频回声消除模块(附完整源码+测试音频文件) webrtc的音频处理模块分为降噪ns,回音消除aec,回声 ...

  5. WebRTC 音频采样算法 附完整C++示例代码

    之前有大概介绍了音频采样相关的思路,详情见<简洁明了的插值音频重采样算法例子 (附完整C代码)>. 音频方面的开源项目很多很多. 最知名的莫过于谷歌开源的WebRTC, 其中的音频模块就包 ...

  6. 音频自动增益 与 静音检测 算法 附完整C代码

    前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...

  7. 音频自动增益 与 静音检测 算法 附完整C代码【转】

    转自:https://www.cnblogs.com/cpuimage/p/8908551.html 前面分享过一个算法<音频增益响度分析 ReplayGain 附完整C代码示例> 主要用 ...

  8. 自动曝光修复算法 附完整C代码

    众所周知, 图像方面的3A算法有: AF自动对焦(Automatic Focus)自动对焦即调节摄像头焦距自动得到清晰的图像的过程 AE自动曝光(Automatic Exposure)自动曝光的是为了 ...

  9. 磨皮美颜算法 附完整C代码

    前言 2017年底时候写了这篇<集 降噪 美颜 虚化 增强 为一体的极速图像润色算法 附Demo程序> 这也算是学习过程中比较有成就感的一个算法. 自2015年做算法开始到今天,还有个把月 ...

随机推荐

  1. JavaScript奇技淫巧

    单行写一个评级系统 var rate = 3; "★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate); CSS调试黑科技,所有元素加 随机色的outlin ...

  2. 谷歌chrome 插件(扩展)开发——进阶篇(c#本地程序和插件交互)下

    在上一篇中,我提出了总任务.接下来去实现. 获取网页内容等其它信息,这是content.js 擅长做的事情: chrome.extension.onMessage.addListener( funct ...

  3. 11.C++-临时对象分析

    首先来参考以下代码: #include <stdio.h> class Test { int mi; public: Test(int i) { mi = i; } Test() { Te ...

  4. [转] SDP协议

    [转] SDP协议 http://blog.csdn.net/dxpqxb/article/details/18706471 1.SDP协议概述 SDP(Session Description Pro ...

  5. java ssm框架实现分页功能 (oracle)

    java web 实现分页功能 使用框架:ssm 数据库:oracle 话说 oracle 的分页查询比 mysql 复杂多了,在这里简单谈一下: 查询 前十条数据: SELECT * FROM( S ...

  6. CSS中图片水平垂直居中方法小结

    写页面时难免会遇到水平垂直居中的问题,总结一下最近使用的方法. 一.使用垂直居中和水平居中 <div id="div1"> <img src="img/ ...

  7. 神奇的Python

    不断学习新的知识,不断掌新的技能是一件非常有趣的事情,其实Python在我学习这门课之前从没听过,刚上第一节课老师给我们讲了一个它的应用比如可以筛选单词,定时放歌等,虽然感觉自己还没有真正理解这门课程 ...

  8. springMVC的异常处理

    1. 异常 什么是异常: 在程序中预期会出现,但是却无法处理的问题,叫做异常 异常处理原则: 延迟处理 先记着...,后续补充

  9. mysql主从复制安装详解

    1.环境准备:两台Linux6.8服务器,(可以通过yum安装mysql:yum install mysql mysql-server -y,安装的版本可能比较低,对于练手来说够用了 )主库ip:19 ...

  10. Android短信验证码倒计时

    有两种实现方法 1.第一种方式:Timer /** * Description:自定义Timer * <p> * Created by Mjj on 2016/12/4. */ publi ...