音频demo:使用开源项目lame来将MP3数据解码出PCM数据

1、README

前言

本demo是使用开源项目lame来将MP3数据解码成PCM数据。(环境:x86_64 Ubuntu16.04 64位)

注:在下面【参考文章】中的第1篇里面提到解码出现过异常情况(hip: bitstream problem, resyncing skipping xxx bytes…),或许是因为我屏蔽了main.c中第88行的fseek(…)函数,在目前demo中提供的MP3文件以及网络下载的其他MP3文件解码均未发现此提示。

a. 编译使用

lame的编译:(源码下载地址:https://sourceforge.net/projects/lame/files/lame/)

tar xzf lame-3.100.tar.gz
cd lame-3.100/
./configure --prefix=$PWD/_install --enable-decoder
make
make install

本demo的编译与使用:

$ make clean && make DEBUG=1
$ 
$ ./mp32pcm 
Usage: ./mp32pcm <in MP3 file> <out PCM file>
Examples: ./mp32pcm audio/test1_44100_stereo.mp3 out1_44100_16bit_stereo.pcm./mp32pcm audio/test2_22050_stereo.mp3 out2_22050_16bit_stereo.pcm./mp32pcm audio/test3_22050_mono.mp3   out3_22050_16bit_mono.pcm./mp32pcm audio/test4_8000_mono.mp3    out4_8000_16bit_mono.pcm
b. 参考文章
  • 使用lame解码mp3_Griza_J的博客-CSDN博客_lame 解码

  • lame mp3解码 - 小小程序员001 - 博客园

c. demo目录架构
$ tree
.
├── audio
│   ├── out1_44100_16bit_stereo.pcm
│   ├── out2_22050_16bit_stereo.pcm
│   ├── out3_22050_16bit_mono.pcm
│   ├── out4_8000_16bit_mono.pcm
│   ├── test1_44100_stereo.mp3
│   ├── test2_22050_stereo.mp3
│   ├── test3_22050_mono.mp3
│   └── test4_8000_mono.mp3
├── docs
│   ├── lame mp3解码 - 小小程序员001 - 博客园.mhtml
│   └── 使用lame解码mp3_Griza_J的博客-CSDN博客_lame 解码.mhtml
├── include
│   └── lame
│       └── lame.h
├── lib
│   └── libmp3lame.a
├── main.c
├── Makefile
└── README.md

2、主要代码片段

main.c
#include <stdio.h>
#include <stdlib.h>#include "lame/lame.h"/* just for debug */
#ifdef ENABLE_DEBUG#define DEBUG(fmt, args...)     printf(fmt, ##args)
#else#define DEBUG(fmt, args...)
#endif#define INBUF_SIZE 		(4096)
#define BUF_SIZE 		(512)
#define MP3BUF_SIZE 	((int)(1.25 * BUF_SIZE) + 7200)int main(int argc, char *argv[])
{char *inMp3FileName = NULL;char *outPcmFileName = NULL;FILE *fpInMP3 = NULL;FILE *fpOutPcm = NULL;short pcm_l[INBUF_SIZE];short pcm_r[INBUF_SIZE];unsigned char mp3Buf[MP3BUF_SIZE];hip_t hip = NULL;if (argc != 3){printf("Usage: \n""    %s <in MP3 file> <out PCM file>\n""Examples: \n""    %s audio/test1_44100_stereo.mp3 out1_44100_16bit_stereo.pcm\n""    %s audio/test2_22050_stereo.mp3 out2_22050_16bit_stereo.pcm\n""    %s audio/test3_22050_mono.mp3   out3_22050_16bit_mono.pcm\n""    %s audio/test4_8000_mono.mp3    out4_8000_16bit_mono.pcm\n",argv[0], argv[0], argv[0], argv[0], argv[0]);return -1;}else{inMp3FileName = argv[1];outPcmFileName = argv[2];}fpInMP3 = fopen(inMp3FileName, "rb");if(!fpInMP3){perror("open input MP3 file failed");goto exit;}fpOutPcm = fopen(outPcmFileName, "wb");if(!fpOutPcm){perror("open output PCM file failed");goto exit;}/* MP3 decode 1/4: init handler */hip = hip_decode_init();if(!hip){printf("init mp3 decoder failed!\n");goto exit;}int readMP3Bytes = -1;int samples = -1;int samplesRate = -1;int channels = -1;mp3data_struct mp3Info = {};/* MP3 decode 2/4: read MP3 header info */do{readMP3Bytes =  fread(mp3Buf, 1, 16, fpInMP3);hip_decode_headers(hip, mp3Buf, readMP3Bytes, pcm_l, pcm_r, &mp3Info);samplesRate = mp3Info.samplerate;channels = mp3Info.stereo;		}while(!mp3Info.header_parsed && readMP3Bytes > 0);// don't need to reset file position//fseek(fpInMP3, 0, SEEK_SET);printf("Input MP3 Info: \n""    samplesRate: %d\n""    channels: %d\n",samplesRate, channels);while(1){readMP3Bytes = fread(mp3Buf, 1, 418, fpInMP3);if(readMP3Bytes <= 0)break;/* MP3 decode 3/4: decode MP3 data */samples = hip_decode(hip, mp3Buf, readMP3Bytes, pcm_l, pcm_r);if(samples > 0){DEBUG("read MP3 bytes: %d \t decode output samples: %d\n", readMP3Bytes, samples);for(int i = 0; i < samples; i++){fwrite(pcm_l + i, 2, 1, fpOutPcm); /* pcm_l/pcm_r type is 'short', so the 'i' don't to multi 2 */if(channels == 2){fwrite(pcm_r + i, 2, 1, fpOutPcm);}}}}printf("\e[32m%s -> %s success\e[0m\n", inMp3FileName, outPcmFileName);exit:/* MP3 decode 4/4: decode exit */if(hip) hip_decode_exit(hip);if(fpOutPcm) {fflush(fpOutPcm);fclose(fpOutPcm);}if(fpInMP3) fclose(fpInMP3);return 0;
}

3、demo下载地址(任选一个)

  • https://download.csdn.net/download/weixin_44498318/89525484

  • https://gitee.com/linriming/audio_mp32pcm_with_libmp3lame.git

  • https://github.com/linriming20/audio_mp32pcm_with_libmp3lame.git

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/43461.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

显示渲染-OSG框架解析

1.背景介绍 1.1 OSG介绍 OSG的全称&#xff1a;OpenSceneGraph&#xff0c;它是一个开放源码&#xff0c;跨平台的图形开发包&#xff0c;它为诸如飞行器仿真&#xff0c;游戏&#xff0c;虚拟现实&#xff0c;科学计算可视化这样的高性能图形应用程序开发而设计。 它基于场…

Springboot随机端口配置

网上所有地方都告诉你的错误配置: server: port: ${random.int[6008,6009]} 这才是正确配置: server: port: ${random.int(6008,6009)} 如果能解决你的问题请记得点赞&#xff01;让更多人知道&#xff01;

DNS缓存详解

目录 一、缓存分类 1. 客户端缓存&#xff08;以浏览器缓存为列&#xff09; 2. 操作系统缓存 3.本地hosts文件静态映射 二、DNS查找优先顺序 1.浏览器查找顺序 2.cmd ping查找顺序&#xff08;非浏览器&#xff09; 一、缓存分类 在一台终端上&#xff0c;DNS缓存可以…

Android 12系统源码_设备设置(一)Settings介绍

前言 Settings 类是一个用于访问和管理设备设置的关键类&#xff0c;而作为系统开发人员&#xff0c;经常需要用这个类来做一些系统设备设置&#xff0c;而Settings里面存在着好几个处理不同领域的设备设置类&#xff0c;那么如何才能结合自己的业务场景正确选择使用这些设备设…

微信小程序开发跳转京东,淘宝小程序

没有淘宝小程序&#xff0c;所以只能提示他复制链接网页打开 跳转京东小程序 获取京东小程序 京东小程序appId&#xff1a;wx91d27dbf599dff74 或者点开京东小程序&#xff0c;查看详情即可获取到京东的appid 店铺页面路径 店铺首页&#xff1a;pages/shop/index/index?…

《无所不能的JavaScript · prototype 原型链》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; 近期刚转战 CSDN&#xff0c;会严格把控文章质量&#xff0c;绝不滥竽充数&#xff0c;欢迎多多交流。&am…

OpenWrt入门 (1) - 登录及ssh命令接入wifi

本文参考自: [OpenWrt 维基]在 OpenWrt 上启用 Wi-Fi 接入点 --- [OpenWrt Wiki] Enabling a Wi-Fi access point on OpenWrt 需要详细了解的小伙伴请看原文 基本概念 OpenWrt是适用于嵌入式设备的一个Linux发行版。 相对原厂固件而言&#xff0c;OpenWrt不是一个单一、静态…

企业如何从无序管理走向精益生产管理?

先来看看企业生产管理无序的弊端有哪些&#xff1f; 数据统计不及时&#xff1a;纸质生产工单&#xff0c;数据难统计&#xff0c;各业务环节问题难定位&#xff0c;影响车间生产效率。生产过程不透明&#xff1a;生产过程数据难监控&#xff0c;生产派工管理混乱&#xff0c;…

【前端】面试八股文——meta标签

【前端】面试八股文——meta标签 在HTML文档中&#xff0c;meta标签是一个关键但常被忽视的元素。它位于文档的<head>部分&#xff0c;用于提供关于HTML文档的元数据&#xff08;metadata&#xff09;。这些元数据不会直接显示在页面上&#xff0c;但对搜索引擎优化&…

web前端开发——标签一

今天我来针对web前端开发讲解标签一 Html标签_标题&段落&换行 注释标签&#xff1a;Ctrl/ Ctrl/ &#xff0c;用户可能会获取到注释标签 注释的原则: •和代码逻辑一致 •尽量使用中文 •正能量 标题标签&#xff1a;<h1></h1> h1-h6 标题标签有6…

C++线程锁std::mutex

基本用法 “mutex”是“mutual exclusion”的缩写&#xff0c;意思是互斥锁。互斥锁用于多线程编程中&#xff0c;以确保同一时间只有一个线程能够访问某一共享资源&#xff0c;从而避免数据竞争和不一致性。 std::mutex是最基本的互斥锁&#xff0c;用于保护共享数据。它有两…

Vue3框架搭建2:axios+typescript封装

仓库地址&#xff1a;https://github.com/buguniao5213/LuArch&#xff08;分支代码未上传&#xff0c;完整一系列后传一波&#xff0c;中途有需求可以再传&#xff09; 1、安装axios npm install axios2、创建文件 先创建一个文件夹&#xff1a; ├── src/ │ ├── …

51单片机-第二节-数码管

一、数码管介绍&#xff1a; 1.什么是数码管&#xff1f; 多个LED组合成8字显示器。 2.一位数码管的引脚&#xff08;只有一个8&#xff09;&#xff1a; 数码管的引脚为1-10&#xff0c;其中公共极为3,8&#xff0c;其余八位分别对应一个二极管&#xff0c;如下图&#xff…

Vue2 基础十Vuex

代码下载 Vuex 概述 组件之间共享数据的方式&#xff1a; 父组件向子组件传值&#xff0c;是以属性的形式绑定值到子组件&#xff08;v-bind&#xff09;&#xff0c;然后子组件用属性props接收。子组件向父组件传值&#xff0c;子组件用 $emit() 自定义事件&#xff0c;父组…

JavaScript--local storage存储的数组不可扩展的问题

数组扩展 问题解析解决办法总结进一步扩展原因 问题 下列代码中的points是从本地存储中获取到的数据&#xff0c;我想存储到一个Map并且新增元素的时候报错 let obj this.objectsManager._objects.get(obstacle.uuid);let points obj.track_points;this.dyObstacleTP.set(ob…

【大模型】大模型相关技术研究—微调

为什么要对大模型进行微调 1.成本效益&#xff1a; o 大模型的参数量非常大&#xff0c;训练成本非常高&#xff0c;每家公司都去从头训练一个自己的大模型&#xff0c;这个事情的性价比非常低。 2.Prompt Engineering 的局限性&#xff1a; o Prompt Engineering 是一种相…

视图库对接系列(GA-T 1400)十二、视图库对接系列(本级)人员数据推送

背景 人体和非机动车和机动车类似的,只是请求的参数不一样而已。人员数据推送 接入人员数据推送相对比较简单,我们只需要实现对应的接口就ok了。 具体如图: 有增删改查接口,目前的话 因为我们是做平台,我们只需要实现添加接口就可以了。 接口实现 service 层 /**** …

软件工程面向对象 超市管理系统 需求分析 系统设计 课程设计报告

1、引言 系统简述 超市管理系统的功能主要有前台管理和后台管理两个大块。其使用对象 有超市管理人员和超市销售人员两类。超市管理系统主要为了实现商品输 入、 输出管理数据的自动化&#xff0c; 提高商品统计信息的实时性&#xff0c; 减轻人工劳动强 度从而节省人力成本。实…

Perl 语言开发(九):深入探索Perl语言的文件处理

目录 1. 文件打开与关闭 1.1 打开文件 1.2 关闭文件 2. 读取文件内容 2.1 逐行读取 2.2 一次性读取整个文件 3. 写入文件内容 3.1 覆盖写入 3.2 追加写入 4. 文件测试操作 4.1 文件测试运算符 5. 文件路径操作 5.1 文件路径处理模块 5.2 获取文件路径信息 6. 文…

探索加油小程序开发:便捷出行的科技新篇章

在快节奏的现代生活中&#xff0c;出行已成为人们日常生活中不可或缺的一部分。随着移动互联网技术的飞速发展&#xff0c;各类小程序以其轻量、便捷的特点迅速融入人们的日常生活&#xff0c;其中&#xff0c;加油小程序作为智慧出行领域的一股清流&#xff0c;正悄然改变着我…