**
Android錄音並進行本地轉碼
**
通過安卓手機進行錄音,
錄音後,使用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
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.<br />
* recommended:<br />
* 2 near-best quality, not too slow<br />
* 5 good quality, fast<br />
* 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<int>(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<size_t>(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
應用界面如下