**
**
通过安卓手机进行录音,
录音后,使用lame进行转码操作
开发中需要使用这个功能,只是一个简单的进行转码的工具,具体的代码信息如下
项目的基本结构图
1、下载工具包
下载lame工具包
使用的最新版本
安装NDK环境
2、lame内容复制
首先在 src/main/目录下新建一个 cpp文件夹,Lame源码中 libmp3lame拷贝到 cpp文件夹下,可以重命名,例如我命名为 lamemp3
将Lame源码中的 include文件夹下的 lame.h复制到 lamemp3文件夹中
剔除 lamemp3中不必要的文件和目录,.rc/am/in文件都可以删除,Android这里用不到,只保留 .c和 .h文件
修改 util.h的源码。在570行找到 ieee754_float32_t数据类型,将其修改为 float类型,因为 ieee754_float32_t是Linux或者是Unix下支持的数据类型,在Android下并不支持。
set_get.h中24行将 include
在 id3tag.c和 machine.h两个文件里,將 HAVE_STRCHR和 HAVE_MEMCPY的ifdef结构体注释掉,不然编译会报错。
3、build.gradle配置
因为Androidstudio已经更新到最新
defaultConfig {
applicationId "com.example.gz.testmp3"
minSdkVersion 23
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild{
cmake{
cppFlags "-frtti -fexceptions" //设置cpp配置参数,c文件请使用CFlags
abiFilters 'armeabi-v7a', "armeabi"
}
}
ndk{
abiFilters 'armeabi-v7a',"armeabi"
}
}
sourceSets{
main{
jniLibs.srcDirs = ['libs']
}
}
如果下载的是最新的NDK与cmake,报出了一下的错误,
abis [mips64, armeabi, mips] are not supported for platform. supported
abis are [armeabi-v7a, arm64-v8a, x86, x86_64].
解决办法将gradle中cmake abiFilters配置改为:abiFilters ‘x86’, ‘x86_64’,’arm64-v8a’, ‘armeabi-v7a’
Google NDK r18解释: Support for ARMv5 (armeabi), MIPS, and MIPS64 has been removed. Attempting to build any of these ABIs will result in an error
我这里的abiFilters 只写了两个
4、编写Java native方法 MP3Converter
public class MP3Converter {
static {
System.loadLibrary("lame-mp3-utils");//这里一定要写对名称
}
//测试lame环境是否安装成功
public static native String getLameVersion();
/**
* init lame
* @param inSampleRate
* input sample rate in Hz
* @param channel
* number of channels
* @param mode
* 0 = CBR, 1 = VBR, 2 = ABR. default = 0
* @param outSampleRate
* output sample rate in Hz
* @param outBitRate
* rate compression ratio in KHz
* @param quality
* quality=0..9. 0=best (very slow). 9=worst.
* recommended:
* 2 near-best quality, not too slow
* 5 good quality, fast
* 7 ok quality, really fast
*/
public native static void init(int inSampleRate, int channel, int mode,
int outSampleRate, int outBitRate, int quality);
/**
* file convert to mp3
* it may cost a lot of time and better put it in a thread
* @param inputPath
* file path to be converted
* @param mp3Path
* mp3 output file path
*/
public native static void convertMp3(String inputPath, String mp3Path);
/**
* get converted bytes in inputBuffer
* @return
* converted bytes in inputBuffer
* to ignore the deviation of the file size,when return to -1 represents convert complete
*/
public native static long getConvertBytes();
}
5、编写调用C/C++的cpp
这个直接使用的是百度上的,仅限于能看懂,对于c++不懂
extern "C"
JNIEXPORT void JNICALL
Java_jaygoo_library_converter_MP3Converter_convertMp3(JNIEnv * env, jobject obj, jstring jInputPath, jstring jMp3Path) {
const char* cInput = env->GetStringUTFChars(jInputPath, 0);
const char* cMp3 = env->GetStringUTFChars(jMp3Path, 0);
//open input file and output file
FILE* fInput = fopen(cInput,"rb");
FILE* fMp3 = fopen(cMp3,"wb");
short int inputBuffer[BUFFER_SIZE * 2];
unsigned char mp3Buffer[BUFFER_SIZE];//You must specified at least 7200
int read = 0; // number of bytes in inputBuffer, if in the end return 0
int write = 0;// number of bytes output in mp3buffer. can be 0
long total = 0; // the bytes of reading input file
nowConvertBytes = 0;
//if you don't init lame, it will init lame use the default value
if(lame == NULL){
lameInit(44100, 2, 0, 44100, 96, 7);
}
//convert to mp3
do{
read = static_cast(fread(inputBuffer, sizeof(short int) * 2, BUFFER_SIZE, fInput));
total += read * sizeof(short int)*2;
nowConvertBytes = total;
if(read != 0){
write = lame_encode_buffer_interleaved(lame, inputBuffer, read, mp3Buffer, BUFFER_SIZE);
//write the converted buffer to the file
fwrite(mp3Buffer, sizeof(unsigned char), static_cast(write), fMp3);
}
//if in the end flush
if(read == 0){
lame_encode_flush(lame,mp3Buffer, BUFFER_SIZE);
}
}while(read != 0);
//release resources
resetLame();
fclose(fInput);
fclose(fMp3);
env->ReleaseStringUTFChars(jInputPath, cInput);
env->ReleaseStringUTFChars(jMp3Path, cMp3);
nowConvertBytes = -1;
}
6、剩下就是调用了
/**
* 开始录音
* @param mFlag
*/
public void recode(int mFlag){
if(mState != -1){
Log.e(mState+"1", "mState: "+mState );
Message msg = new Message();
Bundle b = new Bundle();// 存放数据
b.putInt("cmd",CMD_RECORDFAIL);
b.putInt("msg", ErrorCode.E_STATE_RECODING);
msg.setData(b);
uiHandler.sendMessage(msg); // 向Handler发送消息,更新UI
return;
}
int mResult = -1;
AudioRecorderWav mRecord_1 = AudioRecorderWav.getInstance();
mResult = mRecord_1.startRecordAndFile(MainActivity.this);
if(mResult == ErrorCode.SUCCESS){
mState = mFlag;
uiThread = new UIThread();
new Thread(uiThread).start();
}else{
Message msg = new Message();
Bundle b = new Bundle();// 存放数据
b.putInt("cmd",CMD_RECORDFAIL);
b.putInt("msg", mResult);
msg.setData(b);
uiHandler.sendMessage(msg); // 向Handler发送消息,更新UI
}
}
可能遇到的问题:
rg.gradle.api.internal.tasks.compile.CompilationFailedException:
Compilation failedCompilation failed; see the compiler error output for details.
解决过程
terminal 输入
gradlew compileDebugSources
查看错误信息
代码下载地址
TestMp3
参考文章:
教你如何使用Android NDK实现一个MP3转码库
Android NDK开发(六)——使用开源LAME转码mp3