当前位置: 首页 > news >正文

使用Lame库实现wav、pcm转mp3

 

 

文章目录

前言

一、Lame库是什么?

二、使用步骤

0.创建native项目

1.下载Lame库

2.pcm转MP3

3.wav转MP3

 4、native方法如下

三、注意

总结


前言

   因为使用android录音后生成的文件是wav或者pcm格式,项目要求最后的文件需要是mp3格式,于是就使用到了lame库。

一、Lame库是什么?

LAME 是最好的MP3编码器,编码高品质MP3的最好也是唯一的选择。

Demo放在了文章末尾,demo是一个lib库,直接引入就可以使用的。

本demo实例使用的是CMakeLists的方式编译的c库。

二、使用步骤

0.创建native项目

新建一个native项目或者native的module,创建成功后就会自动生成cpp文件夹和一个native.cpp、CMakeLists

 

1.下载Lame库

Lame官网icon-default.png?t=N176https://sourceforge.net/projects/lame/files/lame/

    下载完把libmp3lame 文件夹下的所有.c和.h文件还有include文件夹下的lame.h考入到新建工程的cpp文件下

 

 demo使用的是3.99这个版本,如果你的网很慢可以使用在后面的 demo里面的lame库。

2.pcm转MP3

cpp代码如下(示例):


