Android中内置的MediaCodeC提供了很多音视频编解码器,但由于MP3是有版权的,所以原生MediaCodeC只提供了MP3的解码能力,对于MP3的编码就需要借助外部库了。LAME库由开源社区开发,当前是公认有损质量MP3中压缩效果最好的编码器。本文的主要工作为将LAME源码编译为so库,并在Android中使用。
fft.c
文件的vector引用include "vector/lame_intrin.h"
2) 将set_get.h
中的 #include <lame.h>
修改为 #include "lame.h"
3) 将util.h
文件的574行的extern ieee754_float32_t fast_log2(ieee754_float32_t x);
替换为 extern float fast_log2(float x);
1. C++项目的编译有两种方式: 1) CMake:Android Studio新的构建方式,在build.gradle中指定CMakeList.txt文件路径,jni会按照这个脚本来进行编译。 2) ndk-build:老eclipse的构建方式,也就是Android.mk的形式。
2. 本文介绍第一种方式 修改app目录下的CMakeList.txt,由于lame源码需要编译的文件较多,可以使用以下方式编译整个文件夹
aux_source_directory(src/main/cpp/libmp3lame LAME_SRC_DIR)
add_library(lame-lib SHARED lame-lib.cpp ${LAME_SRC_DIR})
3. 在app/build.gradle中配置cmake参数
externalNativeBuild {
cmake {
cFlags "-DSTDC_HEADERS" // 必须,给编译器加上STDC头文件的宏定义
abiFilters "armeabi-v7a" // 可选,指定生成so的兼容的架构
}
}
4. 编辑lame-lib.cpp文件,调用lame方法
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_demo_lame_MainActivity_stringFromJNI2(
JNIEnv *env,
jobject /* this */) {
return env->NewStringUTF(get_lame_version());
}
}
5. 编译项目,可在屏幕上看到lame的版本号
在lame-lib.cpp中添加以下代码,lame初始化时采样率等参数的要求可在lame源码中看到。最后在MainActivity中调用wav2mp3方法即可。
int BUFF_SIZE = 8192;
JNIEXPORT void JNICALL Java_com_demo_lame_MainActivity_wav2mp3
(JNIEnv *env, jobject obj, jstring jwav, jstring jmp3, jint inSampleRate, jint inChannels, jint outSampleRate, jint byteRate, jint mode, jint quality) {
jboolean isCopy;
const char *cwav = env->GetStringUTFChars(jwav, &isCopy);
const char *cmp3 = env->GetStringUTFChars(jmp3, &isCopy);
// 打开wav文件
FILE *fwav = fopen(cwav, "rb");
// 移除wav文件头
fseek(fwav, 4 * 1024, SEEK_CUR);
FILE *fmp3 = fopen(cmp3, "wb+");
int channel = inChannels;
short int wav_buffer[BUFF_SIZE * channel];
unsigned char mp3_buffer[BUFF_SIZE];
// init lame
lame_global_flags *lameConvert;
lameConvert = lame_init();
lame_set_in_samplerate(lameConvert, inSampleRate);
lame_set_num_channels(lameConvert, inChannels);
lame_set_out_samplerate(lameConvert, outSampleRate);
if (byteRate > 0) {
lame_set_brate(lameConvert, byteRate);
}
lame_set_mode(lameConvert, (MPEG_mode) mode);
lame_set_quality(lameConvert, quality);
lame_set_VBR(lameConvert, vbr_default);
lame_init_params(lameConvert);
int read;
int write;
int total = 0;
do {
read = fread(wav_buffer, sizeof(short int) * channel, BUFF_SIZE, fwav);
total += read * sizeof(short int) * channel;
if (read != 0) {
write = lame_encode_buffer(lameConvert, wav_buffer, nullptr, read, mp3_buffer, BUFF_SIZE);
} else {
write = lame_encode_flush(lameConvert, mp3_buffer, BUFF_SIZE);
}
fwrite(mp3_buffer, 1, write, fmp3);
} while (read != 0);
lame_mp3_tags_fid(lameConvert, fmp3);
lame_close(lameConvert);
fclose(fwav);
fclose(fmp3);
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。