降噪是音频图像算法中的必不可少的。

目的肯定是让图片或语音 更加自然平滑,简而言之,美化。

图像算法和音频算法 都有其共通点。

图像是偏向 空间 处理,例如图片中的某个区域。

图像很多时候是以二维数据为主,矩形数据分布。

音频更偏向 时间 处理,例如语音中的某段时长。

音频一般是一维数据为主,单声道波长。

处理方式也是差不多,要不单通道处理,然后合并,或者直接多通道处理。

只是处理时候数据参考系维度不一而已。

一般而言,

图像偏向于多通道处理,音频偏向于单通道处理。

而从数字信号的角度来看,也可以理解为聚类,频率归一化之类的。

总之就是对一些有一定规律的数字数据进行计算处理。

图像降噪被磨皮美颜这个大主题给带远了。

音频降噪目前感觉大有所为,像前面分享的《基于RNN的音频降噪算法 (附完整C代码)》

能达到这样的降噪效果,深度学习 确实有它独到的一面。

但是无可厚非,做机器学习之前还是要基于前人很多 基础算法进行数据的预处理等操作。

才能达到至善至美。

各有优劣,所谓算法肯定是互相配合为主,没有说谁能替换掉谁。

做算法最核心的思路就是使用各个算法的核心思想,放大它的优点,弱化它的缺点。

当然,做人也是如此。

音频降噪算法,网上公开的算法不多,资源也比较有限。

还是谷歌做了好事,把WebRTC开源,确实是一个基础。

前人种树,后人乘凉。

花了点时间,把WebRTC的噪声抑制模块提取出来,方便他人。

噪声抑制在WebRTC中有两个版本,一个是浮点,一个是定点。

一般定点做法是为了在一些特定环境下牺牲极少的精度,提升计算性能。

这个就不展开了,涉及到算法性能优化方面的一些知识点。

至于算法的实现,见源代码:

浮点版本:

noise_suppression.c

定点版本:

noise_suppression_x.c

算法提供4个降噪级别,分别是:

enum nsLevel {
kLow,
kModerate,
kHigh,
kVeryHigh
}; 实测效果还是很不错的,不过在一些特定的应用场景下,
其实这个算法还可以进一步调优。
改进思路,很多时候是基于需求来的,
打住打住,不细说了。 完整示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
//采用https://github.com/mackron/dr_libs/blob/master/dr_wav.h 解码
#define DR_WAV_IMPLEMENTATION #include "dr_wav.h"
#include "noise_suppression.h" #ifndef nullptr
#define nullptr 0
#endif //写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 = ;
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();
}
}
} //读取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("读取wav文件失败.");
}
//仅仅处理单通道音频
if (channels != ) {
drwav_free(buffer);
buffer = nullptr;
*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;
if (path[] && 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';
}
} enum nsLevel {
kLow,
kModerate,
kHigh,
kVeryHigh
}; static float S16ToFloat_C(int16_t v) {
if (v > ) {
return ((float) v) / (float) INT16_MAX;
} return (((float) v) / ((float) -INT16_MIN));
} void S16ToFloat(const int16_t *src, size_t size, float *dest) {
size_t i;
for (i = ; i < size; ++i)
dest[i] = S16ToFloat_C(src[i]);
} static int16_t FloatToS16_C(float v) {
static const float kMaxRound = (float) INT16_MAX - 0.5f;
static const float kMinRound = (float) INT16_MIN + 0.5f;
if (v > ) {
v *= kMaxRound;
return v >= kMaxRound ? INT16_MAX : (int16_t) (v + 0.5f);
} v *= -kMinRound;
return v <= kMinRound ? INT16_MIN : (int16_t) (v - 0.5f);
} void FloatToS16(const float *src, size_t size, int16_t *dest) {
size_t i;
for (i = ; i < size; ++i)
dest[i] = FloatToS16_C(src[i]);
} int nsProcess(int16_t *buffer, size_t sampleRate, int samplesCount, enum nsLevel level) {
if (buffer == nullptr) return -;
if (samplesCount == ) return -;
size_t samples = WEBRTC_SPL_MIN(, sampleRate / );
if (samples == ) return -;
const int maxSamples = ;
int num_bands = ;
int16_t *input = buffer;
size_t nTotal = (samplesCount / samples); NsHandle *nsHandle = WebRtcNs_Create(); int status = WebRtcNs_Init(nsHandle, sampleRate);
if (status != ) {
printf("WebRtcNs_Init fail\n");
return -;
}
status = WebRtcNs_set_policy(nsHandle, level);
if (status != ) {
printf("WebRtcNs_set_policy fail\n");
return -;
}
for (int i = ; i < nTotal; i++) {
float inf_buffer[maxSamples];
float outf_buffer[maxSamples];
S16ToFloat(input, samples, inf_buffer);
float *nsIn[] = {inf_buffer}; //ns input[band][data]
float *nsOut[] = {outf_buffer}; //ns output[band][data]
WebRtcNs_Analyze(nsHandle, nsIn[]);
WebRtcNs_Process(nsHandle, (const float *const *) nsIn, num_bands, nsOut);
FloatToS16(outf_buffer, samples, input);
input += samples;
}
WebRtcNs_Free(nsHandle); return ;
} void noise_suppression(char *in_file, char *out_file) {
//音频采样率
uint32_t sampleRate = ;
//总音频采样数
uint64_t inSampleCount = ;
int16_t *inBuffer = wavRead_int16(in_file, &sampleRate, &inSampleCount); //如果加载成功
if (inBuffer != nullptr) {
nsProcess(inBuffer, sampleRate, inSampleCount, kVeryHigh);
wavWrite_int16(out_file, inBuffer, sampleRate, inSampleCount); free(inBuffer);
}
} int main(int argc, char *argv[]) {
printf("WebRtc Noise Suppression\n");
printf("博客:http://cpuimage.cnblogs.com/\n");
printf("音频噪声抑制\n");
if (argc < )
return -;
char *in_file = argv[];
char drive[];
char dir[];
char fname[];
char ext[];
char out_file[];
splitpath(in_file, drive, dir, fname, ext);
sprintf(out_file, "%s%s%s_out%s", drive, dir, fname, ext);
noise_suppression(in_file, out_file); printf("按任意键退出程序 \n");
getchar();
return ;
}

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

