精华内容
下载资源
问答
  • 基于RNN的音频降噪算法 (附完整C代码)
    2021-04-18 10:13:26

    前几天无意间看到一个项目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:gaozhihan@vip.qq.com\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

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

    邮箱地址是:

    gaozhihan@vip.qq.com

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

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

    基于傅里叶变换的音频重采样算法 &lpar;附完整c代码&rpar;

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

    mser 最大稳定极值区域&lpar;文字区域定位&rpar;算法 附完整C代码

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

    单独编译和使用webrtc音频降噪模块&lpar;附完整源码&plus;测试音频文件&rpar;

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

    WebRTC 音频采样算法 附完整C&plus;&plus;示例代码

    之前有大概介绍了音频采样相关的思路,详情见. 音频方面的开源项目很多很多. 最知名的莫过于谷歌开源的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&" ...

    &lbrack;转&rsqb;linux 如何改变文件属性与权限

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

    vi编辑器 &colon;x与&colon;wq的区别

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

    bzoj 5338&colon; &lbrack;TJOI2018&rsqb;xor &lpar;树链剖分&plus;可持久化01Trie&rpar;

    链接: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&period;py中的路由搜索优化

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

    Spring&period;NET依赖注入框架学习--入门

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

    雷林鹏分享:C&num; 结构(Struct)

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

    更多相关内容
  • 音频降噪算法 附完整C代码

    千次阅读 2020-12-24 11:43:56
    降噪音频图像算法中的必不可少的。 目的肯定是让图片或语音 更加自然平滑,简而言之,美化。 图像算法音频算法 都有其共通点。 图像是偏向 空间 处理,例如图片中的某个区域。 图像很多时候是以二维数据为主,...

    本文转载自博客:https://cloud.tencent.com/developer/article/1117226
    降噪是音频图像算法中的必不可少的。

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

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

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

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

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

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

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

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

    一般而言,

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

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

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

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

    音频降噪目前感觉大有所为,像前面分享的《基于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 = 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("读取wav文件失败.");
        }
        //仅仅处理单通道音频
        if (channels != 1) {
            drwav_free(buffer);
            buffer = nullptr;
            *sampleRate = 0;
            *totalSampleCount = 0;
        }
        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[0] && path[1] == ':') {
            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 > 0) {
            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 = 0; 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 > 0) {
            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 = 0; 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 -1;
        if (samplesCount == 0) return -1;
        size_t samples = WEBRTC_SPL_MIN(160, sampleRate / 100);
        if (samples == 0) return -1;
        const int maxSamples = 320;
        int 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++) {
            float inf_buffer[maxSamples];
            float outf_buffer[maxSamples];
            S16ToFloat(input, samples, inf_buffer);
            float *nsIn[1] = {inf_buffer};   //ns input[band][data]
            float *nsOut[1] = {outf_buffer};  //ns output[band][data]
            WebRtcNs_Analyze(nsHandle, nsIn[0]);
            WebRtcNs_Process(nsHandle, (const float *const *) nsIn, num_bands, nsOut);
            FloatToS16(outf_buffer, samples, input);
            input += samples;
        }
        WebRtcNs_Free(nsHandle);
    
        return 1;
    }
    
    void noise_suppression(char *in_file, char *out_file) {
        //音频采样率
        uint32_t sampleRate = 0;
        //总音频采样数
        uint64_t inSampleCount = 0;
        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 < 2)
            return -1;
        char *in_file = argv[1];
        char drive[3];
        char dir[256];
        char fname[256];
        char ext[256];
        char out_file[1024];
        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 0;
    }
    

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

    示例具体流程为:

    加载wav(拖放wav文件到可执行文件上)->降噪->保存wav
    也可以直接在下面网址下载资源:
    https://download.csdn.net/download/littlezls/13770836

    展开全文
  • 项目地址:https://github.com/xiph/rnnoise基于RNN的音频降噪算法。采用的是 GRU/LSTM模型。阅读下训练代码,可惜的是作者没有提供数据训练集。不过基本可以断定他采用的数据集里,肯定有urbansound8k。urbansound8k...

    前几天无意间看到一个项目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)

    贴上完整示例代码 :

    30a070b887761b19085305b3faca4a2c.gif

    /* Copyright (c) 2017 Mozilla */

    /*

    Redistribution and use in source and binary forms, with or without

    modification, are permitted provided that the following conditions

    are met:

    - Redistributions of source code must retain the above copyright

    notice, this list of conditions and the following disclaimer.

    - Redistributions in binary form must reproduce the above copyright

    notice, this list of conditions and the following disclaimer in the

    documentation and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR

    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,

    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,

    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR

    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF

    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING

    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS

    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    */

    #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 = 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);

    }

    }

    }

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

    }

    if (channels != 1) {

    drwav_free(buffer);

    buffer = NULL;

    *sampleRate = 0;

    *totalSampleCount = 0;

    }

    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[0] && path[1] == ':') {

    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 - 1;

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

    for (uint32_t idx = 0; 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 + 1;

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

    }

    }

    void denoise_proc(int16_t *buffer, uint32_t buffen_len) {

    const int frame_size = 480;

    DenoiseState *st;

    st = rnnoise_create();

    int16_t patch_buffer[frame_size];

    if (st != NULL) {

    uint32_t frames = buffen_len / frame_size;

    uint32_t lastFrame = buffen_len % frame_size;

    for (int i = 0; i < frames; ++i) {

    rnnoise_process_frame(st, buffer, buffer);

    buffer += frame_size;

    }

    if (lastFrame != 0) {

    memset(patch_buffer, 0, frame_size * sizeof(int16_t));

    memcpy(patch_buffer, buffer, lastFrame * sizeof(int16_t));

    rnnoise_process_frame(st, patch_buffer, patch_buffer);

    memcpy(buffer, patch_buffer, lastFrame * sizeof(int16_t));

    }

    }

    rnnoise_destroy(st);

    }

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

    uint32_t in_sampleRate = 0;

    uint64_t in_size = 0;

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

    uint32_t out_sampleRate = 48000;

    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://cpuimage..com/\n");

    printf("e-mail:gaozhihan@vip.qq.com\n");

    if (argc < 2)

    return -1;

    char *in_file = argv[1];

    char drive[3];

    char dir[256];

    char fname[256];

    char ext[256];

    char out_file[1024];

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

    return 0;

    }

    30a070b887761b19085305b3faca4a2c.gif

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

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

    示例具体流程为:

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

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

    邮箱地址是:

    gaozhihan@vip.qq.com

    展开全文
  • 但凡学习音频降噪算法的朋友,肯定看过一个算法. <<语音增强-理论与实践>> 中提及到基于对数的最小均方误差的降噪算法,也就是LogMMSE. 资料见: <<Speechenhancementusingaminimummean-...

    近期比较忙,

    抽空出来5.1开源献礼.

    但凡学习音频降噪算法的朋友,肯定看过一个算法.

    <<语音增强-理论与实践>> 中提及到基于对数的最小均方误差的降噪算法,也就是LogMMSE.

    资料见:

    <<Speech enhancement using a minimum  mean-square error log-spectral amplitude estimator.>> 

    -----Ephraim, Y. and Malah, D. (1985)

    之前也是花了不少时间去查阅降噪相关的思路,

    但是最终发现前人的思路,有很多局限性或者说弊端.

    一般都是提出一种数学先验的假设,换句话说,在paper里讲点故事.

    然后最终,故事的结局都是it works.

    但实际应用却差强人意.

     

     而一般的图像降噪流程,见图:

    也就是,一个降噪算法的基本组成部分有:

    1.噪声提取(用于提取噪声)

    2.静音检测(一般检测是否为人声,减少误判)

    3.数学先验假设(用于降噪)

     

    当然最小均方误差的降噪思路,用在图像上一样适用.

     

    但是,大多数音频降噪算法仅仅适配某种特殊情况(特例).

    工程化应用时,会发现,

    一个坑接着一个坑,

    然后不得不妥协.勉强能用就行,

    要求太高不现实.

     

    而当年看了logMMSE的思路之后,就很清楚地明白,

    这思路是可行的,但是特别鸡肋.

     

    话说如此,但是对作为学习信号处理,音频降噪来说,

    这个是一个特别好的入门示例算法.

    至少经过实践之后,你心中能有了个大概的印象.

    音频降噪是一个什么样的工作,会碰到什么样的难点.

     

     logmmse的各种实现,在github搜索一下,都能找得到.

    这里,并不打算解析logmmse的算法细节.

     

    只是分享一段非常简单有效的类似logmmse算法的c语言实现.

    说是类似,不如说,

    思路来自logmmse,只是更加的简洁明了.(自我以为)

    自己动手,丰衣足食.

    稍微改进一下,可以进一步适配各种环境和情况,

    当然也不是那么容易,

    例如:

    +vad.

    +延时记忆机制诸如此类

     

    代码基于本人最近开源的基于傅里叶变换的重采样算法.

    https://github.com/cpuimage/FFTResampler

    题外话:

    在之前为了找各种重采样算法,费心死了.

    所以,写一个通用简洁的重采样算法是我的一个待办事项.

    重采样算法算是暂时结束了.

    https://github.com/cpuimage/resampler

    https://github.com/cpuimage/FFTResampler

    这两个平时应该是够用了,

    下一步要继续做的话,

    可能就是音频超分辨率算法了.

     

    除了懒,没别的,能复用就复用了.

    回到主题上,这个简易的算法用来去除平稳噪声或底噪,是非常合适的,

    当然当前开源实现的算法,是非实时的,

    当然稍微改进下可以应用在实时的环境.

     

    值5.1放假之际,开源出来,给大家参考学习.

    权当抛砖引玉,一起玩耍.

     

    项目地址:

    https://github.com/cpuimage/SimpleAudioDenoise


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

    当然一些基础性的问题,一概忽略.

    有时间给我写邮件,不如多看点资料书籍.

     

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

    转载于:https://www.cnblogs.com/cpuimage/p/10800768.html

    展开全文
  • 助听器算法,多通道DRC,降噪,啸叫陷波器
  • 转:https://www.cnblogs.com/cpuimage/p/8905965.html降噪音频图像算法中的必不可少的。目的肯定是让图片或语音 更加自然平滑,简而言之,美化。图像算法音频算法都有其共通点。图像是偏向空间处理,例如图片中...
  • Android 音频降噪源码

    2018-11-08 11:50:46
    android音频降噪,采用webrtc技术,包含底层源码和so库
  • Matlab实现音频降噪

    2016-10-26 21:26:09
    可用于音频信号处理的学习,兼容Octave!
  • 16bitPCM降噪

    2020-12-07 18:10:59
    16bitPCM降噪工程,该资源为从其他地方下载,亲测可用,降噪明显有效,可供学习参考或者可直接使用
  • 机器之心专栏网易云信音频实验室网易云信音频实验室自主研发了一个针对瞬态噪声的轻量级网络音频降噪算法(网易云信 AI 音频降噪),对于 Non-stationary Noise 和 Tran...
  • LMS音频降噪matlab程序

    2018-04-12 14:16:16
    本人课件作业,供大家参考:输入语音,加上高斯白噪声,采用32阶LMS自适应滤波,输出滤波后音频
  • 音频降噪 2

    2022-03-13 22:34:29
    最近几年,随着 AI 技术的不断演进,在降噪等音频处理领域,都出现了很多基于 Artificail Intelligence(AI)或者说基于人工神经网络模型的降噪算法。这些 AI 算法在降噪能力上较传统算法都有很大的提升。但 AI 降噪...
  • 音频降噪 1

    2022-03-13 22:01:02
    它是由 Israel Cohen 提出的音频降噪算法。OMLSA 是对人声进行估计,通过先验无声概率及先验信噪比 SNR 的估计来得到有声条件概率,从而实现了对人声谱的估计。 IMCRA 则是通过信号的最小值跟踪,得到先验无声概率...
  • 音频处理,FFT算法实现,C#源码,随便写的,就这样吧。
  • 今天小编就为大家分享一篇Python谱减法语音降噪实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 一段包含人声和噪声的音频经过该模块处理,从理论上讲,只剩下人声了。 webrtc的NS在业内还是赫赫有名的,通过实际对比测试,我们发现webrtc的降噪的确是性能和稳定性 都要高于同类开源算法。 webrtc的ns原理是这样...
  • 语音降噪算法

    千次阅读 2021-03-30 10:37:18
    SNR越低,降噪效果越差 1.LMS自适应滤波器、陷波器降噪...2)当用户使用蓝牙耳机或有线耳机通话时,手机端的双麦克风降噪算法往往又会失效。 3)双麦克风在工业设计上也会造成很多阻碍。两个麦克风会让声学音频路径的设计
  • 【技术实现步骤摘要】一种基于深度神经网络的音频降噪方法本专利技术涉及歌唱领域的音频降噪方法,特别是一种基于深度神经网络的音频降噪方法。技术介绍现实生活中的语音音频信号或是歌声音频信号,往往都不是纯净的...
  • 有大佬做过fpga实现算法的项目吗,求求大佬教教我,我丝毫没有头绪,在这先谢谢大佬
  • 音频噪音消除算法

    千次阅读 2022-02-25 13:50:46
    音频降噪算法在音频通话处理中是必不可少的,网上公开的算法不是很多,资源也比较有限,绝大多数效果都不是很理想,都无法达到产品级的效果,近期在研究webrtc代码,把WebRTC的噪声抑制模块提取出来,也做了一些细节...
  • python实现Logmmse声音降噪算法 1.所需环境 pip install logmmse pip install wave pip install numpy 2.具体代码 import logmmse import wave import numpy as np if __name__ == '__main__': # out = logmmse....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,371
精华内容 1,348
关键字:

音频降噪算法

友情链接: DbHelper.rar