Article Directory
4. The native method is as follows
foreword
Because the file generated after using android recording is in wav or pcm format, the project requires the final file to be in mp3 format, so the lame library is used.
1. What is the Lame library?
LAME is the best MP3 encoder, the best and only choice for encoding high-quality MP3.
Demo is placed at the end of the article. Demo is a lib library, which can be used directly by importing it.
This demo example uses the c library compiled by CMakeLists .
2. Use steps
0. Create a native project
Create a new native project or native module. After the creation is successful, the cpp folder and a native.cpp, CMakeLists will be automatically generated.
1. Download the Lame library
Lame official website https://sourceforge.net/projects/lame/files/lame/
After downloading, put all the .c and .h files in the libmp3lame folder and the lame.h in the include folder into the cpp file of the new project
The demo uses version 3.99. If your network is slow, you can use the lame library in the demo later.
2.pcm to MP3
The cpp code is as follows (example):
/************************************************************************
* PCM 转 MP3 *
***********************************************************************/
Mp3Encoder *encoder;
extern "C" JNIEXPORT jint JNICALL
Java_com_meng_nativelib_NativeLib_pcmToMp3JNI(
JNIEnv *env,
jobject,
jstring pcm_path,
jstring mp3_path,
jint sample_rate,
jint channel,
jint bit_rate) {
const char *pcmPath = env->GetStringUTFChars(pcm_path, NULL);
const char *mp3Path = env->GetStringUTFChars(mp3_path, NULL);
encoder = new Mp3Encoder();
int initStatus = encoder->Init(pcmPath, mp3Path, sample_rate, channel, bit_rate);
if (initStatus != 0) {
return -1;
}
encoder->Encode();
env->ReleaseStringUTFChars(pcm_path, pcmPath);
env->ReleaseStringUTFChars(mp3_path, mp3Path);
return 0;
}
extern "C" JNIEXPORT void JNICALL
Java_com_meng_nativelib_NativeLib_pcmToMp3JNIDestroy(
JNIEnv *env,
jobject) {
encoder->Destroy();
}
3.wav to MP3
int flag = 0;
/**
* wav转换mp3
*/
extern "C"
JNIEXPORT void JNICALL Java_com_meng_nativelib_NativeLib_wavToMp3
(JNIEnv *env, jobject obj, jstring jwav, jstring jmp3, jint inSamplerate, jint inChannel,
jint outBitrate) {
char *cwav = Jstring2CStr(env, jwav);
char *cmp3 = Jstring2CStr(env, jmp3);
//1.打开 wav,MP3文件
FILE *fwav = fopen(cwav, "rb");
fseek(fwav, 4 * 1024, SEEK_CUR);
FILE *fmp3 = fopen(cmp3, "wb+");
int channel = inChannel;//单声道
short int wav_buffer[8192 * channel];
unsigned char mp3_buffer[8192];
//1.初始化lame的编码器
lame_t lameConvert = lame_init();
//2. 设置lame mp3编码的采样率
lame_set_in_samplerate(lameConvert, inSamplerate);
lame_set_out_samplerate(lameConvert, inSamplerate);
lame_set_num_channels(lameConvert, channel);
lame_set_mode(lameConvert, MONO);
// 3. 设置MP3的编码方式
lame_set_VBR(lameConvert, vbr_default);
lame_init_params(lameConvert);
int read;
int write; //代表读了多少个次 和写了多少次
int total = 0; // 当前读的wav文件的byte数目
do {
if (flag == 404) {
return;
}
read = fread(wav_buffer, sizeof(short int) * channel, 8192, fwav);
total += read * sizeof(short int) * channel;
if (read != 0) {
write = lame_encode_buffer(lameConvert, wav_buffer, NULL, read, mp3_buffer, 8192);
//write = lame_encode_buffer_interleaved(lame,wav_buffer,read,mp3_buffer,8192);
} else {
write = lame_encode_flush(lameConvert, mp3_buffer, 8192);
}
//把转化后的mp3数据写到文件里
fwrite(mp3_buffer, 1, write, fmp3);
} while (read != 0);
lame_mp3_tags_fid(lameConvert, fmp3);
lame_close(lameConvert);
fclose(fwav);
fclose(fmp3);
}
4. The native method is as follows
package com.meng.nativelib
object NativeLib {
// Used to load the 'lame_lib' library on application startup.
init {
System.loadLibrary("lame_lib")
}
external fun getVersion(): String?
/**
* wav 转mp3 16000,1,1
* @param wavFilePath 源文件路径
* @param mp3FilePath 生成mp3目标文件路径
* @param sampleRate Lame采样率 最好写 16000 Lame采样率
* MPEG1 MPEG2 MPEG2.5
* 44100 22050 11025
* 8000 24000 12000
* 32000 16000 8000
*@param channels 1
* @param bitRate 实际没有使用
*/
external fun wavToMp3(
wavFilePath: String, mp3FilePath: String, sampleRate: Int, channels: Int, bitRate: Int
)
external fun pcmToMp3JNI(
pcmFilePath: String, mp3FilePath: String, sampleRate: Int, channels: Int, bitRate: Int
): Int
external fun pcmToMp3JNIDestroy()
}
Three, pay attention
- When writing cpp code, be sure to add extern "C" on the method ( the main function is to correctly implement C++ code to call other C language code. After adding extern "C", it will instruct the compiler to use C language for this part of the code (instead of C++) to compile. Since C++ supports function overloading, the compiler will add the parameter types of the function to the compiled code during the process of compiling the function, not just the function name; while the C language Function overloading is not supported, so the parameter type of the function will not be included when compiling the function of the C language code, generally only the function name is included. )
- Don't forget to add the new cpp file to add_library of CMakeLists
- After adding the cpp file, it is best to make the cpp folder once (Build->Make Moduie at the top of AndroidStudio)
- If the compiled so file is not found after compiling and running, you can go to build to check whether the compiling so file is successful
Demo address https://gitcode.net/weixin_41620505/pcm-and-wav-to-mp3
Summarize
There are still many pitfalls in the first compilation, such as the points that need to be paid attention to above.