美文网首页WebRTC webrtc
单独抽取webRtc的NS&NSX(降噪)模块

单独抽取webRtc的NS&NSX(降噪)模块

作者: INode | 来源:发表于2020-01-15 18:07 被阅读0次

    注意:本文抽取的NS与NSX源码基于webRtc源码2020年1月7日的提交
    本文只提取源码中 legacy 版本的NS与NSX模块
    本文代码最终使用在Android设备上(其它设备根据情况自行调整)

    抽取AGC(增益)模块文章链接:https://www.jianshu.com/p/e105a373d6d9

    本文简述步骤:下载源码抽取文件修改源码文件编写jni文件编写CMakeLists.txt文件正常使用特别注意GitHub链接
    (提示: 非代码编写顺序 )

    1.webRtc源码

    使用Git工具Clone源码地址:https://webrtc.googlesource.com/src (需要翻墙)

    2.NS&NSX模块抽取

    主函数入口为noise_suppression.h与noise_suppression_x.h
    以下为主要源码文件:

    modules/audio_processing/legacy_ns/
                                        defines.h
                                        noise_suppression.c
                                        noise_suppression.h
                                        noise_suppression_x.c
                                        noise_suppression_x.h
                                        ns_core.c
                                        ns_core.h
                                        nsx_core.c
                                        nsx_core.h
                                        nsx_core_c.c
                                        nsx_defines.h
                                        windows_private.h
    

    以下为依赖的源码文件:

    rtc_base/
            numerics/
                    safe_conversions.h
                    safe_conversions_impl.h
            system/
                  arch.h
            checks.cc
            checks.h
            compile_assert_c.h
            sanitizer.h
    
    common_audio/signal_processing/
                                  include/real_fft.h
                                  include/signal_processing_library.h
                                  include/spl_inl.h
                                  include/spl_inl_armv7.h
                                  include/spl_inl_mips.h
                                  complex_bit_reverse.c
                                  complex_fft.c
                                  complex_fft_tables.h
                                  copy_set_operations.c
                                  cross_correlation.c
                                  division_operations.c
                                  dot_product_with_scale.cc
                                  dot_product_with_scale.h
                                  downsample_fast.c
                                  energy.c
                                  get_scaling_square.c
                                  min_max_operations.c
                                  real_fft.c
                                  spl_init.c
                                  vector_scaling_operations.c
    
    third_party/
               fft4g/
                    fft4g.c
                    fft4g.h
               spl_sqrt_floor/
                             spl_sqrt_floor.c
                             spl_sqrt_floor.h
    
    system_wrappers/include/cpu_features_wrapper.h
    

    3.修改源码文件

    主要修改check.h与check.cc文件,因为这两个文件引用了absl库
    主要修改是移除log打印,检查数据则修改使用基础库文件assert.h代替,效果无差别
    下面贴出主要代码,详情查看GitHub中源码(因为全贴出来代码太长了)

    check.h修改如下

    //zhonghua code------------------------------------
    #include <assert.h>
    
    #define RTC_CHECK(condition) assert(condition)
    #define RTC_CHECK_EQ(val1, val2) assert(val1 == val2)
    #define RTC_CHECK_NE(val1, val2) assert(val1 != val2)
    #define RTC_CHECK_LE(val1, val2) assert(val1 <= val2)
    #define RTC_CHECK_LT(val1, val2) assert(val1 < val2)
    #define RTC_CHECK_GE(val1, val2) assert(val1 >= val2)
    #define RTC_CHECK_GT(val1, val2) assert(val1 > val2)
    
    #define RTC_DCHECK(condition) RTC_CHECK(condition)
    #define RTC_DCHECK_EQ(v1, v2) RTC_CHECK_EQ(v1, v2)
    #define RTC_DCHECK_NE(v1, v2) RTC_CHECK_NE(v1, v2)
    #define RTC_DCHECK_LE(v1, v2) RTC_CHECK_LE(v1, v2)
    #define RTC_DCHECK_LT(v1, v2) RTC_CHECK_LT(v1, v2)
    #define RTC_DCHECK_GE(v1, v2) RTC_CHECK_GE(v1, v2)
    #define RTC_DCHECK_GT(v1, v2) RTC_CHECK_GT(v1, v2)
    
    #define FATAL()
    
    //zhonghua code------------------------------------
    //为了缩减lib库大小,这样处理后可缩减200K大小
    
    #ifdef USE_WEBRTC_CODE
    
    #ifdef __cplusplus
    // C++ version.
    ···
    ···[此处省略N行]
    ···
    #endif  // __cplusplus
    #endif
    

    check.cc文件主要是去掉执行代码,理论上是可以去掉这个文件

    //zhonghua code---------------------------------------
    //为了缩减lib库大小,这样处理后可缩减200K大小
    #ifdef USE_WEBRTC_CODE
    namespace {
    #if defined(__GNUC__)
    __attribute__((__format__(__printf__, 2, 3)))
    #endif
    void AppendFormat(std::string* s, const char* fmt, ...) {
    ···
    ···[此处省略N行]
    ···
    #endif
    //zhonghua code---------------------------------------
    

    4.编写jni文件

    这里的JNI文件指的是我们调用webRtc模块的C++文件
    我一般使用的是NSX模块,但是接口代码是都实现了的,大家仔细斟酌使用哈

    #include <jni.h>
    #include <string>
    #include <cstdlib>
    
    #include "modules/audio_processing/legacy_ns/noise_suppression.h"
    #include "modules/audio_processing/legacy_ns/noise_suppression_x.h"
    
    #if defined(__cplusplus)
    extern "C" {
    #endif
    
    
    JNIEXPORT jlong JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsCreate(JNIEnv *env, jobject obj) {
        return (long) WebRtcNs_Create();
    }
    
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsInit(JNIEnv *env, jobject obj, jlong nsHandler,
                                                           jint frequency) {
        NsHandle *handler = (NsHandle *) nsHandler;
        if (handler == nullptr) {
            return -3;
        }
        return WebRtcNs_Init(handler, frequency);
    }
    
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsSetPolicy(JNIEnv *env, jobject obj,
                                                                jlong nsHandler, jint mode) {
        NsHandle *handle = (NsHandle *) nsHandler;
        if (handle == nullptr) {
            return -3;
        }
        return WebRtcNs_set_policy(handle, mode);
    }
    
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsProcess(JNIEnv *env,
                                                              jobject obj, jlong nsHandler,
                                                              jfloatArray spframe, jint num_bands,
                                                              jfloatArray outframe) {
        NsHandle *handle = (NsHandle *) nsHandler;
        if (handle == nullptr) {
            return -3;
        }
        jfloat *cspframe = env->GetFloatArrayElements(spframe, nullptr);
        jfloat *coutframe = env->GetFloatArrayElements(outframe, nullptr);
        WebRtcNs_Process(handle, &cspframe, num_bands, &coutframe);
        env->ReleaseFloatArrayElements(spframe, cspframe, 0);
        env->ReleaseFloatArrayElements(outframe, coutframe, 0);
        return 0;
    }
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsFree(JNIEnv *env,
                                                           jobject obj, jlong
                                                           nsHandler) {
        NsHandle *handle = (NsHandle *) nsHandler;
        if (handle == nullptr) {
            return -3;
        }
        WebRtcNs_Free(handle);
        return 0;
    }
    
    JNIEXPORT jlong JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsxCreate(JNIEnv *env, jobject obj) {
        return (long) WebRtcNsx_Create();
    }
    
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsxInit(JNIEnv *env, jobject obj, jlong nsHandler,
                                                            jint frequency
    ) {
        NsxHandle *handler = (NsxHandle *) nsHandler;
        if (handler == nullptr) {
            return -3;
        }
        return WebRtcNsx_Init(handler, frequency);
    }
    
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsxSetPolicy(JNIEnv *env,
                                                                 jobject obj, jlong
                                                                 nsHandler,
                                                                 jint mode
    ) {
        NsxHandle *handle = (NsxHandle *) nsHandler;
        if (handle == nullptr) {
            return -3;
        }
        return WebRtcNsx_set_policy(handle, mode);
    }
    
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsxProcess(JNIEnv *env,
                                                               jobject obj, jlong
                                                               nsHandler,
                                                               jshortArray speechFrame,
                                                               jint num_bands,
                                                               jshortArray outframe) {
        NsxHandle *handle = (NsxHandle *) nsHandler;
        if (handle == nullptr) {
            return -3;
        }
        jshort *cspeechFrame = env->GetShortArrayElements(speechFrame, nullptr);
        jshort *coutframe = env->GetShortArrayElements(outframe, nullptr);
        WebRtcNsx_Process(handle, &cspeechFrame, num_bands, &coutframe);
        env->ReleaseShortArrayElements(speechFrame, cspeechFrame, 0);
        env->ReleaseShortArrayElements(outframe, coutframe, 0);
        return 0;
    }
    
    JNIEXPORT jint JNICALL
    Java_vip_inode_demo_webrtc_NoiseSuppressorUtils_nsxFree(JNIEnv *env, jobject obj, jlong nsHandler) {
        NsxHandle *handle = (NsxHandle *) nsHandler;
        if (handle == nullptr) {
            return -3;
        }
        WebRtcNsx_Free(handle);
        return 0;
    }
    
    #if defined(__cplusplus)
    }
    #endif
    

    5.编写CMakeLists.txt文件

    Android中使用需要定义宏WEBRTC_ANDROIDWEBRTC_POSIX

    CMakeLists.txt内容如下:

    cmake_minimum_required(VERSION 3.4.1)
    file(GLOB SRC_FILES
            */*.cc
            */*/*.c
            */*/*.cc
            */*/*/*.c
            ns-lib.cpp
            )
    add_library(legacy_ns-lib SHARED ${SRC_FILES})
    include_directories(./)
    add_definitions(
            -DWEBRTC_ANDROID
            -DWEBRTC_POSIX
    )
    find_library(log-lib log)
    
    target_link_libraries(legacy_ns-lib ${log-lib})
    

    6.正常使用

    在Java中使用需要先初始化

    主要使用代码:

    //初始化
    val nsUtils = NoiseSuppressorUtils()
    val nsxId = nsUtils.nsxCreate()
    val nsxInit = nsUtils.nsxInit(nsxId, 16000)
    val nexSetPolicy = nsUtils.nsxSetPolicy(nsxId, 2)
    Log.i(tag, "nsxId : $nsxId  nsxInit: $nsxInit nexSetPolicy: $nexSetPolicy")
    ···
    val inputData = ShortArray(160)
    val outNsData = ShortArray(160)
    nsUtils.nsxProcess(nsxId, inputData, 1, outNsData)
    ···
    nsUtils.nsxFree(nsxId)
    

    特别注意:每次处理的音频数据需始终为 10ms (否则会失败)

    以下为官方注解:

    /*
     * This functions does noise suppression for the inserted speech frame. The
     * input and output signals should always be 10ms (80 or 160 samples).
     *
     * Input
     *      - nsxInst       : NSx instance. Needs to be initiated before call.
     *      - speechFrame   : Pointer to speech frame buffer for each band
     *      - num_bands     : Number of bands
     *
     * Output:
     *      - nsxInst       : Updated NSx instance
     *      - outFrame      : Pointer to output frame for each band
     */
    void WebRtcNsx_Process(NsxHandle *nsxInst,
                           const int16_t *const *speechFrame,
                           int num_bands,
                           int16_t *const *outFrame);
    

    GitHub链接:https://github.com/inodevip/WebRtcNsAgcModel

    抽取AGC(增益)模块文章链接:https://www.jianshu.com/p/e105a373d6d9

    相关文章

      网友评论

        本文标题:单独抽取webRtc的NS&NSX(降噪)模块

        本文链接:https://www.haomeiwen.com/subject/kpitzctx.html