speex 在android上降噪与回音消除使用

        音频的录制,播放传输,势必离不开音频的降噪和回音消除,特别是在语音的双向对讲过程中,回音消除是必须跨越的门槛,总结在jni代码中,代码实现如下,具体调试流程,参数设置则只能说多次测试的结果。配合speex源码编译成so后即可使用。
#include <stdio.h>
#include <jni.h>
#include <string.h>
#include "speex/speex_preprocess.h"
#include "speex/speex_echo.h"
#include <stdio.h>
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "keymatch", __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, "keymatch", __VA_ARGS__)


SpeexPreprocessState *st;
int nInitSuccessFlag = 0;
SpeexEchoState* m_pState;
SpeexPreprocessState* m_pPreprocessorState;
int      m_nFrameSize;
int      m_nFilterLen;
int      m_nSampleRate;
int 	 iArg;

jint Java_com_stream_Speex_CancelNoiseInit(JNIEnv* env,jobject this,jint frame_size, jint sample_rate)
{

   int i;
   int count=0;
   float f;

   st = speex_preprocess_state_init(frame_size/2, sample_rate);
   
   i=1;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i);//降噪
   i = -25;//负的32位整数
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS,&i); //设置噪声的dB
   
   i=1;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i);//增益
   i=24000;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
   i=0;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i);
   f=.0;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
   f=.0;
   speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
   LOGI("speex init");
   return 1;
}

jint Java_com_stream_Speex_CancelNoisePreprocess(JNIEnv* env,jobject this,jbyteArray buffer)
{
    char * inbuffer = (*env)->GetByteArrayElements(env,buffer, 0);

    short *in = inbuffer;
    LOGI("speex change 000");

    int vad = speex_preprocess_run(st, in);

    (*env)->ReleaseByteArrayElements(env,buffer, (jbyte *)inbuffer, 0);
    LOGI("speex change ok");
    return vad;
}

jint Java_com_stream_Speex_CancelNoiseDestroy(JNIEnv* env,jobject this)
{
    if(st != NULL){
       speex_preprocess_state_destroy(st);
	    st = NULL;
	}
    LOGI("speex destory");
    return 1;
}


//回声消除部分代码

     //初始化回音消除参数
      /*
       * jint frame_size        帧长      一般都是  80,160,320
       * jint filter_length     尾长      一般都是  80*25 ,160*25 ,320*25
       * jint sampling_rate     采样频率  一般都是  8000,16000,32000
       * 比如初始化 
       *  InitAudioAEC(80, 80*25,8000)   //8K,10毫秒采样一次
       *  InitAudioAEC(160,160*25,16000) //16K,10毫秒采样一次
       *  InitAudioAEC(320,320*25,32000) //32K,10毫秒采样一次
       */
jint Java_com_audioaec_talkdemo_AudioAEC_InitAudioAEC( JNIEnv* env,jobject thiz,jint frame_size,jint filter_length,jint sampling_rate)
{
	if(nInitSuccessFlag == 1)
	return 1 ;

	if (frame_size<=0 || filter_length<=0 || sampling_rate<=0)
	{
	  m_nFrameSize  =160;
	  m_nFilterLen  = 160*8;
	  m_nSampleRate = 8000;
	}
	else
	{
	  m_nFrameSize  =frame_size;
	  m_nFilterLen  = filter_length;
	  m_nSampleRate = sampling_rate;
	}

	m_pState = speex_echo_state_init(m_nFrameSize, m_nFilterLen); 
	if(m_pState == NULL)
	return -1 ;

	m_pPreprocessorState = speex_preprocess_state_init(m_nFrameSize, m_nSampleRate); 
	if(m_pPreprocessorState == NULL)
	return -2 ;

	iArg = m_nSampleRate;
	speex_echo_ctl(m_pState, SPEEX_ECHO_SET_SAMPLING_RATE, &iArg);
	speex_preprocess_ctl(m_pPreprocessorState, SPEEX_PREPROCESS_SET_ECHO_STATE, m_pState);
	nInitSuccessFlag = 1 ;
	return 1 ;
}

/*
 参数:
  jbyteArray recordArray  录音数据
  jbyteArray playArray    放音数据 
  jbyteArray szOutArray
*/
jint Java_com_audioaec_talkdemo_AudioAEC_AudioAECProc(JNIEnv* env,jobject thiz,jbyteArray recordArray,jbyteArray playArray,jbyteArray szOutArray)
{
	if(nInitSuccessFlag == 0)
	return 0 ;

	jbyte* recordBuffer = (jbyte *)(*env)->GetByteArrayElements(env,recordArray, 0);
	jbyte* playBuffer = (jbyte *)(*env)->GetByteArrayElements(env,playArray, 0);
	jbyte* szOutBuffer = (jbyte *)(*env)->GetByteArrayElements(env,szOutArray, 0);

	speex_echo_cancellation(m_pState,(spx_int16_t *)recordBuffer,
	   (spx_int16_t *)playBuffer,(spx_int16_t *)szOutBuffer); 
	int flag=speex_preprocess_run(m_pPreprocessorState,(spx_int16_t *)szOutBuffer);  

	(*env)->ReleaseByteArrayElements(env,recordArray,recordBuffer,0) ;
	(*env)->ReleaseByteArrayElements(env,playArray,playBuffer,0) ;
	(*env)->ReleaseByteArrayElements(env,szOutArray,szOutBuffer,0) ;

	return 1 ;
}

    //退出
jint Java_com_sosea_xmeeting_SpeexAEC_ExitSpeexDsp( JNIEnv* env,jobject thiz)
{
	if(nInitSuccessFlag == 0)
	return 0 ;

	if (m_pState != NULL) 
	{ 
		speex_echo_state_destroy(m_pState); 
		m_pState = NULL; 
	} 
	if (m_pPreprocessorState != NULL) 
	{ 
		speex_preprocess_state_destroy(m_pPreprocessorState); 
		m_pPreprocessorState = NULL; 
	} 

	 nInitSuccessFlag = 0 ;

	 return 1 ;
}



   

猜你喜欢

转载自blog.csdn.net/qq_27688259/article/details/80525215