Android ilbc 语音对话示范之代码搭建
基于上一篇中提到的google网站的一份代码(http://code.google.com/p/android-ilbc/)这个需要git下载,我上传了一份在CSDN,
稍微进行了修改:下载链接:(http://download.csdn.net/detail/ranxiedao/4450917)。
现在开始讲解代码结构搭建环节:
要求:
环境:Ubuntu 12.04 (其他Linux环境皆可),Android 2.2 及以上系统
工具:Elicpse 3.7 ,Android NDK r7 ,Android SDK r7
1. 新建工程:
打开Eclipse,新建一个Android 程序,名称为 AndroidILBC,要求SDK 使用2.2及以上版本,因为Android是从2.2开始正式支持NDK 开发。
2. 添加底层代码:
将下载的源码中的 jni 文件夹复制到新建的工程的根目录下,此时,代码结构如下:
3. jni 目录下的Android.mk 的内容为:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libilbc
codec_dir := iLBC_RFC3951 #ilbc 源代码的目录
LOCAL_SRC_FILES := \
$(codec_dir)/anaFilter.c \
$(codec_dir)/constants.c \
$(codec_dir)/createCB.c \
$(codec_dir)/doCPLC.c \
$(codec_dir)/enhancer.c \
$(codec_dir)/filter.c \
$(codec_dir)/FrameClassify.c \
$(codec_dir)/gainquant.c \
$(codec_dir)/getCBvec.c \
$(codec_dir)/helpfun.c \
$(codec_dir)/hpInput.c \
$(codec_dir)/hpOutput.c \
$(codec_dir)/iCBConstruct.c \
$(codec_dir)/iCBSearch.c \
$(codec_dir)/iLBC_decode.c \
$(codec_dir)/iLBC_encode.c \
$(codec_dir)/LPCdecode.c \
$(codec_dir)/LPCencode.c \
$(codec_dir)/lsf.c \
$(codec_dir)/packing.c \
$(codec_dir)/StateConstructW.c \
$(codec_dir)/StateSearchW.c \
$(codec_dir)/syntFilter.c
LOCAL_C_INCLUDES += $(common_C_INCLUDES)
LOCAL_PRELINK_MODULE := false
include $(BUILD_STATIC_LIBRARY)
# Build JNI wrapper
include $(CLEAR_VARS)
LOCAL_MODULE := libilbc-codec #生成的 .so库名,可以自行修改
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
$(codec_dir)
LOCAL_SRC_FILES := ilbc-codec.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
LOCAL_STATIC_LIBRARIES := libilbc
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
4. 代码分析:
打开jni 文件夹下的 ilbc-codec.c 文件,里面总共只有五个函数,负责音频编解码器的初始化,以及音频的编码和解码。其中的三个方法:
jint Java_com_googlecode_androidilbc_Codec_init(
JNIEnv *env, jobject this, jint mode)
和
jint Java_com_googlecode_androidilbc_Codec_encode(
JNIEnv *env, jobject this,
jbyteArray sampleArray, jint sampleOffset, jint sampleLength,
jbyteArray dataArray, jint dataOffset)
和
jint Java_com_googlecode_androidilbc_Codec_decode(
JNIEnv *env, jobject this,
jbyteArray dataArray, jint dataOffset, jint dataLength,
jbyteArray sampleArray, jint sampleOffset)
根据这三个函数的名称就可以知道,使用来让 Java层代码调用的三个函数,现在我们对这三个函数进行改造(仅仅是换个函数名称而已)
5. 写Java层native 方法:
在程序的Java层代码中,建立一个包,用于放 NDK 的java层代码,比如我建一个名为 xmu.swordbearer.audio 的包,里面新建一个类:
AudioCodec.java ,在这个类中只负责对底层C函数进行调用,相当于一个工具类。新建三个 public staic native int 方法:
package xmu.swordbearer.audio;
public class AudioCodec {
// initialize decoder and encoder
public static native int audio_codec_init(int mode);
// encode
public static native int audio_encode(byte[] sample, int sampleOffset,
int sampleLength, byte[] data, int dataOffset);
// decode
public static native int audio_decode(byte[] data, int dataOffset,
int dataLength, byte[] sample, int sampleLength);
}
三个方法分别用于初始化,音频编码,音频解码,在这里只需声明为 native 方法,不用写任何代码;
6. 编译.h 头文件:(如果不会,请参考之前的文章)
打开终端,定位到第 5步建立的 AudioCodec.java 目录下,如下:
这一步很关键,进入到src目录后,就要带上 AudioCodec 这个类的包名,此例中的包名为: xmu.swordbearer.audio如果上述步
骤正确,就会在该包下生成一个 xmu_swordbearer_audio_AudioCodec.h 的头文件,内容如下:
/*
* Class: xmu_swordbearer_audio_AudioCodec
* Method: audio_codec_init
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_xmu_swordbearer_audio_AudioCodec_audio_1codec_1init
(JNIEnv *, jclass, jint);
/*
* Class: xmu_swordbearer_audio_AudioCodec
* Method: audio_encode
* Signature: ([BII[BI)I
*/
JNIEXPORT jint JNICALL Java_xmu_swordbearer_audio_AudioCodec_audio_1encode
(JNIEnv *, jclass, jbyteArray, jint, jint, jbyteArray, jint);
/*
* Class: xmu_swordbearer_audio_AudioCodec
* Method: audio_decode
* Signature: ([BII[BI)I
*/
JNIEXPORT jint JNICALL Java_xmu_swordbearer_audio_AudioCodec_audio_1decode
(JNIEnv *, jclass, jbyteArray, jint, jint, jbyteArray, jint);
第4步中分析的三个方法修改,打开jni 下的 ilbc-codec.c 文件,,把那三个名称分别用刚刚生成的这三个方法名替换,具体对应如下:
Java_com_googlecode_androidilbc_Codec_init
改为:
Java_xmu_swordbearer_audio_AudioCodec_audio_1codec_1init
Java_com_googlecode_androidilbc_Codec_encode
改为:
Java_xmu_swordbearer_audio_AudioCodec_audio_1encode
补充:移动开发 , Android ,