Android使用LAME将pcm格式转mp3格式

lame介绍:LAME是一款开源的MP3编码器,被认为是中高比特率和VBR的最佳MP3编码器,质量和速度方面的改进仍在继续,可能使LAME成为仍在积极开发的唯一MP3编码器。使用lame进行mp3编码,需要了解一些NDK相关的知识,比如jni和cmake。

准备工作:

  • 下载lame源码:https://lame.sourceforge.io/ 直接下载最新版本,本文使用的是3.100版本
  • android studio新建一个c++ support项目

集成lame源码

在cpp目录下,新建一个文件夹lamemp3,将下载的的源码文件中的\lame-3.100\libmp3lame文件夹下的所有.c和.h文件拷贝到lamemp3下并将\lame-3.100\include下的lame.h也拷贝进去,到这里,lame的源码都已经拷贝完成了,接下来,需要修改部分源码内容以及gradle配置参数。

1)删除fft.c文件的47行的”include “vector/lame_intrin.h”“

2)修改set_get.h文件的24行的#include“lame.h”

3)将util.h文件的574行的”extern ieee754_float32_t fast_log2(ieee754_float32_t x);”
替换为 “extern float fast_log2(float x);”

需要修改app 下的build.gradle文件

android {
...defaultConfig {...externalNativeBuild{cmake{cFlags "-DSTDC_HEADERS"}}}
}

接下来,我们编辑cmake,编辑好以后,点击android studio的build下的refresh linked c++ project,关于cmake部分,看cmake文件注释部分,cmake编写方式不局限一种,取决于你对cmake相关方法的了解