示例具体流程为:

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

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

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

音频降噪算法 附完整C代码的更多相关文章

  1. 基于RNN的音频降噪算法 (附完整C代码)

    前几天无意间看到一个项目rnnoise. 项目地址: https://github.com/xiph/rnnoise 基于RNN的音频降噪算法. 采用的是 GRU/LSTM 模型. 阅读下训练代码,可 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 浅谈element-ui中的BEM范式实践

    日常的工作中,我们无时无刻不在和样式打交道.没有样式的页面就如同一部电影,被人随意地在不同地方做了截取. BEM规范应该是对于我们现在前端组件开发中我觉得是最合适的一套范式了.所以,我在自己的日常工作 ...

  2. 听翁恺老师mooc笔记(6)--指针运算

    指针值加1就是将指针值加上sizeof(指针所指变量的类型) 1+1=2,那么指针加1是加上了1这个数字吗?试一下,在代码中定义了char数组,char也是整数,数组名是ac,ac中有10个元素,0- ...

  3. 网易云音乐APP分析

    网易云音乐-感受音乐的力量 你选择的产品是?  网易云音乐 为什么选择该产品作为分析? 之前用的一直是QQ音乐,但是有一天一个朋友分享了一首网易云上的音乐(顺便分享一下歌名:Drop By Drop) ...

  4. 高级软件工程第四次作业(C++)

    1 团队组成和选题情况说明 1.1 Git链接:https://github.com/WHUSE2017/C-team 1.2 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(26 ...

  5. 201621123025《Java程序设计》第1周学习总结

    201621123025<Jave程序设计>第一周学习总结 1.本章学习总结 对于java这门课程,如果不会编码那么会很难学会如何去使用它,而在大一的一二学期的专业课--C语言和数据结构我 ...

  6. 201621123057 《Java程序设计》第7周学习总结

    1. 本周学习总结 1.1 思维导图:Java图形界面总结 1.2 可选:使用常规方法总结其他上课内容. 2.书面作业 1. GUI中的事件处理 1.1 写出事件处理模型中最重要的几个关键词. 答: ...

  7. XP实验报告

    实验名称:敏捷开发与XP实践 实验人员:20162309邢天岳(结对搭档20162313苑洪铭) 实验日期:2017.5.5 实验内容:1.在IDEA中使用工具(Code->Reformate ...

  8. 【iOS】Swift ?和 !(详解)

    Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值, 也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化 .如果在使用变量之前不进行初始化就会报错: [ ...

  9. UVA 10622 Perfect P-th Powers

    https://vjudge.net/problem/UVA-10622 将n分解质因数,指数的gcd就是答案 如果n是负数,将答案除2至奇数 原理:(a*b)^p=a^p*b^p #include& ...

  10. day-1 用python编写一个简易的FTP服务器

    从某宝上购买了一份<Python神经网络深度学习>课程,按照视频教程,用python语言,写了一个简易的FTP服务端和客户端程序,以前也用C++写过聊天程序,编程思路差不多,但是pytho ...