基于rnn的语音降噪matlab,基于RNN的音频降噪算法 (附完整C代码)

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

基于RNN的音频降噪算法。

采用的是 GRU/LSTM 模型。

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

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

urbansound8k 数据集地址:

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

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

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

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

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

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

具体修改如下:

1.支持wav格式

2.支持全部采样率

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

3.增加CMake文件

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

贴上完整示例代码 :

#include

#include "rnnoise.h"

#include

#include

#define DR_WAV_IMPLEMENTATION

#include "dr_wav.h"

void wavWrite_int16(char *filename, int16_t *buffer, int sampleRate, uint32_t totalSampleCount) {

drwav_data_format format;

format.container = drwav_container_riff;

format.format = DR_WAVE_FORMAT_PCM;

format.channels = ;

format.sampleRate = (drwav_uint32) sampleRate;

format.bitsPerSample = ;

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

}

}

}

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 == NULL) {

fprintf(stderr, "ERROR\n");

exit();

}

) {

drwav_free(buffer);

buffer = NULL;

*sampleRate = ;

*totalSampleCount = ;

}

return buffer;

}

void splitpath(const char *path, char *drv, char *dir, char *name, char *ext) {

const char *end;

const char *p;

const char *s;

] && path[] == ':') {

if (drv) {

*drv++ = *path++;

*drv++ = *path++;

*drv = '\0';

}

} else if (drv)

*drv = '\0';

for (end = path; *end && *end != ':';)

end++;

for (p = end; p > path && *--p != '\\' && *p != '/';)

if (*p == '.') {

end = p;

break;

}

if (ext)

for (s = end; (*ext = *s++);)

ext++;

for (p = end; p > path;)

if (*--p == '\\' || *p == '/') {

p++;

break;

}

if (name) {

for (s = p; s < end;)

*name++ = *s++;

*name = '\0';

}

if (dir) {

for (s = path; s < p;)

*dir++ = *s++;

*dir = '\0';

}

}

void resampleData(const int16_t *sourceData, int32_t sampleRate, uint32_t srcSize, int16_t *destinationData,

int32_t newSampleRate) {

if (sampleRate == newSampleRate) {

memcpy(destinationData, sourceData, srcSize * sizeof(int16_t));

return;

}

uint32_t last_pos = srcSize - ;

uint32_t dstSize = (uint32_t) (srcSize * ((float) newSampleRate / sampleRate));

; idx < dstSize; idx++) {

float index = ((float) idx * sampleRate) / (newSampleRate);

uint32_t p1 = (uint32_t) index;

float coef = index - p1;

uint32_t p2 = (p1 == last_pos) ? last_pos : p1 + ;

destinationData[idx] = (int16_t) ((1.0f - coef) * sourceData[p1] + coef * sourceData[p2]);

}

}

void f32_to_s16(int16_t *pOut, const float *pIn, size_t sampleCount) {

if (pOut == NULL || pIn == NULL) {

return;

}

; i < sampleCount; ++i) {

*pOut++ = (short) pIn[i];

}

}

void s16_to_f32(float *pOut, const int16_t *pIn, size_t sampleCount) {

if (pOut == NULL || pIn == NULL) {

return;

}

; i < sampleCount; ++i) {

*pOut++ = pIn[i];

}

}

void denoise_proc(int16_t *buffer, uint32_t buffen_len) {

;

DenoiseState *st;

st = rnnoise_create();

float patch_buffer[frame_size];

if (st != NULL) {

uint32_t frames = buffen_len / frame_size;

uint32_t lastFrame = buffen_len % frame_size;

; i < frames; ++i) {

s16_to_f32(patch_buffer, buffer, frame_size);

rnnoise_process_frame(st, patch_buffer, patch_buffer);

f32_to_s16(buffer, patch_buffer, frame_size);

buffer += frame_size;

}

) {

memset(patch_buffer, , frame_size * sizeof(float));

s16_to_f32(patch_buffer, buffer, lastFrame);

rnnoise_process_frame(st, patch_buffer, patch_buffer);

f32_to_s16(buffer, patch_buffer, lastFrame);

}

}

rnnoise_destroy(st);

}