# Sets the minimum version of CMake required to build the native library.
#设置构建本地库所需的最低cmake版本
cmake_minimum_required(VERSION 3.4.1)
#设置库文件导出目录
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/lameLibs/${ANDROID_ABI})
#批量导入c文件和cpp文件
file(GLOB lame lamemp3/*.c)
file(GLOB lame2 lamemp3/*.cpp)
#批量导入头文件
include_directories(${CMAKE_CURRENT_LIST_DIR}/lamemp3)
# 创建和给一个库命名,可以设置为静态库
# 或动态库,并且提供它源码的相关路径
# 你可以定义多个库,然后cmake为你构建他们
# gradle会自动打包共享库到你的apk中
add_library( # Sets the name of the library.native-lib# Sets the library as a shared library.SHARED# 导入所有源文件native-lib.cpp${lame}${lame2})#所有指定的预构建库,并将路径定义为变量,用于后面引入
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)#指令cmake需要链接到的库
target_link_libraries(#指定目标librarynative-lib#链接目标库到log库${log-lib})

编写MP3转换的c++实现,

在cpp/lamemp3文件夹下载新建pcm2pm3.cpp和pcm2pm3.h文件,这里贴出实现部分,完成代码参考项目源码

//初始化lame
int pcm2mp3::init(const char *pcm_path, const char *mp3_path, int sample_rate, int channel,int bitRate) {int result=-1;pcm_file=fopen(pcm_path,"rb");if(pcm_file!= NULL){mp3_file=fopen(mp3_path,"wb");if (mp3_file!= NULL){//开始初始化lame_client=lame_init();lame_set_in_samplerate(lame_client,sample_rate);lame_set_out_samplerate(lame_client,sample_rate);lame_set_num_channels(lame_client,channel);lame_set_brate(lame_client,bitRate);lame_set_quality(lame_client,2);lame_init_params(lame_client);result=0;}}return result;
}
//pcm文件转mp3文件
void pcm2mp3::pcm_to_mp3() {int bufferSize = 1024 * 256;short *buffer = new short[bufferSize / 2];short *leftBuffer = new short[bufferSize / 4];short *rightBuffer = new short[bufferSize / 4];unsigned char* mp3_buffer = new unsigned char[bufferSize];size_t readBufferSize = 0;while ((readBufferSize = fread(buffer, 2, bufferSize / 2, pcm_file)) > 0) {for (int i = 0; i < readBufferSize; i++) {if (i % 2 == 0) {leftBuffer[i / 2] = buffer[i];} else {rightBuffer[i / 2] = buffer[i];}}size_t wroteSize = lame_encode_buffer(lame_client, (short int *) leftBuffer, (short int *) rightBuffer, (int)(readBufferSize / 2), mp3_buffer, bufferSize);fwrite(mp3_buffer, 1, wroteSize, mp3_file);}delete [] buffer;delete [] leftBuffer;delete [] rightBuffer;delete [] mp3_buffer;}

接下来就是编写jni调用c++方法,定义了三个native方法,一个获取版本号用于测试lame加载是否成功,pcmTomp3进行文件转换,destroy进行相关对象的释放

public class LameJni {static {System.loadLibrary("native-lib");}public native String getVersion();//初始化lamepublic native int pcmTomp3(String pcmPath,String mp3Path,int sampleRate, int channel,  int bitRate);public native void destroy();}

然后是对native方法的实现,这里只贴出转换的实现,关于jni的命名规则以及类型转换规则,这里不多赘述,查看jni相关资料即可

pcm2mp3 *mp3_encoder;
extern "C"
JNIEXPORT int JNICALL
Java_com_david_sampling_util_LameJni_pcmTomp3(JNIEnv *env, jclass clazz, jstring pcm_path,jstring mp3_path, jint sample_rate, jint channel,jint bit_rate) {int result=-1;const char *pcm_path_=env->GetStringUTFChars(pcm_path,0);const char *mp3_path_=env->GetStringUTFChars(mp3_path,0);mp3_encoder=new pcm2mp3();mp3_encoder->init(pcm_path_,mp3_path_,sample_rate,channel,bit_rate);mp3_encoder->pcm_to_mp3();env->ReleaseStringUTFChars(pcm_path,pcm_path_);env->ReleaseStringUTFChars(mp3_path,mp3_path_);return result;
}

然后java层通过jni调用即可实现mp3文件的编码

//注:本例经过尝试,发现如果采样率不缩小,那么声音会变快,原因还未找到
lameJni.pcmTomp3(pcmFile.getAbsolutePath(),mp3File.getAbsolutePath(),mSampleRate/2,mChannel==AudioFormat.CHANNEL_IN_MONO?1:2,128);

以上,即可将pcm转换为mp3,关于pcm的获取,可以参考上一篇:https://blog.csdn.net/s591628545/article/details/104525958

项目地址:https://github.com/kingdavidsun/AudioSampling.git

Android使用LAME将pcm文件转mp3文件相关推荐

  1. Android使用lame将PCM文件转码为MP3文件

    Android使用lame将PCM文件转码为MP3文件 1. 软件版本 Android Studio版本:4.2 lame版本:3.100 编译参考:centos7使用ndk编译lame 2. 项目配 ...

  2. android 录音的格式转换,Android仿微信录音功能(录音后的raw文件转mp3文件)

    现在很多时候需要用到录音,然后如果我们的App是ios和android两端的话,就要考虑录音的文件在两端都能使用,这个时候就需要适配,两端的录音文件都要是mp3文件,这样才能保证两边都能播放. 针对这 ...

  3. 语音amr文件转换为mp3文件

    1.安卓前端生成amr语音文件,经过base64加密变成加密字符串 2.把加密后的字符串解密成amr文件 生成amr文件目录   String fileUrl = System.getProperty ...

  4. Java使用ffmpeg合并多个视频文件、mp3文件

    /*** 合并多个视频文件.mp3文件*/@Testpublic void mergeFile(){// 合并命令String commit = "$0 -f concat -safe 0 ...

  5. 如何将微信amr文件转换为mp3文件

    本篇经验将介绍,如何将微信的amr文件转换为mp3文件. 工具/原料 电脑 电脑软件:silk2mp3 amr文件 方法/步骤 下载软件,解压. 进入以下目录,打开软件. silk-v3-decode ...

  6. 医用设备心跳心率检测mp3文件输出(mp3文件处理)(二)

    本系统是通过一套国外先进的医用设备将用户心跳心率存储到 mp3文件中, 该软件系统由于日本以非常高的价格出售, 公司决定由我破译硬件数据,开发一套替换日本软件产品.  该项目共花费2个月时间完成.   ...

  7. android 视频转音频,将mp4文件转换为mp3文件的方法

    很多文章关于将MP4转为MP3写的都很复杂,我这里总结一个比较简单的方法.此方法有个BUG,最后再说.但整体功能比较简单可用. 一,导入第三方文件 此方法用到3个第三方库文件如下,(资源和Demo在文 ...

  8. c# m4a文件转mp3文件 【.net】

    我的需求是手机上传录音.客户因手机上传的文件是m4a录音文件,按需求方要求,只要是m4a文件统一转成mp3格式上传,并且保留m4a格式文件.这两种方法跟自己业务有关,希望能帮到相同业务需求的朋友 第一 ...

  9. C++播放音频mav文件和mp3文件

    更多语音提示资料,阅读:为自己的软件添加语音提示功能 实现了一个类,该类提供播放音频文件功能 获得音频文件路径: void PlayAudio::GetDataPath(string path, st ...

最新文章

  1. 解决SVN提示https证书验证失败问题svn: E230001: Server SSL certificate verification failed: certificate issued
  2. Qt Creator使用ClearCase
  3. PC SERVER 序列号查询
  4. 通过getSystemServices获取手机管理大全
  5. Le-net网络总结
  6. android开发仿原生联系人,android 仿IOS联系人列表
  7. html/js/css资源
  8. 20个开发人员非常有用的Java功能代码(二)
  9. Asp.net2.0页面的生命周期
  10. activate激活虚拟环境无效解决办法
  11. 人眼分辨 PPI_1080P=2K,分辨率≠清晰度?关于显示器大多数人都错了
  12. python os.path.splitext()的用法_Python中的os.path路径模块中的操作方法总结
  13. 安卓rom制作教程_Android ROM制作教程-开发必需
  14. 稳压二极管型号对照表
  15. MySQL学习笔记第8课(共10课)
  16. 单片机数字时钟/闹钟
  17. 霍夫斯特拉大学计算机科学专业排名,院校排名
  18. 量化择业 银行vs券商vs公募vs私募?(行内人深度分享)
  19. 41.clip-path 滚动特效
  20. 使用JDK中的安全包对数据进行加解密

热门文章

  1. 描述超宽带雷达的原理
  2. 【数据处理】箱线图(boxplot)的绘制
  3. 拼接 字符串使用 Lambda 表达式
  4. ThingsBoard CE添加Excel导出功能-优化篇
  5. Micro Services
  6. springboot学生综合测评系统
  7. c++构造函数和析构函数
  8. python 弹球游戏
  9. 每日一面 - JVM 何时会 Stop the world
  10. Django(8)reverse函数