(笔记)
首先配置speex到环境请看 http://blog.csdn.net/jingwen3699/article/details/8332079
按照以上方式配好后可以看到jni文件夹中有个speex_jni.cpp文件,此文件与speex.java文件对应。导入自己项目中时将
speex_jni.cpp文件中方法中对应的包名改为speex.java的包名。以免引起之后的.so文件生成无反应。
speex_jni.cpp部分代码
配置完成后使用NDK生成.so文件
在speex.java文件中已经提供好对应的初始化、编解码方法。下面对这几种方法做使用说明
class Speex {
/* quality
* 1 : 4kbps (very noticeable artifacts, usually intelligible)
* 2 : 6kbps (very noticeable artifacts, good intelligibility)
* 4 : 8kbps (noticeable artifacts sometimes)
* 6 : 11kpbs (artifacts usually only noticeable with headphones)
* 8 : 15kbps (artifacts not usually noticeable)
*/
private static final int DEFAULT_COMPRESSION = 8;
Speex() {
}
//初始化方法
public void init() {
load();
open(DEFAULT_COMPRESSION);
}
private void load() {
try {
//加载对应我们刚刚生成的.so文件。这里speex指的是libs文件夹中对应硬件构架文件夹下的的libsspeex.so
//至于前置的libs是生成前自动补充的
System.loadLibrary("speex");
} catch (Throwable e) {
e.printStackTrace();
}
}
//设置默认压缩率
public native int open(int compression);
public native int getFrameSize();
//解码
public native int decode(byte encoded[], short lin[], int size);
//编码
public native int encode(short lin[], int offset, byte encoded[], int size);
public native void close();
}
初始化代码
//获取音频的最小缓冲区(如果不需要可以不写)
int audioBufferSize = AudioRecord.getMinBufferSize(hz, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT);
//创建音频对象(录音孔,采样率,声道,音频格式,缓冲区)
ar = new AudioRecord(MediaRecorder.AudioSource.MIC, hz, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, audioBufferSize);
编码代码public native int encode(short lin[], int offset, byte encoded[], int size);
void send(){ //创建两个数组 int num = 0; byte[] buffer = new byte[160]; short[] ss = new short[160]; //读取AudioRecord对象中的数据到数组(记得read前先 ar.startRecording() 打开录音) num = ar.read(ss, 0, 160); //使用Speex编码方法 sx.encode(ss, 0, buffer, num); if(num>0){ //最后调用流来对编码后的buffer数组进行保存或传输 send2(buffer, "172.16.77.4", 60001); } }
解码方法
public native int decode(byte encoded[], short lin[], int size);与编码类似 依次传入被编码数组、解码后数组、以及大小
完成这些之后就可以获取到真正的音频数据了。但是在播放过程中我测试出来speex只是对音频数据进行相应的编解码,未对音频做处理。至于降噪、回声消除、增益、静音检测需要做以下初始化调用。
首先,打开项目-->jni-->speex_jni.cpp 找到 open 方法加入以下代码。
extern "C"
JNIEXPORT jint JNICALL Java_com_example_audiotest1_Speex_open
(JNIEnv *env, jobject obj, jint compression) {
int tmp;
if (codec_open++ != 0)
return (jint)0;
speex_bits_init(&ebits);
speex_bits_init(&dbits);
//加入以下代码=======================
SpeexPreprocessState * m_st;
SpeexEchoState* s_es;
m_st=speex_preprocess_state_init(160, 8000);
int denoise = 1;
int noiseSuppress = -25;
speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_DENOISE, &denoise); //降噪
speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &noiseSuppress); //设置噪声
int agc = 1;
int q=24000;
speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_AGC, &agc);//增益
speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_AGC_LEVEL,&q);
int vad = 1;
int vadProbStart = 80;
int vadProbContinue = 65;
speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_VAD, &vad); //静音检测
speex_preprocess_ctl(m_st, SPEEX_PREPROCESS_SET_PROB_START , &vadProbStart); //Set
s_es = speex_echo_state_init( 160, 8000 );
int __sample_rate = 4000;
speex_echo_ctl( s_es, SPEEX_ECHO_SET_SAMPLING_RATE, &__sample_rate );//回音消除
speex_preprocess_ctl( m_st, SPEEX_PREPROCESS_SET_ECHO_STATE, s_es );
//=========================================
// ses = speex_encoder_init( &speex_nb_mode);
enc_state = speex_encoder_init(&speex_nb_mode);
dec_state = speex_decoder_init(&speex_nb_mode);
tmp = compression;
speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &tmp);
speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE, &enc_frame_size);
speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &dec_frame_size);
return (jint)0;
}
因为speex源码中存在上述音频处理方法,我们在初始化speex的时候调用这些方法传入适当参数就可以达到效果。
DEMO下载:http://download.csdn.net/detail/qq_32274413/9607268 (需在代码中更改 ip port)
如有问题可以联系我的qq:948366879