void rnnDeNoise(char *in_file, char *out_file) {

uint32_t in_sampleRate = ;

uint64_t in_size = ;

int16_t *data_in = wavRead_int16(in_file, &in_sampleRate, &in_size);

uint32_t out_sampleRate = ;

uint32_t out_size = (uint32_t) (in_size * ((float) out_sampleRate / in_sampleRate));

int16_t *data_out = (int16_t *) malloc(out_size * sizeof(int16_t));

if (data_in != NULL && data_out != NULL) {

resampleData(data_in, in_sampleRate, (uint32_t) in_size, data_out, out_sampleRate);

denoise_proc(data_out, out_size);

resampleData(data_out, out_sampleRate, (uint32_t) out_size, data_in, in_sampleRate);

wavWrite_int16(out_file, data_in, in_sampleRate, (uint32_t) in_size);

free(data_in);

free(data_out);

} else {

if (data_in) free(data_in);

if (data_out) free(data_out);

}

}

int main(int argc, char **argv) {

printf("Audio Noise Reduction\n");

printf("blog:http://tntmonks.cnblogs.com/\n");

printf("e-mail:[email protected]\n");

)

;

];

];

];

];

];

];

splitpath(in_file, drive, dir, fname, ext);

sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);

rnnDeNoise(in_file, out_file);

printf("press any key to exit.\n");

getchar();

;

}

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

示例具体流程为:

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

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

邮箱地址是:

[email protected]

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

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

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

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

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

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

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

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

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

之前有大概介绍了音频采样相关的思路,详情见. 音频方面的开源项目很多很多. 最知名的莫过于谷歌开源的WebRTC, 其中的音频模块就包 ...

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

前面分享过一个算法 主要用于评估一定长度音频的音量强度, 而分析之后,很多类似的需求,肯定是做音频增益,提高音量诸如此类做法. ...

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

转自:https://www.cnblogs.com/cpuimage/p/8908551.html 前面分享过一个算法 主要用 ...

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

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

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

前言 2017年底时候写了这篇 这也算是学习过程中比较有成就感的一个算法. 自2015年做算法开始到今天,还有个把月 ...

随机推荐

Excel字符串连接

1.利用&连接. ="('"&A4&"','"&B4&"','"&C4&" ...

[转]linux 如何改变文件属性与权限

转自:http://www.cnblogs.com/yangjinjin/p/3165076.html 我们知道档案权限对于一个系统的安全重要性,也知道档案的权限对于使用者与群组的相关性, 那如何修改 ...

vi编辑器 :x与:wq的区别

按一下ESC键,之后 :wq保存和退出VI [vi是Unix/Linux系统最常用的编辑器之一,我习惯使用":x"命令来保存文件并退出,不愿意使用":wq"命令 ...

bzoj 5338: [TJOI2018]xor (树链剖分+可持久化01Trie)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=5338 题面: 5338: [TJOI2018]xor Time Limit: 30 Sec  ...

【mysql】mysql存储引擎

了解存储引擎我们先看下mysql的体系架构. 上图是mysql的逻辑架构图,可以看到分了几层. 第一层是大部分网路客户端工具,比如php,python  ,JDBC等,主要功能就是连接处理,授权认证等 ...

linux异步IO的两种方式【转】

转自:https://blog.csdn.net/shixin_0125/article/details/78898146 知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个C ...

bottle.py中的路由搜索优化

# Now search regexp routes # ROUTES_REGEXP是一个字典,键是请求方法,值是[路由, 处理函数]的列表 # 例如:{"GET", [[路由1, ...

Spring.NET依赖注入框架学习--入门

Spring.NET依赖注入框架学习--入门 在学些Spring.net框架之前,有必要先脑补一点知识,比如什么是依赖注入?IOC又是什么?控制反转又是什么意思?它们与Spring.net又有什么关系 ...

雷林鹏分享:C# 结构(Struct)

C# 结构(Struct) 在 C# 中,结构是值类型数据结构.它使得一个单一变量可以存储各种数据类型的相关数据.struct 关键字用于创建结构. 结构是用来代表一个记录.假设您想跟踪图书馆中书的动 ...

你可能感兴趣的:(基于rnn的语音降噪matlab,基于RNN的音频降噪算法 (附完整C代码))