一、简介
目前的项目需要使用Android的录音功能,而Android AudioRecord 无法直接录出mp3格式,因此需要我们进行对pcm数据进行编码格式处理。目前比较优秀的mp3编码库,比较推荐的是 Lame。
二、Lame编译
1、Lame下载
我们可以直接去官方网站上下载最新版本的 Lame 3.100版本。
2、Android studio创建C++项目
当我们创建好Android C++项目后,需要进行如下配置:
1、在cpp目录下新增lame目录。

2、将刚刚下载lame 3.100解压
- 复制 libmp3lame 文件夹里面 .c 和 .h结尾的文件到新增lame目录下
- 复制 vector 文件夹里面的 lame_intrin.h 到新增lame目录下
- 复制 include文件夹里面的 lame.h 到新增lame目录下
3、编写 CMakeLists.txt
bash
cmake_minimum_required(VERSION 3.4.1)
SET(lame_dir ${CMAKE_SOURCE_DIR}/lame)
# 将给定目录添加到编译器用于搜索包含文件的目录中。相对路径被解释为相对于当前源目录
# 是用来提供编译搜索头文件路径的
include_directories(${lame_dir})
#设定一个目录
aux_source_directory(${lame_dir} SRC_LIST)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
#确保生成的 .so 文件包含完整的调试信息和符号表
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
#生成以 libLames.so 文件文件名的so文件
add_library( # Sets the name of the library.
Lame
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
${SRC_LIST}
Lame.cpp)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
target_link_libraries( # Specifies the target library.
Lame
# Links the target library to the log library
# included in the NDK.
${log-lib})
# 16K 对齐
target_link_options(Lame PRIVATE "-Wl,-z,max-page-size=16384")
4、编写Lame.cpp
arduino
#include <jni.h>
#include <string>
#include "lame.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_com_hql_lame_LameUtils_getVersion(JNIEnv *env, jobject thiz) {
throw "a";
return (*env).NewStringUTF(get_lame_version());
}
5、build.gradle.kts 配置
ini
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "com.hql.he.lame"
compileSdk = 35
defaultConfig {
minSdk = 26
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
ndk {
abiFilters.addAll(arrayOf("arm64-v8a"))
}
//解决.c 里面的警告
externalNativeBuild {
cmake {
cFlags("-DSTDC_HEADERS")
}
}
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
}
6、错误解决
-
unknown type name 'ieee754_float32_t'
将util.h的570行改为
arduinoextern ieee754_float32_t fast_log2(ieee754_float32_t x); 改为 extern float fast_log2(float x);
-
fft.c报错
修改为:
arduino
#include "lame_intrin.h"
三、编写 LameUtils
kotlin
object LameUtils {
init {
System.loadLibrary("Lame")
}
external fun getVersion(): String
}
四、运行
这时候运行,会报如下错误:

addr2line 定位和解决报错
- 找到addr2line
在命令行输入如下命令:
bash
aarch64-linux-android-addr2line -f -C -e /xxx/arm64-v8a/libLame.so 000000000006bf3c
结果:
bash
Java_com_hql_lame_LameUtils_getVersion
/xxx/LameMp3/lame_mp3/src/main/cpp/Lame.cpp:8
删除该行,即可解决错误。在运行,即显示如下:

出现上述结果 3.100,即表示成功编译。
编译lame.so可以使用如下命令:
- assemble
- assembleRelease
最终生成so文件路径为:
五、总结
- 1、编译lame
- 2、Android 16k对齐
- 3、addr2line的使用
六、其他
1、如何查看so文件是否包含符号表
a、使用file命令
file libLame.so
结果
scala
libLame.so: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, BuildID[sha1]=ec26f0b295b66218ff61cd04a6d8e2657e6ccf5e, with debug_info, not stripped
not stripped 即代表有符号表。
b、使用llvm-vm命令

llvm-vm libLame.so
表示有符号表
2、如何查看so文件是否16k对齐
