音頻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.pswp.cn/diannao/43461.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43461.shtml
英文地址,請注明出處:http://en.pswp.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;正悄然改變著我…