NDK环境配置
这里主要是介绍Eclipse的NDK开发环境配置,至于Android Studio的配置比较简单,自行Google吧。。。
下载安装CDT
多的不解释,Eclipse插件安装
https://dl.google.com/android/eclipse/
安装完成重启即可
下载安装NDK
同样,上官网下载相应的NDK
下载完成解压放在适当的目录下
若出现下面的情况
说明NDK版本过高,请下载低一些的版本,正确后如下
到此NDK开发环境就配置完成了,当然这是基于安装的jdk版本是1.7以上的情况,若是1.6的话,还要安装cygwin,当然也还有其他一些配置
实在是必须在1.6环境下进行NDK开发,可以看这篇文章
Android NDK开发(一)——环境搭建
LAME编译
- 新建的项目根目录下建立jni目录
- 解压下载的lame-3.99.5.tar.gz文件,拷贝libmp3lame文件夹下的文件到jni目录下
- 拷贝 lame.h到jni目录 (include目录下)
- 删除非.c /.h文件
- 编辑 jni/util.h,在574行把 extern ieee754_float32_t fast_log2(ieee754_float32_t x);替换为 extern float fast_log2(float x);。
创建Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)
LOCAL_MODULE := mp3lame
LOCAL_SRC_FILES := bitstream.c fft.c id3tag.c mpglib_interface.c presets.c quantize.c reservoir.c tables.c util.c VbrTag.c encoder.c gain_analysis.c lame.c newmdct.c psymodel.c quantize_pvt.c set_get.c takehiro.c vbrquantize.c version.c lame_util.c
LOCAL_LDLIBS += -llog
include $(BUILD_SHARED_LIBRARY)
创建Application.mk
APP_PLATFORM := android-9
APP_ABI := all //输出的.so版本,all表示全部
APP_CFLAGS += -DSTDC_HEADERS
在Java层编写调用C端的代码
public class LameUtil {
static{
System.loadLibrary("mp3lame");
}
/**
* Initialize LAME.
*/
public native static void init(int inSamplerate, int inChannel,
int outSamplerate, int outBitrate, int quality);
/**
* Encode buffer to mp3.
*/
public native static int encode(short[] bufferLeft, short[] bufferRight,
int samples, byte[] mp3buf);
/**
* Flush LAME buffer.
*/
public native static int flush(byte[] mp3buf);
/**
* Close LAME.
*/
public native static void close();
}
编译头文件
jdk_1.7 及以上版本直接到项目src目录,以下到class目录
如此成功后会在jni目录下生成如下文件
看下生成的文件内容
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_autolink_mp3library_util_LameUtil */
#ifndef _Included_com_autolink_mp3library_util_LameUtil
#define _Included_com_autolink_mp3library_util_LameUtil
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_autolink_mp3library_util_LameUtil
* Method: init
* Signature: (IIIII)V
*/
JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_init
(JNIEnv *, jclass, jint, jint, jint, jint, jint);
/*
* Class: com_autolink_mp3library_util_LameUtil
* Method: encode
* Signature: ([S[SI[B)I
*/
JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_encode
(JNIEnv *, jclass, jshortArray, jshortArray, jint, jbyteArray);
/*
* Class: com_autolink_mp3library_util_LameUtil
* Method: flush
* Signature: ([B)I
*/
JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_flush
(JNIEnv *, jclass, jbyteArray);
/*
* Class: com_autolink_mp3library_util_LameUtil
* Method: close
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_close
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
编写本地C语言代码,实现音频文件的转码
#include "lame.h"
#include "com_autolink_mp3library_util_LameUtil.h"
#include <stdio.h>
#include <jni.h>
static lame_global_flags *lame = NULL;
JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_init(
JNIEnv *env, jclass cls, jint inSamplerate, jint inChannel, jint outSamplerate, jint outBitrate, jint quality) {
if (lame != NULL) {
lame_close(lame);
lame = NULL;
}
lame = lame_init();
lame_set_in_samplerate(lame, inSamplerate);
lame_set_num_channels(lame, inChannel);//杈撳叆娴佺殑澹伴亾
lame_set_out_samplerate(lame, outSamplerate);
lame_set_brate(lame, outBitrate);
lame_set_quality(lame, quality);
lame_init_params(lame);
}
JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_encode(
JNIEnv *env, jclass cls, jshortArray buffer_l, jshortArray buffer_r,
jint samples, jbyteArray mp3buf) {
jshort* j_buffer_l = (*env)->GetShortArrayElements(env, buffer_l, NULL);
jshort* j_buffer_r = (*env)->GetShortArrayElements(env, buffer_r, NULL);
const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
int result = lame_encode_buffer(lame, j_buffer_l, j_buffer_r,
samples, j_mp3buf, mp3buf_size);
(*env)->ReleaseShortArrayElements(env, buffer_l, j_buffer_l, 0);
(*env)->ReleaseShortArrayElements(env, buffer_r, j_buffer_r, 0);
(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
return result;
}
JNIEXPORT jint JNICALL Java_com_autolink_mp3library_util_LameUtil_flush(
JNIEnv *env, jclass cls, jbyteArray mp3buf) {
const jsize mp3buf_size = (*env)->GetArrayLength(env, mp3buf);
jbyte* j_mp3buf = (*env)->GetByteArrayElements(env, mp3buf, NULL);
int result = lame_encode_flush(lame, j_mp3buf, mp3buf_size);
(*env)->ReleaseByteArrayElements(env, mp3buf, j_mp3buf, 0);
return result;
}
JNIEXPORT void JNICALL Java_com_autolink_mp3library_util_LameUtil_close
(JNIEnv *env, jclass cls) {
lame_close(lame);
lame = NULL;
}
新建C++编译器
右键项目Properties->Builders在右边的选项卡中点击“New”新建编译器(选择Program):
配置Main、Refresh和Build Options选项卡,如图
如此之后,clean一下工程即会自动编译获得.so文件
最后给项目加上下面两个权限
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
如何使用呢
package com.autolink.mp3library;
import java.io.File;
import java.io.IOException;
import com.autolink.mp3library.util.MP3Recorder;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends Activity {
private MP3Recorder mRecorder = new MP3Recorder(new File(Environment.getExternalStorageDirectory(), "test.mp3"));
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.StartButton).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try {
mRecorder.start();
} catch (IOException e) {
e.printStackTrace();
}
}
});
findViewById(R.id.StopButton).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mRecorder.stop();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mRecorder.stop();
}
}
参考链接:
http://blog.csdn.net/allen315410/article/details/42456661
http://blog.csdn.net/whurs/article/details/45487521
Android studio 可看下面这个