不会没有关系,网上有很多相关的文章,经过查找知道手机端可用方案大概有如下几种: 参考文章: speex现在分成两部分了,主要的speex包含编码解码 ,另外一部分声学处理就是speexdsp专门用来处理回声消除 将用红色箭头标识的两文件夹复制到android工程的cpp(jni)目录下的speexdsp目录中: 这里注意了 复制都完成了,就把libseexdsp中的几个test文件删除,不然会有些麻烦,不删除也没有问题哈。主要是这几个test文件都有main函数。 另外,还得在使用我另外编译iconv中使用的方式先configurate下,生成config.h文件。把这个config.h文件也复制到speexdsp目录的include目录中 我已经将所有源代码上传于github,各位可以自行下载修改,所有speex支持的参数设置,我已经通过jni公开。只是有很多参数 我也是不得要领,不知道有什么作为! 本地验证呢,这个nn,与tail是最难确认的了。 有人使用speexdsp作了测试,有人说效果可以,实际环境中使用效果如何,有待验证。
前言
本来我只是个纯写一般app的码农,奈何进了这家以音视频为主的公司。刚进公司时,还有好些牛人都没有离职(在 音视频方面浸淫以久的同事)。那关于音视频方面的什么传输库,h264,aac编解码等方面的事,有专门的人员来写和维 护,我作为移动端的开发人员,只需要用他们提供的传输库,使用他们在pc端的功能模块就可以了。我也可以快乐的 下班。可公司发展不景气(没有挣到钱),接下来你们懂的。(人员各种流失。。。)最后,移动原生开发的就剩下 两人(我也算在里面)。ios方面的开发,全走了。交接工作全给了我了,OMY,我对苹果开发可是啥也不会呀。只希 望公司能接下来招几个搞ios的人吧。。。可是过了很长的时间,都没有招人,慢慢的,我也了解到领导就没有再招人 的意思。。很明显,交接给你了(我),那么ios的工作就你来干了。。。。我真是。。。。好吧,说远了!回到主 题,因为有些android手机对回声消除不太好,老板就要求我能不能解决下这个问题。我去,我是谁,,我在哪。。我 不会呀。但总不能直接说不会吧。只能硬着头皮上了。。
上网
先谈speex
说干就干,反正我自己现在(以后)也是没有能力写出回声消除算法的(那都是天才巨人干的事)。我能做的就是站在巨人的肩上。
下载speexdsp
下传送门:
解压源代码
export NDK=/Users/xxx/Library/Android/android-ndk-r20 export ANDROID_NDK=/Users/xxx/Library/Android/android-ndk-r20 export NDK=/Users/xxx/Library/Android/android-ndk-r20 export PATH=${PATH}:${ANDROID_NDK} export PATH=${PATH}:${NDK} export ANDROID_TOOLS=/Users/xxx/Library/Android/sdk/platform-tools export ANDROID_HOME=/Users/xxx/Library/Android/sdk export PATH=${PATH}:${ANDROID_HOME} export ANDROID_TOOLS export PATH=${PATH}:${ANDROID_TOOLS} #PATH=/bin:/usr/bin:/usr/local/bin:${PATH} # darwin-x86_64 是Mac的路径,实际按目录结构修改 export PATH="$NDK:$NDK/shader-tools/darwin-x86_64:$NDK/build/tools:$PATH" # 预设值,待会才生成的目录 export SYSROOT=~/my-android-toolchain/sysroot export PATH=~/my-android-toolchain/bin:$PATH export CC=arm-linux-androideabi-gcc # or export CC=clang export CXX=arm-linux-androideabi-g++ # or export CXX=clang++ export CXXFLAGS="-lstdc++" export CPPFLAGS="-lstdc++" export CC="arm-linux-androideabi-gcc --sysroot=$SYSROOT" export LD="arm-linux-androideabi-ld" export AR="arm-linux-androideabi-ar" export RANLIB="arm-linux-androideabi-ranlib" export STRIP="arm-linux-androideabi-strip" export CPP="arm-linux-androideabi-gcc -E" cd ~ mkdir my-android-toolchain $NDK/build/tools/make-standalone-toolchain.sh --arch=arm --install-dir=~/my-android-toolchain --platform=android-21 --stl=gnustl cd ~/Downloads/speexdsp-1.2rc3 ./configurate --host=arm-linux-eabi
接下来就是编写CMakeLists.txt及jni中间文件
// // Created by vnetoo on 2020/5/8. // #include "echo_config.h" #ifndef SPEEX_AUDIO_ECHO_H #define SPEEX_AUDIO_ECHO_H #define NN 128 //帧长 一般都是 80,160,320, #define TAIL 1024 //尾长 一般都是 80*25 ,160*25 ,320*25 #define ECHO_ERROR -1 #define ECHO_OK 0 // defined speexEcho struct typedef struct SpeexEcho{ SpeexEchoState* st; SpeexPreprocessState* den; int aec_init_flag; pthread_mutex_t mutex; int enable_echo; int frame_size; int enable_vad; }SpeexEcho; /** * 初始化回声消除 * @param context * @param frameSize * @param filterSize * @param sampleRate * @return */ int echo_init(SpeexEcho* context,const unsigned short frameSize ,const unsigned short filterSize,const unsigned short sampleRate); /** * 设置回声消除参数 * @param context * @param key * @param value * @ 0/1 */ int echo_set_ctl(SpeexEcho* context,const unsigned short key , int value); /** * 获取回声消除器的参数 * @param context * @param key * @param result * @return */ int echo_get_ctl(SpeexEcho* context,const unsigned short key , void* result); /*** * 设置噪声参数 * @param context * @param key * @param value * @return */ int echo_set_preprocess_ctl(SpeexEcho* context,const unsigned short key , void* value); int echo_get_preprocess_ctl(SpeexEcho* context,const unsigned short key , void* value); /*** * 处理数据 * @param context * @param near mic数据 * @param far 播放数据 * @param out 处理之后的数据 * @return */ int echo_sync_process(const SpeexEcho* context,unsigned short* near,unsigned short* far, unsigned short* out,size_t size); int echo_denoise_only(const SpeexEcho* context,unsigned short* near); int echo_asyn_process_near(const SpeexEcho* context,unsigned short* near,unsigned short *out); int echo_asyn_process_far(const SpeexEcho* context,unsigned short* far); /** * 清除,释放 */ void echo_distroy(SpeexEcho* context); #endif //SPEEX_AUDIO_ECHO_H
// // Created by vnetoo on 2020/5/8. // #include "include/audio_echo.h" int echo_init(SpeexEcho *context, const unsigned short frameSize, const unsigned short filterSize, const unsigned short sampleRate) { pthread_mutex_lock(&(context->mutex)); unsigned short fs = frameSize; if (fs <= 0) { return ECHO_ERROR; } unsigned short fl = filterSize; if (fl <= 0) { return ECHO_ERROR; } int mSampleRate = sampleRate; if(mSampleRate<=0){ return ECHO_ERROR; } context->st = speex_echo_state_init(fs, fl); ASSERT(context->st != NULL, "init echo error"); if (context->st == NULL) { LOGE("init echo error with frameSize:%d,filterSize:%d", fs, fl); return ECHO_ERROR; } context->den = speex_preprocess_state_init(fs, sampleRate); ASSERT(context->den != NULL, "init preprocess with sampleRate: %d, error", mSampleRate); int flag = -1; flag = speex_echo_ctl(context->st, SPEEX_ECHO_SET_SAMPLING_RATE, &mSampleRate); ASSERT(flag == 0, "set sampleRate for echo error"); flag = speex_preprocess_ctl(context->den, SPEEX_PREPROCESS_SET_ECHO_STATE, context->st); ASSERT(flag == 0, "set aec proprocess to st error") context->aec_init_flag = flag == 0 ? 1 : 0; pthread_mutex_unlock(&(context->mutex)); LOGI("init speex aec success"); return ECHO_OK; } int echo_set_ctl(SpeexEcho *context, const unsigned short key, int value) { ASSERT(context != NULL, "speexEcho is NULL") if (context != NULL && context->aec_init_flag == 1) { int result = speex_echo_ctl(context->st, key, &value); if (result == 0) { return ECHO_OK; } else { LOGE("set speex_echo_ctl(%d,%d) unknow key", key, value); } } return ECHO_ERROR; } int echo_get_ctl(SpeexEcho *context, const unsigned short key, void *result) { ASSERT(context != NULL, "speexEcho is NULL") if (context != NULL && context->aec_init_flag == 1) { int result = speex_echo_ctl(context->st, key, &result); if (result == 0) { return ECHO_OK; } else { LOGE("get speex_echo_ctl(%d,%d) unknow key", key, result); } } return ECHO_ERROR; } int echo_set_preprocess_ctl(SpeexEcho *context, const unsigned short key, void *value) { ASSERT(context != NULL, "speexEcho is NULL") if (context != NULL && context->aec_init_flag == 1) { pthread_mutex_lock(&(context->mutex)); int result = speex_preprocess_ctl(context->den, key, value); if(key == SPEEX_PREPROCESS_SET_NOISE_SUPPRESS){ int* v = (int*)value; LOGI("SPEEX_PREPROCESS_SET_NOISE_SUPPRESS=>%d result:%d",*v,result); }else if(key == SPEEX_PREPROCESS_SET_DENOISE){ int* v = (int*)value; LOGI("SPEEX_PREPROCESS_SET_DENOISE=>%d result:%d",*v,result); } else if(key == SPEEX_PREPROCESS_SET_AGC){ int* v = (int*)value; LOGI("SPEEX_PREPROCESS_SET_AGC=>%d result:%d",*v,result); }else if(key == SPEEX_PREPROCESS_SET_DEREVERB){ int* v = (int*)value; LOGI("SPEEX_PREPROCESS_SET_DEREVERB=>%d result:%d",*v,result); }else if(key == SPEEX_PREPROCESS_SET_VAD){ int* v = (int*)value; &context->enable_vad == *v; LOGI("SPEEX_PREPROCESS_SET_VAD=>%d result:%d",*v,result); }else if(key == SPEEX_PREPROCESS_SET_NOISE_SUPPRESS){ int* v = (int*)value; LOGI("SPEEX_PREPROCESS_SET_NOISE_SUPPRESS=>%d result:%d",*v,result); }else if(key == SPEEX_PREPROCESS_SET_AGC_LEVEL){ int* v = (int*)value; LOGI("SPEEX_PREPROCESS_SET_AGC_LEVEL=>%d result:%d",*v,result); } pthread_mutex_unlock(&(context->mutex)); if (result == 0) { return ECHO_OK; } else { LOGE("set echo_set_preprocess_ctl(%d) unknow key", key); } } return ECHO_ERROR; } int echo_get_preprocess_ctl(SpeexEcho *context, const unsigned short key, void *result) { ASSERT(context != NULL, "speexEcho is NULL") if (context != NULL && context->aec_init_flag == 1) { int ret = speex_preprocess_ctl(context->den, key, result); if (ret == 0) { return ECHO_OK; } else { LOGE("get echo_set_preprocess_ctl(%d) unknow key", key); } } return ECHO_ERROR; } int echo_sync_process(const SpeexEcho *context, unsigned short *near, unsigned short *far, unsigned short *out,size_t size) { ASSERT(context != NULL, "speexEcho is NULL") ASSERT(near != NULL, "mic record data is NULL") ASSERT(far != NULL, "playData is NULL") ASSERT(out != NULL, "outputBuffer is NULL") if (context != NULL && context->aec_init_flag == 1) { pthread_mutex_lock(&(context->mutex)); // speex_preprocess_run(context->den, far); speex_echo_cancellation(context->st, near, far, out); int result = speex_preprocess_run(context->den, out); pthread_mutex_unlock(&(context->mutex)); return result; } return ECHO_ERROR; } int echo_denoise_only(const SpeexEcho* context,unsigned short* near){ ASSERT(near != NULL, "near data is NULL") pthread_mutex_lock(&(context->mutex)); int result = speex_preprocess_run(context->den, near); pthread_mutex_unlock(&(context->mutex)); return result; } int echo_asyn_process_near(const SpeexEcho* context,unsigned short* near,unsigned short *out){ if (context != NULL && context->aec_init_flag == 1) { pthread_mutex_lock(&(context->mutex)); speex_echo_capture(context->st,near,out); pthread_mutex_unlock(&(context->mutex)); return ECHO_OK; } return ECHO_ERROR; } int echo_asyn_process_far(const SpeexEcho* context,unsigned short* far){ if (context != NULL && context->aec_init_flag == 1) { pthread_mutex_lock(&(context->mutex)); speex_echo_playback(context->st,far); pthread_mutex_unlock(&(context->mutex)); return ECHO_OK; } return ECHO_ERROR; } void echo_distroy(SpeexEcho *context) { if (context != NULL && context->aec_init_flag == 1) { pthread_mutex_lock(&(context->mutex)); speex_preprocess_state_destroy(context->den); speex_echo_state_destroy(context->st); context->aec_init_flag = 0; pthread_mutex_unlock(&(context->mutex)); LOGE("release speex echo"); } }
// // Created by vnetoo on 2020/5/8. // #include <stdlib.h> #include <assert.h> #include <jni.h> #include <string.h> #include <pthread.h> #include "include/audio_echo.h" #define ClassName "com/vnetoo/speex/echo/SpeexEcho" #define EchoPk(method) Java_com_vnetoo_speex_echo_SpeexEcho_##method static SpeexEcho echo; static short *out; int debug = 1; inline void throwException(JNIEnv *env, const char *clasz, const char *errorMsg); void throwException(JNIEnv *env, const char *clasz, const char *errorMsg) { jclass newExcCls; (*env)->ExceptionDescribe(env); (*env)->ExceptionClear(env); newExcCls = (*env)->FindClass(env, clasz); if (newExcCls != NULL) { (*env)->ThrowNew(env, newExcCls, errorMsg); } } JNIEXPORT jint JNICALL EchoPk(aecInit)(JNIEnv *env, jclass jclasz, jint frameSize, jint filterSize, jint sampleRate) { int result = echo_init(&echo, frameSize, filterSize, sampleRate); if (result == ECHO_ERROR) { throwException(env, "java/lang/IllegalStateException", "init aec error"); } echo.frame_size = frameSize; LOGI("speex jni init aec success"); return result; } JNIEXPORT jint JNICALL EchoPk(aec_1set_1feature)(JNIEnv *env, jclass jclasz, jint key, jint value) { if (echo.aec_init_flag) { return echo_set_ctl(&echo, key, value); } return ECHO_ERROR; } JNIEXPORT jint JNICALL EchoPk(aec_1set_1other_1feature__II)(JNIEnv *env, jclass clazz, jint key, jint value) { if (echo.aec_init_flag) { int v = value; return echo_set_preprocess_ctl(&echo, key, &v); } return ECHO_ERROR; } JNIEXPORT jint JNICALL EchoPk(aec_1set_1other_1feature__IF)(JNIEnv *env, jclass clazz, jint key, jfloat value) { if (echo.aec_init_flag) { float v = value; return echo_set_preprocess_ctl(&echo, key, &v); } return ECHO_ERROR; } JNIEXPORT jint JNICALL EchoPk(aec_1process)(JNIEnv *env, jclass clazz, jbyteArray near, jbyteArray far,jbyteArray out) { jbyteArray ret = NULL; jbyte *nearData = (*env)->GetByteArrayElements(env, near, JNI_FALSE); jbyte *fearData = (*env)->GetByteArrayElements(env, far, JNI_FALSE); jbyte *outData = (*env)->GetByteArrayElements(env, out, JNI_FALSE); int result = 0; bool needRet = false; if(echo.enable_echo == 1){ result= echo_sync_process(&echo, nearData, fearData, outData, echo.frame_size); LOGI("echo canncel :%d", result ); } else{ result = echo_denoise_only(&echo,nearData); LOGI("echo_denoise_only:%d", result ); } (*env)->ReleaseByteArrayElements(env, near, nearData, JNI_FALSE); (*env)->ReleaseByteArrayElements(env, far, fearData, JNI_FALSE); (*env)->ReleaseByteArrayElements(env, out, outData, JNI_FALSE); return result; } JNIEXPORT void JNICALL EchoPk(destory)(JNIEnv *env, jclass clazz) { // pthread_mutex_lock(&(echo.mutex)); echo_distroy(&echo); free(out); // pthread_mutex_unlock(&(echo.mutex)); out = NULL; } JNIEXPORT jint JNICALL EchoPk(aec_1set_1enable_1echo)(JNIEnv *env, jclass clazz, jboolean enable) { pthread_mutex_lock(&(echo.mutex)); echo.enable_echo = enable ? 1 : 0; LOGI("echo.enable_echo=%d", echo.enable_echo); pthread_mutex_unlock(&(echo.mutex)); return ECHO_OK; } JNIEXPORT jfloat JNICALL EchoPk(aec_1get_1other_1float_1feature)(JNIEnv *env, jclass clazz, jint key) { pthread_mutex_lock(&(echo.mutex)); float value = 0; echo_get_preprocess_ctl(&(echo),key,&value); pthread_mutex_unlock(&(echo.mutex)); return value; } JNIEXPORT jint JNICALL EchoPk(aec_1get_1other_1int_1feature)(JNIEnv *env, jclass clazz, jint key) { pthread_mutex_lock(&(echo.mutex)); int value = 0; echo_get_preprocess_ctl(&(echo),key,&value); pthread_mutex_unlock(&(echo.mutex)); return value; } JNIEXPORT jint JNICALL Java_com_vnetoo_speex_echo_SpeexEcho_ProcessStream(JNIEnv *env, jclass clazz, jbyteArray data, jint offset, jint len) { jbyte *nearData = (*env)->GetByteArrayElements(env, data, JNI_FALSE); short* out = (short*)malloc(len); memset(out,0,len); echo_asyn_process_near(&echo,nearData,out); memcpy(nearData,out,len); free(out); (*env)->ReleaseByteArrayElements(env, data, nearData, JNI_FALSE); return 0; } JNIEXPORT jint JNICALL Java_com_vnetoo_speex_echo_SpeexEcho_ProcessReverseStream(JNIEnv *env, jclass clazz, jbyteArray far_end, jint offset, jint len) { jbyte *nearData = (*env)->GetByteArrayElements(env, far_end, JNI_FALSE); echo_asyn_process_far(&echo,nearData); (*env)->ReleaseByteArrayElements(env, far_end, nearData, JNI_FALSE); return 0; }
package com.vnetoo.speex.echo; class SpeexEcho { public static native int aecInit(int frame_size, int filter_length, int sampling_rate) throws IllegalStateException; public static native int aec_set_enable_echo(boolean enable); public static native int aec_set_feature(int key,int value); public static native int aec_set_other_feature(int key,int value); public static native int aec_set_other_feature(int key,float value); public static native float aec_get_other_float_feature(int key); public static native int aec_get_other_int_feature(int key); public static native int aec_process(byte[] near, byte[] far,byte[] out); public static native int ProcessStream(byte[] data,int offset, int len); public static native int ProcessReverseStream(byte[] far_end,int offset, int len); public static native void destory(); // public static native int aec_get_feature(int key); /** * Set preprocessor denoiser state */ public static final int SPEEX_PREPROCESS_SET_DENOISE = 0; /** * Get preprocessor denoiser state */ public static final int SPEEX_PREPROCESS_GET_DENOISE = 1; /** * Set preprocessor Automatic Gain Control state */ public static final int SPEEX_PREPROCESS_SET_AGC = 2; /** * Get preprocessor Automatic Gain Control state */ public static final int SPEEX_PREPROCESS_GET_AGC = 3; /** * Set preprocessor Voice Activity Detection state */ public static final int SPEEX_PREPROCESS_SET_VAD = 4; /** * Get preprocessor Voice Activity Detection state */ public static final int SPEEX_PREPROCESS_GET_VAD = 5; /** * Set preprocessor Automatic Gain Control level (float) */ public static final int SPEEX_PREPROCESS_SET_AGC_LEVEL = 6; /** * Get preprocessor Automatic Gain Control level (float) */ public static final int SPEEX_PREPROCESS_GET_AGC_LEVEL = 7; /** * Set preprocessor dereverb state */ public static final int SPEEX_PREPROCESS_SET_DEREVERB = 8; /** * Get preprocessor dereverb state */ public static final int SPEEX_PREPROCESS_GET_DEREVERB = 9; /** * Set preprocessor dereverb level */ public static final int SPEEX_PREPROCESS_SET_DEREVERB_LEVEL = 10; /** * Get preprocessor dereverb level */ public static final int SPEEX_PREPROCESS_GET_DEREVERB_LEVEL = 11; /** * Set preprocessor dereverb decay */ public static final int SPEEX_PREPROCESS_SET_DEREVERB_DECAY = 12; /** * Get preprocessor dereverb decay */ public static final int SPEEX_PREPROCESS_GET_DEREVERB_DECAY = 13; /** * Set probability required for the VAD = to go from silence to voice */ public static final int SPEEX_PREPROCESS_SET_PROB_START = 14; /** * Get probability required for the VAD = to go from silence to voice */ public static final int SPEEX_PREPROCESS_GET_PROB_START = 15; /** * Set probability required for the VAD = to stay in the voice state (integer percent) */ public static final int SPEEX_PREPROCESS_SET_PROB_CONTINUE = 16; /** * Get probability required for the VAD = to stay in the voice state (integer percent) */ public static final int SPEEX_PREPROCESS_GET_PROB_CONTINUE = 17; /** * Set maximum attenuation of the noise in dB = (negative number) */ public static final int SPEEX_PREPROCESS_SET_NOISE_SUPPRESS = 18; /** * Get maximum attenuation of the noise in dB = (negative number) */ public static final int SPEEX_PREPROCESS_GET_NOISE_SUPPRESS = 19; /** * Set maximum attenuation of the residual echo in dB = (negative number) */ public static final int SPEEX_PREPROCESS_SET_ECHO_SUPPRESS = 20; /** * Get maximum attenuation of the residual echo in dB = (negative number) */ public static final int SPEEX_PREPROCESS_GET_ECHO_SUPPRESS = 21; /** * Set maximum attenuation of the residual echo in dB = when near end is active (negative number) */ public static final int SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE = 22; /** * Get maximum attenuation of the residual echo in dB = when near end is active (negative number) */ public static final int SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE = 23; /** * Set the corresponding echo canceller state so that residual echo suppression can be performed (NULL = for no residual echo suppression) */ public static final int SPEEX_PREPROCESS_SET_ECHO_STATE = 24; /** * Get the corresponding echo canceller state */ public static final int SPEEX_PREPROCESS_GET_ECHO_STATE = 25; /** * Set maximal gain increase in dB/second (int32) */ public static final int SPEEX_PREPROCESS_SET_AGC_INCREMENT = 26; /** * Get maximal gain increase in dB/second (int32) */ public static final int SPEEX_PREPROCESS_GET_AGC_INCREMENT = 27; /** * Set maximal gain decrease in dB/second (int32) */ public static final int SPEEX_PREPROCESS_SET_AGC_DECREMENT = 28; /** * Get maximal gain decrease in dB/second (int32) */ public static final int SPEEX_PREPROCESS_GET_AGC_DECREMENT = 29; /** * Set maximal gain in dB = (int32) */ public static final int SPEEX_PREPROCESS_SET_AGC_MAX_GAIN = 30; /** * Get maximal gain in dB = (int32) */ public static final int SPEEX_PREPROCESS_GET_AGC_MAX_GAIN = 31; /* Can't set loudness */ /** * Get loudness */ public static final int SPEEX_PREPROCESS_GET_AGC_LOUDNESS = 33; /* Can't set gain */ /** * Get current gain (int32 percent) */ public static final int SPEEX_PREPROCESS_GET_AGC_GAIN = 35; /* Can't set spectrum size */ /** * Get spectrum size for power spectrum (int32) */ public static final int SPEEX_PREPROCESS_GET_PSD_SIZE = 37; /* Can't set power spectrum */ /** * Get power spectrum (int32[] of squared values) */ public static final int SPEEX_PREPROCESS_GET_PSD = 39; /* Can't set noise size */ /** * Get spectrum size for noise estimate (int32) */ public static final int SPEEX_PREPROCESS_GET_NOISE_PSD_SIZE = 41; /* Can't set noise estimate */ /** * Get noise estimate (int32[] of squared values) */ public static final int SPEEX_PREPROCESS_GET_NOISE_PSD = 43; /* Can't set speech probability */ /** * Get speech probability in last frame (int32). */ public static final int SPEEX_PREPROCESS_GET_PROB = 45; /** * Set preprocessor Automatic Gain Control level (int32) */ public static final int SPEEX_PREPROCESS_SET_AGC_TARGET = 46; /** * Get preprocessor Automatic Gain Control level (int32) */ public static final int SPEEX_PREPROCESS_GET_AGC_TARGET = 47; }
使用及例子及所有源码
官方例子:
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "speex/speex_echo.h" #include "speex/speex_preprocess.h" #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define NN 128 #define TAIL 1024 int main(int argc, char **argv) { FILE *echo_fd, *ref_fd, *e_fd; short echo_buf[NN], ref_buf[NN], e_buf[NN]; SpeexEchoState *st; SpeexPreprocessState *den; int sampleRate = 8000; if (argc != 4) { fprintf(stderr, "testecho mic_signal.sw speaker_signal.sw output.swn"); exit(1); } echo_fd = fopen(argv[2], "rb"); ref_fd = fopen(argv[1], "rb"); e_fd = fopen(argv[3], "wb"); st = speex_echo_state_init(NN, TAIL); den = speex_preprocess_state_init(NN, sampleRate); speex_echo_ctl(st, SPEEX_ECHO_SET_SAMPLING_RATE, &sampleRate); speex_preprocess_ctl(den, SPEEX_PREPROCESS_SET_ECHO_STATE, st); while (!feof(ref_fd) && !feof(echo_fd)) { fread(ref_buf, sizeof(short), NN, ref_fd); fread(echo_buf, sizeof(short), NN, echo_fd); speex_echo_cancellation(st, ref_buf, echo_buf, e_buf); speex_preprocess_run(den, e_buf); fwrite(e_buf, sizeof(short), NN, e_fd); } speex_echo_state_destroy(st); speex_preprocess_state_destroy(den); fclose(e_fd); fclose(echo_fd); fclose(ref_fd); return 0; }
结束
兄弟点个赞!!
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算