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

音频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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • JS之防抖和节流
  • SQL FOREIGN KEY
  • 全网最适合入门的面向对象编程教程:12 类和对象的 Python 实现-Python 使用 logging 模块输出程序运行日志
  • [激光原理与应用-102]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 6 - 激光焊接系统的组成
  • 【密码学】分组密码概述
  • Rockchip RK3588 - Rockchip Linux SDK脚本分析
  • 探索C嘎嘎的奇妙世界:第十九关---STL(list的模拟实现)
  • Android studio之编译提示Could not find :umeng-asms-v1.2.1
  • 【MySQL数据库之概念性问题】
  • 重点区域分布式无人机探测防御系统详解
  • QUdpSocket 的bind函数详解
  • 14-57 剑和诗人31 - LLM/SLM 中的高级 RAG
  • Hospital Management Startup 1.0 SQL 注入漏洞(CVE-2022-23366)
  • Mongodb索引的删除
  • 源码编译安装 LAMP
  • @angular/forms 源码解析之双向绑定
  • 【EOS】Cleos基础
  • 78. Subsets
  • ES6, React, Redux, Webpack写的一个爬 GitHub 的网页
  • javascript 哈希表
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • Python 使用 Tornado 框架实现 WebHook 自动部署 Git 项目
  • Spring Boot MyBatis配置多种数据库
  • 代理模式
  • 技术胖1-4季视频复习— (看视频笔记)
  • 检测对象或数组
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 前端面试总结(at, md)
  • 深入浅出Node.js
  • 协程
  • 延迟脚本的方式
  • 在Unity中实现一个简单的消息管理器
  • 正则与JS中的正则
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • 微龛半导体获数千万Pre-A轮融资,投资方为国中创投 ...
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​渐进式Web应用PWA的未来
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • # Kafka_深入探秘者(2):kafka 生产者
  • (1)Jupyter Notebook 下载及安装
  • (1)svelte 教程:hello world
  • (2015)JS ES6 必知的十个 特性
  • (Java实习生)每日10道面试题打卡——JavaWeb篇
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (补充)IDEA项目结构
  • (二十五)admin-boot项目之集成消息队列Rabbitmq
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (二刷)代码随想录第16天|104.二叉树的最大深度 559.n叉树的最大深度● 111.二叉树的最小深度● 222.完全二叉树的节点个数
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (过滤器)Filter和(监听器)listener
  • (接上一篇)前端弄一个变量实现点击次数在前端页面实时更新
  • (七)理解angular中的module和injector,即依赖注入
  • (四)鸿鹄云架构一服务注册中心
  • (算法)大数的进制转换