Android 音频降噪 webrtc 去回声
程序员文章站
2022-04-06 08:04:00
Android 音频降噪 webrtc 去回声集成AECM模块集成NS模块需要源码请留言集成AECM模块1.通过 webrtc官网下载需要模块\modules\audio_processing\aecm2.新建eclipse工程,新建jni文件夹将webrtc aecm模块拷贝到jni文件夹下3.编写本地接口package com.wrtcmy.webrtc.aecm;/** * This class supports the acoustic echo cancellation for...
集成AECM模块
1.通过 webrtc官网下载需要模块\modules\audio_processing\aecm
2.新建eclipse工程,新建jni文件夹将webrtc aecm模块拷贝到jni文件夹下
3.编写本地接口
package com.wrtcmy.webrtc.aecm;
/**
* This class supports the acoustic echo cancellation for mobile edition. Please <b>bug me</b> if you find any bugs in
* this toolkit.<br>
* <br>
* <b>[Notice]</b><br>
* 1. there are 5 more native interface that I'm not trying to provide in this MobileAEC toolkit.<br>
* But I think I should mention it out as a list below, for secondary development if necessary: <br>
* <ul>
* <li>WebRtc_Word32 WebRtcAecm_get_config(void *, AecmConfig *);</li>
* <li>WebRtc_Word32 WebRtcAecm_InitEchoPath(void* , const void* , size_t);</li>
* <li>WebRtc_Word32 WebRtcAecm_GetEchoPath(void* , void* , size_t);</li>
* <li>size_t WebRtcAecm_echo_path_size_bytes();</li>
* <li>WebRtc_Word32 WebRtcAecm_get_error_code(void *);</li>
* </ul>
* 2. if you are working on an android platform, put the shared library "libwebrtc_aecm.so"<br>
* into path "/your project/libs/armeabi/", if the dir does not exist, you should create it, otherwise you<br>
* will get a "unsatisfied link error" at run time.<br>
* 3. you should always call <b>close()</b> method <b>manually</b> when all things are finished.<br>
* <br>
* <b>[Usage]</b> <br>
* <ul>
* 1. You create a MobileAEC object first(set the parameters to constructor or null are both Ok, if null are set, then
* we will use default values instead).<br>
* 2. change the aggressiveness or sampling frequency of the AECM instance if necessary.<br>
* 3. call <b>prepare()</b> method to make the AECM instance prepared. <br>
* 4. then call "farendBuffer" to set far-end signal to AECM instance. <br>
* 5. now you call "echoCancellation()" to deal with the acoustic echo things.<br>
* The order of step 1,2,3,4 and 5 is significant, when all settings are done or you changed previous<br>
* settings, <b>DO NOT</b> forget to call prepare() method, otherwise your new settings will be ignored by AECM
* instance. <br>
* 6. finally you should call <b>close()</b> method <b>manually</b> when all things are done, after that, the AECM
* instance is no longer available until next <b>prepare()</b> is called.<br>
* </ul>
*
* @version 0.1 2013-3-8
*
*/
public class AECM {
static {
System.loadLibrary("webrtc_aecm"); // to load the libwebrtc_aecm.so library.
}
// /
// PUBLIC CONSTANTS
/**
* constant unable mode for Aecm configuration settings.
*/
public static final short AECM_UNABLE = 0;
/**
* constant enable mode for Aecm configuration settings.
*/
public static final short AECM_ENABLE = 1;
// /
// PUBLIC NESTED CLASSES
/**
* For security reason, this class supports constant sampling frequency values in
* {@link SamplingFrequency#FS_8000Hz FS_8000Hz}, {@link SamplingFrequency#FS_16000Hz FS_16000Hz}
*/
public static final class SamplingFrequency {
public long getFS() {
return mSamplingFrequency;
}
/**
* This constant represents sampling frequency in 8000Hz
*/
public static final SamplingFrequency FS_8000Hz = new SamplingFrequency(
8000);
/**
* This constant represents sampling frequency in 16000Hz
*/
public static final SamplingFrequency FS_16000Hz = new SamplingFrequency(
16000);
private final long mSamplingFrequency;
private SamplingFrequency(long fs) {
this.mSamplingFrequency = fs;
}
}
/**
* For security reason, this class supports constant aggressiveness of the AECM instance in
* {@link AggressiveMode#MILD MILD}, {@link AggressiveMode#MEDIUM MEDIUM}, {@link AggressiveMode#HIGH HIGH},
* {@link AggressiveMode#AGGRESSIVE AGGRESSIVE}, {@link AggressiveMode#MOST_AGGRESSIVE MOST_AGGRESSIVE}.
*/
public static final class AggressiveMode {
public int getMode() {
return mMode;
}
/**
* This constant represents the aggressiveness of the AECM instance in MILD_MODE
*/
public static final AggressiveMode MILD = new AggressiveMode(
0);
/**
* This constant represents the aggressiveness of the AECM instance in MEDIUM_MODE
*/
public static final AggressiveMode MEDIUM = new AggressiveMode(
1);
/**
* This constant represents the aggressiveness of the AECM instance in HIGH_MODE
*/
public static final AggressiveMode HIGH = new AggressiveMode(
2);
/**
* This constant represents the aggressiveness of the AECM instance in AGGRESSIVE_MODE
*/
public static final AggressiveMode AGGRESSIVE = new AggressiveMode(
3);
/**
* This constant represents the aggressiveness of the AECM instance in MOST_AGGRESSIVE_MODE
*/
public static final AggressiveMode MOST_AGGRESSIVE = new AggressiveMode(
4);
private final int mMode;
private AggressiveMode(int mode) {
mMode = mode;
}
}
// /
// PRIVATE MEMBERS
private int mAecmHandler = -1; // the handler of AECM instance.
private AecmConfig mAecmConfig = null; // the configurations of AECM instance.
private SamplingFrequency mSampFreq = null; // sampling frequency of input speech data.
private boolean mIsInit = false; // whether the AECM instance is initialized or not.
// /
// CONSTRUCTOR
/**
* To generate a new AECM instance, whether you set the sampling frequency of each parameter or not are both ok.
*
* @param sampFreqOfData
* - sampling frequency of input audio data. if null, then {@link SamplingFrequency#FS_16000Hz
* FS_16000Hz} is set.
*/
public AECM(SamplingFrequency sampFreqOfData) {
setSampFreq(sampFreqOfData);
mAecmConfig = new AecmConfig();
// create new AECM instance but without initialize. Init things are in prepare() method instead.
mAecmHandler = nativeCreateAecmInstance();
}
// /
// PUBLIC METHODS
/**
* set the sampling rate of speech data.
*
* @param fs
* - sampling frequency of speech data, if null then {@link SamplingFrequency#FS_16000Hz FS_16000Hz} is
* set.
*/
public void setSampFreq(SamplingFrequency fs) {
if (fs == null)
mSampFreq = SamplingFrequency.FS_16000Hz;
else
mSampFreq = fs;
}
/**
* set the far-end signal of AECM instance.
*
* @param farendBuf
* @param numOfSamples
* @return the {@link AECM MobileAEC} object itself.
* @throws Exception
* - if farendBuffer() is called on an unprepared AECM instance or you pass an invalid parameter.<br>
*/
public AECM farendBuffer(short[] farendBuf, int numOfSamples)
throws Exception {
// check if AECM instance is not initialized.
if (!mIsInit) {
// TODO(billhoo) - create a custom exception instead of using java.lang.Exception
throw new Exception(
"setFarendBuffer() called on an unprepared AECM instance.");
}
if (nativeBufferFarend(mAecmHandler, farendBuf, numOfSamples) == -1)
// TODO(billhoo) - create a custom exception instead of using java.lang.Exception
throw new Exception(
"setFarendBuffer() failed due to invalid arguments.");
return this;
}
/**
* core process of AECM instance, must called on a prepared AECM instance. we only support 80 or 160 sample blocks
* of data.
*
* @param nearendNoisy
* - In buffer containing one frame of reference nearend+echo signal. If noise reduction is active,
* provide the noisy signal here.
* @param nearendClean
* - In buffer containing one frame of nearend+echo signal. If noise reduction is active, provide the
* clean signal here. Otherwise pass a NULL pointer.
* @param out
* - Out buffer, one frame of processed nearend.
* @param numOfSamples
* - Number of samples in nearend buffer
* @param delay
* - Delay estimate for sound card and system buffers <br>
* delay = (t_render - t_analyze) + (t_process - t_capture)<br>
* where<br>
* - t_analyze is the time a frame is passed to farendBuffer() and t_render is the time the first sample
* of the same frame is rendered by the audio hardware.<br>
* - t_capture is the time the first sample of a frame is captured by the audio hardware and t_process is
* the time the same frame is passed to echoCancellation().
*
* @throws Exception
* - if echoCancellation() is called on an unprepared AECM instance or you pass an invalid parameter.<br>
*/
public void echoCancellation(short[] nearendNoisy, short[] nearendClean,
short[] out, short numOfSamples, short delay) throws Exception {
// check if AECM instance is not initialized.
if (!mIsInit) {
// TODO(billhoo) - create a custom exception instead of using java.lang.Exception
throw new Exception(
"echoCancelling() called on an unprepared AECM instance.");
}
if (nativeAecmProcess(mAecmHandler, nearendNoisy, nearendClean, out,
numOfSamples, delay) == -1)
// TODO(billhoo) - create a custom exception instead of using java.lang.Exception
throw new Exception(
"echoCancellation() failed due to invalid arguments.");
}
/**
* Set the aggressiveness mode of AECM instance, more higher the mode is, more aggressive the instance will be.
*
* @param mode
* @return the {@link AECM MobileAEC} object itself.
* @throws NullPointerException
* - if mode is null.
*/
public AECM setAecmMode(AggressiveMode mode)
throws NullPointerException {
// check the mode argument.
if (mode == null)
throw new NullPointerException(
"setAecMode() failed due to null argument.");
mAecmConfig.mAecmMode = (short) mode.getMode();
return this;
}
/**
* When finished the pre-works or any settings are changed, call this to make AECM instance prepared. Otherwise your
* new settings will be ignored by the AECM instance.
*
* @return the {@link AECM MobileAEC} object itself.
*/
public AECM prepare() {
if (mIsInit) {
close();
mAecmHandler = nativeCreateAecmInstance();
}
mInitAecmInstance((int) mSampFreq.getFS());
mIsInit = true;
// set AecConfig to native side.
nativeSetConfig(mAecmHandler, mAecmConfig);
return this;
}
/**
* Release the resources in AECM instance and the AECM instance is no longer available until next <b>prepare()</b>
* is called.<br>
* You should <b>always</b> call this <b>manually</b> when all things are done.
*/
public void close() {
if (mIsInit) {
nativeFreeAecmInstance(mAecmHandler);
mAecmHandler = -1;
mIsInit = false;
}
}
//
// PROTECTED METHODS
@Override
protected void finalize() throws Throwable {
super.finalize();
// TODO(billhoo) need a safety one.
if (mIsInit) {
close();
}
}
//
// PRIVATE METHODS
/**
* initialize the AECM instance
*
* @param SampFreq
*/
private void mInitAecmInstance(int SampFreq) {
if (!mIsInit) {
nativeInitializeAecmInstance(mAecmHandler, SampFreq);
// initialize configurations of AECM instance.
mAecmConfig = new AecmConfig();
// set default configuration of AECM instance
nativeSetConfig(mAecmHandler, mAecmConfig);
mIsInit = true;
}
}
//
// PRIVATE NESTED CLASSES
/**
* Acoustic Echo Cancellation for Mobile Configuration class, holds the config Info. of AECM instance.<br>
* [NOTE] <b>DO NOT</b> modify the name of members, or you must change the native code to match your modifying.
* Otherwise the native code could not find pre-binding members name.<br>
*
*/
@SuppressWarnings("unused")
public class AecmConfig {
private short mAecmMode = (short) AggressiveMode.AGGRESSIVE.getMode(); // default AggressiveMode.AGGRESSIVE
private short mCngMode = AECM_ENABLE; // AECM_UNABLE, AECM_ENABLE (default)
}
// ///
// PRIVATE NATIVE INTERFACES
/**
* Allocates the memory needed by the AECM. The memory needs to be initialized separately using the
* nativeInitializeAecmInstance() method.
*
* @return -1: error<br>
* other values: created AECM instance handler.
*
*/
private static native int nativeCreateAecmInstance();
/**
* Release the memory allocated by nativeCreateAecmInstance().
*
* @param aecmHandler
* - handler of the AECM instance created by nativeCreateAecmInstance()
* @return 0: OK<br>
* -1: error
*/
private static native int nativeFreeAecmInstance(int aecmHandler);
/**
* Initializes an AECM instance.
*
* @param aecmHandler
* - Handler of AECM instance
* @param samplingFrequency
* - Sampling frequency of data
* @return: 0: OK<br>
* -1: error
*/
private static native int nativeInitializeAecmInstance(int aecmHandler,
int samplingFrequency);
/**
* Inserts an 80 or 160 sample block of data into the farend buffer.
*
* @param aecmHandler
* - Handler to the AECM instance
* @param farend
* - In buffer containing one frame of farend signal for L band
* @param nrOfSamples
* - Number of samples in farend buffer
* @return: 0: OK<br>
* -1: error
*/
private static native int nativeBufferFarend(int aecmHandler,
short[] farend, int nrOfSamples);
/**
* Runs the AECM on an 80 or 160 sample blocks of data.
*
* @param aecmHandler
* - Handler to the AECM handler
* @param nearendNoisy
* - In buffer containing one frame of reference nearend+echo signal. If noise reduction is active,
* provide the noisy signal here.
* @param nearendClean
* - In buffer containing one frame of nearend+echo signal. If noise reduction is active, provide the
* clean signal here.Otherwise pass a NULL pointer.
* @param out
* - Out buffer, one frame of processed nearend.
* @param nrOfSamples
* - Number of samples in nearend buffer
* @param msInSndCardBuf
* - Delay estimate for sound card and system buffers <br>
* @return: 0: OK<br>
* -1: error
*/
private static native int nativeAecmProcess(int aecmHandler,
short[] nearendNoisy, short[] nearendClean, short[] out,
short nrOfSamples, short msInSndCardBuf);
/**
* Enables the user to set certain parameters on-the-fly.
*
* @param aecmHandler
* - Handler to the AECM instance
* @param aecmConfig
* - the new configuration of AECM instance to set.
*
* @return 0: OK<br>
* -1: error
*/
private static native int nativeSetConfig(int aecmHandler,
AecmConfig aecmConfig);
}
4.在jni文件夹下新建Android.mk与Application.mk并在对应模块下新建Android.mk
Android.mk
include $(call all-subdir-makefiles)
Application.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
APP_PROJECT_PATH := $(call my-dir)/../
APP_STL := gnustl_static
APP_BUILD_SCRIPT:=$(call my-dir)/Android.mk
APP_PLATFORM := android-22
APP_ABI := armeabi-v7a,armeabi
APP_CFLAGS:=-DDISABLE_NEON
aecm\Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := webrtc_aecm
LOCAL_CFLAGS += -DWEBRTC_POSIX
LOCAL_SRC_FILES := \
randomization_functions.c \
spl_sqrt_floor.c \
division_operations.c \
vector_scaling_operations.c \
downsample_fast.c \
cross_correlation.c \
spl_init.c \
min_max_operations.c \
complex_fft.c \
complex_bit_reverse.c \
real_fft.c \
delay_estimator.c \
delay_estimator_wrapper.c \
ring_buffer.c \
aecm_core.c \
echo_control_mobile.c \
com_wrtcmy_webrtc_aecm_AECM.c
#aecm_wrapper.c
LOCAL_LDLIBS :=-llog
include $(BUILD_SHARED_LIBRARY)
5.编译生成头文件可参考: Android源码下编译apk、jar与jni ndk-build
6.通过c文件实现
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <stdlib.h> // for NULL
#include <assert.h>
#include <echo_control_mobile.h>
#include "com_wrtcmy_webrtc_aecm_AECM.h"
/* Header for class com_wrtcmy_webrtc_aecm_AECM */
/*
* Class: com_wrtcmy_webrtc_aecm_AECM
* Method: nativeCreateAecmInstance
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_aecm_AECM_nativeCreateAecmInstance
(JNIEnv *env,jclass jclazz) {
void *aecmInstHandler = NULL;
if (WebRtcAecm_Create(&aecmInstHandler) == -1)
return -1;
else
return ((int) aecmInstHandler); //returns the pointer which points to created AECM instance to JAVA layer.
}
/*
* Class: com_wrtcmy_webrtc_aecm_AECM
* Method: nativeFreeAecmInstance
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_aecm_AECM_nativeFreeAecmInstance
(JNIEnv *env, jclass jclazz, jint aecmHandler) {
void *aecmInst = (void *) aecmHandler;
if (aecmInst == NULL)
return -1;
int ret = WebRtcAecm_Free(aecmInst);
aecmInst = NULL;
return ret;
}
/*
* Class: com_wrtcmy_webrtc_aecm_AECM
* Method: nativeInitializeAecmInstance
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_aecm_AECM_nativeInitializeAecmInstance
(JNIEnv *env, jclass jclazz, jint aecmHandler, jint sampFreq) {
void *aecmInst = (void *) aecmHandler;
if (aecmInst == NULL)
return -1;
return WebRtcAecm_Init(aecmInst, sampFreq);
}
/*
* Class: com_wrtcmy_webrtc_aecm_AECM
* Method: nativeBufferFarend
* Signature: (I[SI)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_aecm_AECM_nativeBufferFarend
(JNIEnv *env, jclass jclazz, jint aecmHandler, jshortArray farend,
jint nrOfSamples) {
void *aecmInst = (void *) aecmHandler;
if (aecmInst == NULL)
return -1;
int ret = -1;
if (farend != NULL) {
short *arrFarend = (*env)->GetShortArrayElements(env, farend, NULL);
ret = WebRtcAecm_BufferFarend(aecmInst, arrFarend, nrOfSamples);
//TODO(billhoo) should use JNI_ABORT instead of 0 in 4th param.
//I think there is no need to copy this array back to Java layer.
(*env)->ReleaseShortArrayElements(env, farend, arrFarend, 0);
}
return ret;
}
/*
* Class: com_wrtcmy_webrtc_aecm_AECM
* Method: nativeAecmProcess
* Signature: (I[S[S[SSS)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_aecm_AECM_nativeAecmProcess
(JNIEnv *env, jclass jclazz, jint aecmHandler,
const jshortArray nearendNoisy, const jshortArray nearendClean,
jshortArray out, jshort nrOfSamples, jshort msInSndCardBuf) {
int16_t *arrNearendNoisy = NULL;
int16_t *arrNearendClean = NULL;
int16_t *arrOut = NULL;
void *aecmInst = (void *) aecmHandler;
if (aecmInst == NULL)
return -1;
int ret = -1;
//nearendNoisy and out must not be NULL, otherwise process can not be run, return -1 for error.
if (nearendNoisy == NULL || out == NULL)
return ret;
//get data from java side.
arrNearendNoisy = (*env)->GetShortArrayElements(env, nearendNoisy, NULL);
arrOut = (*env)->GetShortArrayElements(env, out, NULL);
if (nearendClean != NULL)
arrNearendClean = (*env)->GetShortArrayElements(env, nearendClean,
NULL);
ret = WebRtcAecm_Process(aecmInst, arrNearendNoisy, arrNearendClean, arrOut,
nrOfSamples, msInSndCardBuf);
//release and send the changes back to java side.
(*env)->ReleaseShortArrayElements(env, nearendNoisy, arrNearendNoisy, 0);
(*env)->ReleaseShortArrayElements(env, out, arrOut, 0);
if (nearendClean != NULL)
(*env)->ReleaseShortArrayElements(env, nearendClean, arrNearendClean,
0);
return ret;
}
/*
* Class: com_wrtcmy_webrtc_aecm_AECM
* Method: nativeSetConfig
* Signature: (ILcom/wrtcmy/webrtc/aecm/AECM/AecmConfig;)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_aecm_AECM_nativeSetConfig
(JNIEnv *env, jclass jclazz, jint aecmHandler, jobject aecmConfig) {
void * aecmInst = (void *) aecmHandler;
if (aecmInst == NULL)
return -1;
//get reference of AecmConfig class from java side.
jclass JavaAecmConfig = (*env)->GetObjectClass(env, aecmConfig);
//assertion that class not be NULL
//TODO(billhoo) should use Exception handler to handle this situation instead of assertion.
assert(JavaAecmConfig != NULL);
//get configuration field IDs from java side.
jfieldID mAecmModeID = (*env)->GetFieldID(env, JavaAecmConfig, "mAecmMode",
"S");
jfieldID mCngModeID = (*env)->GetFieldID(env, JavaAecmConfig, "mCngMode",
"S");
//if any ID is NULL, return -1 for error.
if (mAecmModeID == NULL || mCngModeID == NULL){
LOGD("$$$$$$$$$$nativeSetConfig->(mAecmModeID == NULL || mCngModeID == NULL)");
return -1;
}
//get values of fields
short echoMode = (*env)->GetShortField(env, aecmConfig, mAecmModeID);
short cngMode = (*env)->GetShortField(env, aecmConfig, mCngModeID);
//set new configuration to AECM instance.
AecmConfig config;
config.echoMode = echoMode;
config.cngMode = cngMode;
LOGD("$$$$$$$$$$WebRtcAecm_set_config");
return WebRtcAecm_set_config(aecmInst, config);
}
7.编译so库可参考: Android源码下编译apk、jar与jni ndk-build可在项目\libs\查看生成文件
集成NS模块
流程严格按照AECM模块只列出不同地方
- 源码文件在\modules\audio_processing\ns
- 编写本地接口
package com.wrtcmy.webrtc.ns;
import android.util.Log;
public class NS {
private static final String TAG = "$$$NS$$$";
static {
try {
// 加载降噪库
System.loadLibrary("webrtc_ns");
} catch (UnsatisfiedLinkError e) {
e.printStackTrace();
}
}
private int mFrequency;
private int mMode;
// -----------------------------------------NS
// 定点数运算----------------------------------------------//
private int nsInstance = -1;
private boolean isNsInit = false;
/**
* 创建ns实例
*
* @return 成功时返回ns实例,失败返回-1
*/
public native int nsCreate();
/**
* 初始化ns
*
* @param frequency
* 采样率
*/
public native int nsInit(int nsInstance, int frequency);
/**
* 设置降噪策略 等级越高,效果越明显
*
* @param mode
* 0: Mild, 1: Medium , 2: Aggressive
*/
public native int nsSetPolicy(int nsInstance, int mode);
/**
* 核心处理方法 sample_H与outData_H 我不是很懂,希望有明白的可以指点下
*
* @param sample
* 低频段音频数据-输入
* @param sample_H
* 高频段音频数据-输入(demo中传的是null)
* @param outData
* 低频段音频数据-输出
* @param outData_H
* 高频段音频数据-输出(demo中传的是null)
*/
public native int nsProcess(int nsInstance, short[] sample,
short[] sample_H, short[] outData, short[] outData_H);
/**
* 销毁实例
*/
public native int nsFree(int nsInstance);
public NS useNs() {
nsInstance = nsCreate();
Log.d(TAG, "nsInstance = " + nsInstance);
return this;
}
public NS setNsConfig(int frequency, int mode) {
this.mFrequency = frequency;
this.mMode = mode;
return this;
}
public NS prepareNs() {
if (isNsInit) {
closeNs();
nsInstance = nsCreate();
}
int initStatus = nsInit(nsInstance, mFrequency);
Log.e(TAG, "nsInitStatus = " + initStatus);
isNsInit = true;
int setStatus = nsSetPolicy(nsInstance, mMode);
Log.e(TAG, "nsSetStatus = " + setStatus);
return this;
}
public int nsProcess(short[] sample, short[] sample_H, short[] outData,
short[] outData_H) {
return nsProcess(nsInstance, sample, sample_H, outData, outData_H);
}
public void closeNs() {
if (isNsInit) {
nsFree(nsInstance);
nsInstance = -1;
isNsInit = false;
}
}
// -------------------------------------------NSX
// 浮点数运算------------------------------------------//
private int nsxInstance = -1;
private boolean isNsxInit = false;
public native int nsxCreate();
public native int nsxInit(int nsxInstance, int frequency);
public native int nsxSetPolicy(int nsxInstance, int mode);
public native int nsxProcess(int nsxInstance, short[] sample,
short[] sample_H, short[] outData, short[] outData_H);
public native int nsxFree(int nsxInstance);
public NS useNsx() {
nsxInstance = nsxCreate();
Log.d(TAG, "nsxInstance = " + nsxInstance);
return this;
}
public NS setNsxConfig(int frequency, int mode) {
this.mFrequency = frequency;
this.mMode = mode;
return this;
}
public NS prepareNsx() {
if (isNsxInit) {
closeNsx();
nsxInstance = nsxCreate();
}
int initStatus = nsxInit(nsxInstance, mFrequency);
Log.e(TAG, "nsxInitStatus = " + initStatus);
isNsxInit = true;
int setStatus = nsxSetPolicy(nsxInstance, mMode);
Log.e(TAG, "nsxSetStatus = " + setStatus);
return this;
}
public int nsxProcess(short[] sample, short[] sample_H, short[] outData,
short[] outData_H) {
return nsxProcess(nsxInstance, sample, sample_H, outData, outData_H);
}
public void closeNsx() {
if (isNsxInit) {
nsxFree(nsxInstance);
nsxInstance = -1;
isNsxInit = false;
}
}
}
- ns\Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := webrtc_ns
LOCAL_CFLAGS += -DWEBRTC_POSIX
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.c)
LOCAL_LDLIBS :=-llog
include $(BUILD_SHARED_LIBRARY)
- 通过c文件实现
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_wrtcmy_webrtc_ns_NS */
#include <stdlib.h> // for NULL
#include "noise_suppression_x.h"
#include "noise_suppression.h"
#include "com_wrtcmy_webrtc_ns_NS.h"
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsCreate
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsCreate
(JNIEnv *env, jobject obj){
NsHandle* handle = NULL;
WebRtcNs_Create(&handle);
LOGD("$$$$$$$$$$WebRtcNs_Create");
return (int)handle;
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsInit
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsInit
(JNIEnv *env, jobject obj, jint nsHandler, jint frequency){
NsHandle *handler = (NsHandle *) nsHandler;
if (handler == NULL){
return -3;
}
return WebRtcNs_Init(handler,frequency);
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsSetPolicy
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsSetPolicy
(JNIEnv *env, jobject obj, jint nsHandler, jint mode){
NsHandle *handle = (NsHandle *) nsHandler;
if (handle == NULL){
return -3;
}
return WebRtcNs_set_policy(handle,mode);
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsProcess
* Signature: (I[S[S[S[S)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsProcess
(JNIEnv *env, jobject obj, jint nsHandler, jshortArray sample,
jshortArray sample_H, jshortArray out,jshortArray out_H){
NsHandle *handle = (NsHandle *) nsHandler;
if(handle == NULL){
return -3;
}
short* spframe = NULL;
short* outframe = NULL;
short* spframe_H = NULL;
short* outframe_H = NULL;
int ret = -1;
spframe = (*env)->GetShortArrayElements(env,sample, NULL);
outframe = (*env)->GetShortArrayElements(env,out, NULL);
if(sample_H != NULL){
spframe_H = (*env)->GetShortArrayElements(env,sample_H, NULL);
}
if(out_H != NULL){
outframe_H = (*env)->GetShortArrayElements(env,out_H, NULL);
}
ret = WebRtcNs_Process(handle,spframe,spframe_H,outframe,outframe_H);
(*env)->ReleaseShortArrayElements(env,sample, spframe, 0);
(*env)->ReleaseShortArrayElements(env,out, outframe, 0);
if(sample_H != NULL){
(*env)->ReleaseShortArrayElements(env,sample_H, spframe_H, 0);
}
if(out_H != NULL){
(*env)->ReleaseShortArrayElements(env,out_H, outframe_H, 0);
}
return ret;
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsFree
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsFree
(JNIEnv *env, jobject obj, jint nsHandler){
NsHandle *handle = (NsHandle *) nsHandler;
if(handle == NULL){
return -3;
}
return WebRtcNs_Free(handle);
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsxCreate
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsxCreate
(JNIEnv *env, jobject obj){
NsHandle* handle = NULL;
WebRtcNsx_Create(&handle);
return (int)handle;
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsxInit
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsxInit
(JNIEnv *env, jobject obj, jint nsxHandler, jint frequency ){
NsHandle *handler = (NsHandle *) nsxHandler;
if (handler == NULL){
return -3;
}
return WebRtcNsx_Init(handler,frequency);
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsxSetPolicy
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsxSetPolicy
(JNIEnv *env, jobject obj, jint nsxHandler, jint mode){
NsHandle *handle = (NsHandle *) nsxHandler;
if (handle == NULL){
return -3;
}
return WebRtcNsx_set_policy(handle,mode);
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsxProcess
* Signature: (I[S[S[S[S)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsxProcess
(JNIEnv *env, jobject obj, jint nsxHandler, jshortArray sample,
jshortArray sample_H, jshortArray out,jshortArray out_H){
NsHandle *handle = (NsHandle *) nsxHandler;
if(handle == NULL){
return -3;
}
short* spframe = NULL;
short* outframe = NULL;
short* spframe_H = NULL;
short* outframe_H = NULL;
int ret = -1;
spframe = (*env)->GetShortArrayElements(env,sample, NULL);
outframe = (*env)->GetShortArrayElements(env,out, NULL);
if(sample_H != NULL){
spframe_H = (*env)->GetShortArrayElements(env,sample_H, NULL);
}
if(out_H != NULL){
outframe_H = (*env)->GetShortArrayElements(env,out_H, NULL);
}
ret = WebRtcNsx_Process(handle,spframe,spframe_H,outframe,outframe_H);
(*env)->ReleaseShortArrayElements(env,sample, spframe, 0);
(*env)->ReleaseShortArrayElements(env,out, outframe, 0);
if(sample_H != NULL){
(*env)->ReleaseShortArrayElements(env,sample_H, spframe_H, 0);
}
if(out_H != NULL){
(*env)->ReleaseShortArrayElements(env,out_H, outframe_H, 0);
}
return ret;
}
/*
* Class: com_wrtcmy_webrtc_ns_NS
* Method: nsxFree
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_com_wrtcmy_webrtc_ns_NS_nsxFree
(JNIEnv *env, jobject obj, jint nsxHandler){
NsHandle *handle = (NsHandle *) nsxHandler;
if(handle == NULL){
return -3;
}
return WebRtcNsx_Free(handle);
}
需要源码请留言
本文地址:https://blog.csdn.net/chen1103978255/article/details/109638627
上一篇: C++ 读入文件中的中文字符