/*************************************************************************                              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转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、native方法如下

package com.meng.nativelibobject 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): Intexternal fun pcmToMp3JNIDestroy()}

三、注意

  • 在编写的cpp代码时一定要在方法上面添加  extern "C"主要作用就是为了能够正确实现C++代码调用其他C语言代码。加上extern "C"后,会指示编译器这部分代码按C语言(而不是C++)的方式进行编译。由于C++支持函数重载,因此编译器编译函数的过程中会将函数的参数类型也加到编译后的代码中,而不仅仅是函数名;而C语言并不支持函数重载,因此编译C语言代码的函数时不会带上函数的参数类型,一般只包括函数名。
  • 不要忘记把新增的cpp文件添加到CMakeLists的add_library里面
  • 新增cpp文件后最好对cpp文件夹make一次(AndroidStudio的顶部Build->Make Moduie)
  • 如果编译运行过后报没有找到你编译的so文件,可以去build下面查看是否编译so文件成功

 Demo地址icon-default.png?t=N176https://gitcode.net/weixin_41620505/pcm-and-wav-to-mp3

总结

第一次编译还是有挺多坑的,比如上面需要注意的那几点。

相关文章:

使用Lame库实现wav、pcm转mp3

文章目录 前言 一、Lame库是什么? 二、使用步骤 0.创建native项目 1.下载Lame库 2.pcm转MP3 3.wav转MP3 4、native方法如下 三、注意 总结 前言 因为使用android录音后生成的文件是wav或者pcm格式,项目要求最后的文件需要是mp3格式,于…...

c++11 标准模板(STL)(std::multimap)(三)

定义于头文件 <map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class multimap;(1)namespace pmr { template <class Key, class T…...

【报复性赚钱】2023年5大风口行业

今天就来和大家分享一下&#xff0c;在时代的洪流下&#xff0c;普通人如何顺应大势抓住机遇&#xff01; 实现人在风口上&#xff0c;猪都会飞起来。 根据对市场的观察及各平台数据分析结果&#xff0c;结合国家政策和经济专家的分析&#xff0c;小编预测了2023年将会迎来大…...

单目相机、双目相机和RGB-D相机学习笔记(一些视频和博文网址)

目录1. 单目相机1.1 摄像头原理1.2 单目相机的标定2 双目相机2.1 双目相机定位原理2.2 双目相机的缺陷3 RGB-D相机3.1 深度相机结构光原理3.2 RGB-D相机的应用1. 单目相机 1.1 摄像头原理 视频网址&#xff1a;【全网最详细】摄像头原理分析&#xff08;约25分钟课程&#xf…...

word和wps添加mathtype选项卡

word或wps添加mathtype选项卡 前提 安装好word或wps安装好mathtype 步骤 确认word或wps具体安装位置确认word或wps位数为32位还是64位复制mathtype中的MathPage.wll文件和MathType Commands 2016.dotm文件到STARTUP位置添加受信任位置添加加载项 安装位置 通过开始页面&a…...

获取成员userID

文章目录一、简介二、获取token1、获取秘钥2、获取Token三、获取部门数据1、获取部门列表2、获取子部门ID列表3、获取单个部门详情四、获取成员信息1、读取成员2、获取部门成员3、获取部门成员详情一、简介 同步数据到企微&#xff1a; 企业如果需要从自有的系统同步通讯录到…...

DOM编程-显示网页时钟

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>显示网页时钟</title> </head> <body bgcolor"antiquewhite"> <script type"text/javascrip…...

浅谈保护数据的加密策略

加密是一种将信息从可读格式转换为混乱字符串的技术。这样做可以防止数据传输中的机密数据泄露。文档、文件、消息和所有其他形式的网络通信都可以加密。加密策略和身份验证服务的结合&#xff0c;还能保障企业机密信息只对授权用户开启访问权限。常见的数据加密包括以下两种&a…...

Java中String,StringBuffer和StringBuilder

String类 我们在定义string变量时 常常写 String str "hello word"; 这样的代码,看起来和int a 0; 是一样的声明方式, 但其实两者是不同的, int 是java中定义的基本数据类型, 而String是一个类&#xff0c;是一个特殊的类&#xff0c;可以像基本数据类型一样直接赋…...

华为认证常见技术问答整理:什么是Datacom认证?

一、关于Datacom认证Q&#xff1a;什么是Datacom认证&#xff1f;A&#xff1a;Datacom&#xff0c;即DatacomCommunication的缩写&#xff0c;中文为“数据通信”&#xff0c;属于ICT技术架构认证类别&#xff08;华为认证包含ICT技术架构认证、平台与服务认证和行业ICT认证三…...

Read book Netty in action (Chapter II) (Netty Introduction)

前言 支持15W的并发客户端&#xff0c;我们应该视为理所当然的事情&#xff0c;很多公司甚至能够支撑更多&#xff0c;例如我们熟知的 BAT&#xff0c;当几年前双十一的夜晚&#xff0c;并发量是不可估计的。还有春节的时候购票的时候的并发。作为一个优秀的开发人员&#xff…...

python--route

routes是用python重新实现的Rails routes系统&#xff0c;用于将url映射到应用程序的actions &#xff0c;并反过来生成url 它也是在openstack实现restful通信的方式&#xff0c;它被用来做将 URL 映射为 App 的 action&#xff0c;以及为 App的action 产生 URL 两个重要的方法…...

java面试中被问到项目中的难点,怎么回答

java面试中被问到项目中的难点&#xff0c;怎么回答回答步骤举例说明回答步骤 回答这个问题的方法取决于你的项目的类型和难度。 但是&#xff0c;一般来说&#xff0c;你可以遵循以下步骤来回答这个问题&#xff1a; 描述你的项目&#xff1a;首先简要描述你的项目的类型和目…...

【速通版】吴恩达机器学习笔记Part1

准备速通一下吴恩达的机器学习 很快做个笔记5.2.3 监督学习 part 2_哔哩哔哩_bilibili 目录 1.概述&#xff08;P1-P3) 2.supervised learning&#xff1a;&#xff08;P4,P5) regression&#xff1a; classification 3.unsupervised learning &#xff08;P6- 1.聚类算…...

面试(九)小米C++开发一面 21.11.02

1、局部变量与全局变量的区别?可以同名嘛? 首先是作用域: 局部变量只在变量声明的代码块范围内生效 全局变量在其声明后的所有位置都能访问到 在局部变量与全局变量同名的情况下,全局变量会被屏蔽掉,只会使用局部变量的内容 2、extern 当在a.c中想要使用b.c中的函数fu…...

儿童书写台灯哪个牌子比较好?2023儿童护眼台灯分享

现在儿童的近视率高达52.7%&#xff0c;有科技水平的提高和电子产品的普及&#xff0c;近视率逐年攀升&#xff0c;出现低龄化现象&#xff0c;调查结果显示&#xff0c;其中6岁儿童达到14.3%&#xff0c;小学生为35.6%。初中生71.1%&#xff0c;高中生高达80.5%&#xff0c;可…...

市场调研计划书如何写?

想要做好一个产品&#xff0c;市场调研是必不可少的一步&#xff0c;也是第一步&#xff0c;那么如何进行市场调研呢&#xff1f;以下是我整理的一份市场调研计划书&#xff0c;希望能够帮助到大家&#xff01;&#xff01;&#xff01; 一、文档版本控制 主要记录文档的版本…...

python网络爬虫—快速入门(理论+实战)(七)

系列文章目录 &#xff08;1&#xff09;python网络爬虫—快速入门&#xff08;理论实战&#xff09;&#xff08;一&#xff09; &#xff08;2&#xff09;python网络爬虫—快速入门&#xff08;理论实战&#xff09;&#xff08;二&#xff09; &#xff08;3&#xff09; p…...

机器学习笔记——Chapter 1 – The Machine Learning landscape

ML学习笔记 Chapter 1 – The Machine Learning landscape 1.如何定义机器学习&#xff1f; Answer&#xff1a;机器学习是一门通过编程让计算机从数据中进行学习的科学&#xff08;和艺术&#xff09;。 2.机器学习在哪些问题上表现突出&#xff0c;你能给出四种类型吗&am…...

skimage.feature--corner_harris、hog、local_binary_pattern说明

skimage.feature说明–corner_harris、hog、local_binary_pattern 文章目录skimage.feature说明--corner_harris、hog、local_binary_pattern1. 前言2. corner_harris2.1 介绍2.2 参数及返回3. hog3.1 介绍3.2 参数及返回4. local_binary_pattern4.1 介绍4.2 参数及返回5. 总结…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...