音頻demo:使用faad2將AAC數據解碼出PCM數據

1、README

前言

本demo是使用的開源項目faad2將aac數據解碼成pcm數據。

a. 編譯使用

faad2的編譯:(faad2下載地址:https://sourceforge.net/projects/faac/files/faad2-src/faad2-2.8.0/)

tar xzf faad2-2.8.8.tar.gz
cd faad2-2.8.8/
./configure --prefix=$PWD/_install
make
make install

demo的編譯使用:

$ make clean && make
$ 
$ ./aac2pcm 
Usage:./aac2pcm <in aac file> <out pcm file>
Examples:./aac2pcm ./audio/test1_44100_stereo.aac  out1_44100_16bit_stereo.pcm./aac2pcm ./audio/test2_8000_mono.aac     out2_16000_16bit_stereo.pcm  # output [samplerate] and [channels] will be auto configured.
b. 參考文章
  • 用faad解碼AAC(ADTS封裝)_gavinr的博客-CSDN博客_faad解碼aac
c. demo目錄架構
$ tree
.
├── aac_adts.c
├── aac_adts.h
├── audio
│   ├── out1_44100_16bit_stereo.pcm
│   ├── out2_16000_16bit_stereo.pcm
│   ├── test1_44100_stereo.aac
│   └── test2_8000_mono.aac
├── docs
│   └── 用faad解碼AAC(ADTS封裝)_gavinr的博客-CSDN博客_faad解碼aac.mhtml
├── include
│   ├── faad.h
│   └── neaacdec.h
├── lib
│   └── libfaad.a
├── main.c
├── Makefile
└── README.md

2、主要代碼片段

aac_adts.c
#include "aac_adts.h"int getAdtsFrame(FILE *fp, uint8_t *pAdtsFrameData, T_AdtsHeader *ptAdtsHeaderInfo)
{uint32_t readBytes = 0;if(!fp || !pAdtsFrameData || !ptAdtsHeaderInfo)return -1;// ADTS header size is AAC_ADTS_HEADER_SIZE(=7) bytesreadBytes = fread(pAdtsFrameData, 1, AAC_ADTS_HEADER_SIZE, fp);if(readBytes <= 0)return -2;ptAdtsHeaderInfo->syncword              = (pAdtsFrameData[0] << 4 ) | (pAdtsFrameData[1]  >> 4);ptAdtsHeaderInfo->id                    = (pAdtsFrameData[1] & 0x08) >> 3;ptAdtsHeaderInfo->layer                 = (pAdtsFrameData[1] & 0x06) >> 1;ptAdtsHeaderInfo->protection_absent     =  pAdtsFrameData[1] & 0x01;ptAdtsHeaderInfo->profile               = (pAdtsFrameData[2] & 0xc0) >> 6;ptAdtsHeaderInfo->sampling_freq_index   = (pAdtsFrameData[2] & 0x3c) >> 2;ptAdtsHeaderInfo->private_bit           = (pAdtsFrameData[2] & 0x02) >> 1;ptAdtsHeaderInfo->channel_configuration = (((pAdtsFrameData[2] & 0x01) << 2) | ((pAdtsFrameData[3] & 0xc0) >> 6));ptAdtsHeaderInfo->original_copy         = (pAdtsFrameData[3] & 0x20) >> 5;ptAdtsHeaderInfo->home                  = (pAdtsFrameData[3] & 0x10) >> 4;ptAdtsHeaderInfo->copyright_identification_bit   = (pAdtsFrameData[3] & 0x08) >> 3;ptAdtsHeaderInfo->copyright_identification_start = (pAdtsFrameData[3] & 0x04) >> 2;ptAdtsHeaderInfo->aac_frame_length = ((pAdtsFrameData[3] & 0x03) << 11) |((pAdtsFrameData[4] & 0xFF) << 3) |((pAdtsFrameData[5] & 0xE0) >> 5);ptAdtsHeaderInfo->adts_buffer_fullness = ((pAdtsFrameData[5] & 0x1f) << 6 | (pAdtsFrameData[6] & 0xfc) >> 2);ptAdtsHeaderInfo->number_of_raw_data_blocks_in_frame = (pAdtsFrameData[6] & 0x03);if (ptAdtsHeaderInfo->syncword != 0xFFF)return -3;/* read the remaining frame of ADTS data outside the AAC_ADTS_HEADER_SIZE(=7) bytes header,* and it should be written after offsetting the header by AAC_ADTS_HEADER_SIZE(=7) bytes*/readBytes = fread(pAdtsFrameData + AAC_ADTS_HEADER_SIZE, 1, ptAdtsHeaderInfo->aac_frame_length - AAC_ADTS_HEADER_SIZE, fp);if(readBytes <= 0)return -4;return 0;
}
aac_adts.h
#ifndef __AAC_ADTS_H__
#define __AAC_ADTS_H__#include <stdio.h>
#include <stdint.h>#define AAC_ADTS_HEADER_SIZE 	(7)#define MAX_ADTS_SIZE 			(1024) /* 1K Bytes */typedef enum{MPEG_4 = 0x0,MPEG_2 = 0x1,
}aac_id_t;typedef enum{SFI_96000 = 0x0,SFI_88200 = 0x1,SFI_64000 = 0x2,SFI_48000 = 0x3,SFI_44100 = 0x4,SFI_32000 = 0x5,SFI_24000 = 0x6,SFI_22050 = 0x7,SFI_16000 = 0x8,SFI_12000 = 0x9,SFI_11025 = 0xa,SFI_8000  = 0xb,SFI_7350  = 0xc,SFI_ERROR = 0xd,
}sampling_freq_index_t;/* AAC(ADTS) Header element member.* [Note: It is not stored as defined type size!!!]*/
typedef struct{/* fixed header */uint32_t syncword;              // 12bit  '1111 1111 1111' is stand by ADTS frameuint32_t id;                    // 1 bit  0 for MPEG-4, 1 for MPEG-2uint32_t layer;                 // 2 bit  always '00'uint32_t protection_absent;     // 1 bit  1 not crc, 0 have crc 1uint32_t profile;               // 2 bit  AAC profile, '01' for AAC-LCuint32_t sampling_freq_index;   // 4 bit  reference to 'sampling_freq_index_t'uint32_t private_bit;           // 1 bit  always '0'uint32_t channel_configuration; // 3 bit  channels countuint32_t original_copy;         // 1 bit  always '0'uint32_t home;                  // 1 bit/* varible header */uint32_t copyright_identification_bit;   // 1 bit  always '0'uint32_t copyright_identification_start; // 1 bit  always '0'uint32_t aac_frame_length;               // 13bit  length of [adts header] + [adts data]uint32_t adts_buffer_fullness;           // 11bit  0x7FF stand by varible bit rateuint32_t number_of_raw_data_blocks_in_frame;  // 2 bit  always '00', number of AAC Frames(RDBs) in ADTS frame minus 1
}T_AdtsHeader, *PT_AdtsHeader;/************************************************************************* function describe: get one frame aac(adts, include adts header) from*                    aac file.* params:*   [fp]: aac file handler.(in)*   [pAdtsFrameData]: the function will fill the aac data in it, must be*                     alloced memory before call this function.(out)*   [ptAdtsHeaderInfo]: AAC-ADTS header information in this frame.(out)* return: 0-success  other-error************************************************************************/
int getAdtsFrame(FILE *fp, uint8_t *pAdtsFrameData, T_AdtsHeader *ptAdtsHeaderInfo);#endif /*  __AAC_ADTS_H__ */
main.c
#include <stdio.h>
#include <stdlib.h>#include "aac_adts.h"
#include "faad.h"#define MAX_DEC_SIZE   (128 * 1024)int main(int argc, char *argv[])
{int ret = -1;FILE *fpAAC = NULL;FILE *fpPCM = NULL;unsigned char *aacBuf = NULL;unsigned char *pcmPtr = NULL;unsigned char channels = 0;unsigned long sampleRate = 0;T_AdtsHeader adtsHeader = {};NeAACDecHandle aacDecHandler = 0;NeAACDecFrameInfo aacDecFrameInfo = {};uint32_t audioSampleRate = -1;if(argc != 3){printf("Usage:\n""    %s <in aac file> <out pcm file>\n""Examples:\n""    %s ./audio/test1_44100_stereo.aac  out1_44100_16bit_stereo.pcm\n""    %s ./audio/test2_8000_mono.aac     out2_16000_16bit_stereo.pcm  # output [samplerate] and [channels] will be auto configured.\n",argv[0], argv[0], argv[0]);return -1;}/* open file */fpAAC = fopen(argv[1], "rb");fpPCM = fopen(argv[2], "wb");if(!fpAAC || !fpPCM){printf("[%s:%d] open <%s> or <%s> file failed!\n", __FUNCTION__, __LINE__, argv[1], argv[2]);goto exit;}/* alloc memory */aacBuf = (unsigned char *)malloc(MAX_DEC_SIZE);if(!aacBuf){printf("[%s:%d] alloc memory for aacBuf failed!\n", __FUNCTION__, __LINE__);goto exit;}/* aac decode 1/4: open aac decoder */aacDecHandler = NeAACDecOpen();/* use to configure decoder params */ret = getAdtsFrame(fpAAC, aacBuf, &adtsHeader);if(ret < 0){if(ret == -2){printf("aac file end!\n");goto exit;}else{printf("[%s:%d] get adts frame failed with %d!\n", __FUNCTION__, __LINE__, ret);goto exit;}}else{fseek(fpAAC, 0, SEEK_SET); // reset/* aac decode 2/4: init aac decoder params */NeAACDecInit(aacDecHandler, aacBuf, adtsHeader.aac_frame_length, &sampleRate, &channels);printf("\e[32m>>> will be decoded output with [samplerate: %lu], [channels: %d]<<<\e[0m\n", sampleRate, channels);}while(1){ret = getAdtsFrame(fpAAC, aacBuf, &adtsHeader);if(ret < 0){if(ret == -2){printf("aac file end!\n");break;}else{printf("[%s:%d] get adts frame failed with %d!\n", __FUNCTION__, __LINE__, ret);goto exit;}}//printf("get one adts frame with size: %d\n", adtsHeader.aac_frame_length);/* aac decode 3/4: decode */pcmPtr = (unsigned char*)NeAACDecDecode(aacDecHandler, &aacDecFrameInfo, aacBuf, adtsHeader.aac_frame_length/* include header */);if(aacDecFrameInfo.error > 0){printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, NeAACDecGetErrorMessage(aacDecFrameInfo.error));goto exit;}else if(pcmPtr && aacDecFrameInfo.samples > 0){printf("<in> [aac frame size: %lu] [header type: %s] ""[profile: %s]    |    <out> [samplerate: %lu] [samples cnt: %lu] [channels: %d] \n",aacDecFrameInfo.bytesconsumed, aacDecFrameInfo.header_type == 2 ? "ADTS" : "Other", aacDecFrameInfo.object_type == 2 ? "LC" : "Other", aacDecFrameInfo.samplerate,aacDecFrameInfo.samples,aacDecFrameInfo.channels);fwrite(pcmPtr, 1, aacDecFrameInfo.samples * aacDecFrameInfo.channels, fpPCM);}else{printf("[%s:%d] Unknown decode error!\n", __FUNCTION__, __LINE__);}}/* aac decode 1/4: close aac decoder */NeAACDecClose(aacDecHandler);printf("\e[32mSuccess!\e[0m\n");exit:if(fpAAC) fclose(fpAAC);if(fpPCM) {fflush(fpPCM); fclose(fpPCM);}if(aacBuf) free(aacBuf);return 0;
}

3、demo下載地址(任選一個)

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

  • https://gitee.com/linriming/audio_aac2pcm_with_faad2

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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/42981.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/42981.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/42981.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【數據結構】單鏈表:數據結構中的舞者,穿梭于理論與實踐的舞池

歡迎來到白劉的領域 Miracle_86.-CSDN博客 系列專欄 數據結構與算法 先贊后看&#xff0c;已成習慣 創作不易&#xff0c;多多支持&#xff01; 一、鏈表的概念和結構 1.1 鏈表的概念 在上一篇文章中&#xff0c;我們了解了線性表(linear list)&#xff0c;并且學習了其…

Spring——IOC創建對象方式

可參考官網&#xff1a;https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.htmlhttps://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html 1. 使用無參構造創建對象&#xff0…

數據庫性能優化系統設計

設計一個數據庫性能優化系統&#xff0c;目標是監測、診斷并改善數據庫的運行效率&#xff0c;確保系統能夠高效穩定地處理大量數據請求。以下是一個概要設計&#xff0c;包括關鍵模塊、功能和實現思路&#xff1a; 1. 系統架構 分布式監控中心&#xff1a;采用分布式架構收集…

C++ STL 協程(Coroutines)

一:什么是協程(Coroutines): 協程是輕量級線程,可以暫停和恢復執行,協程擁有自己的暫停點狀態,協程暫停時,將當前狀態保存起來,在恢復執行時會恢復之前保存的狀態。 二:例子: #include <coroutine> #include <iostream>void doTheWork() {std::cout <…

PHP寶藏神器多功能投票系統源碼小程序

&#x1f389;發現寶藏神器&#xff01;一鍵解鎖“多功能投票小程序”的無限可能? &#x1f308; 開篇安利&#xff1a;告別繁瑣&#xff0c;擁抱高效&#xff01; Hey小伙伴們&#xff0c;是不是經常為組織活動、收集意見而頭疼不已&#xff1f;&#x1f92f; 今天就要給大…

【理解STL】

目錄 一、STL的概念1、STL的定義2、STL的組成 二、容器1、容器的定義及作用2、string類&#xff08;非容器&#xff09;3、vector容器4、set容器5、queue容器6、priority_queue容器7、stack容器8、deque容器9、map容器10、pair容器11、bitset容器12、map和set的區別13、vector和…

Node 中基于 Koa 框架的 Web 服務搭建實戰

前言 在《Node之Web服務 - 掘金 (juejin.cn)》一文中,我們使用 HTTP 模塊構建了后端接口,從而實現了后端服務的開發。可以對此進行進一步優化 http模塊代碼回顧 const http require("http");const server http.createServer((req, res) > {if (reqUrl.pathna…

Python前沿技術:機器學習與人工智能

Python前沿技術&#xff1a;機器學習與人工智能 一、引言 隨著科技的飛速發展&#xff0c;機器學習和人工智能&#xff08;AI&#xff09;已經成為了計算機科學領域的熱門話題。Python作為一門易學易用且功能強大的編程語言&#xff0c;已經成為了這兩個領域的首選語言之一。本…

【零基礎】學JS

喝下這碗雞湯 “知識就是力量。” - 弗朗西斯培根 1.三元運算符 目標:能利用三元運算符執行滿足條件的語句 使用場景:其實是比if雙分支更簡單的寫法&#xff0c;可以使用三元表達式 語法&#xff1a;條件 ? 滿足條件的執行代碼 : 不滿足條件執行的代碼 接下來用一個小案例來展…

C#實現求解函數導數和值

using MathNet.Symbolics; using System; using System.IO; using System.Text;private string ConvertToLatex(string mathExpression) {return mathExpression.Replace(" * ", "").Replace("*", ""); }// 將函數定義為字符串 string…

AI語言處理的雙刃劍:Tokens令牌化技術解析

生成式人工智能模型&#xff0c;如GPT-4o&#xff0c;采用基于Transformer架構的復雜處理方式&#xff0c;這與人類處理文本的方式存在明顯差異。這些模型依賴于一種稱為“令牌化”的過程&#xff0c;將文本分解為更小的片段&#xff0c;稱為“令牌”&#xff0c;以便更有效地處…

Kafka拋棄Zookeeper后如何啟動?

Kafaka如何下載 官網地址 目前Kafka最新的版本就是3.7.1 我們可以看到下面這兩個版本信息&#xff1f;什么意思呢&#xff1f; Scala 2.12 - kafka_2.12-3.7.1.tgz (asc, sha512)Scala 2.13 - kafka_2.13-3.7.1.tgz (asc, sha512) 我們應該知道&#xff0c;一個完整的Kafka實…

平安消保在行動 | 守護每一個舒心笑容 不負每一場雙向奔赴

“要時刻記得以消費者為中心&#xff0c;把他們當做自己的朋友&#xff0c;站在他們的角度去思考才能更好地解決問題。” 談及如何成為一名合格的消費者權益維護工作人員&#xff0c;平安養老險深圳分公司負責咨訴工作的龐宏霄認為&#xff0c;除了要具備扎實的專業技能和溝通…

MySQL篇四:表的約束

文章目錄 前言1. 空屬性2. 默認值3. 列描述4. zerofill5. 主鍵6. 自增長7. 唯一鍵8. 外鍵 前言 真正約束字段的是數據類型&#xff0c;但是數據類型約束很單一&#xff0c;需要有一些額外的約束&#xff0c;更好的保證數據的合法性&#xff0c;從業務邏輯角度保證數據的正確性。…

JAVA學習筆記-JAVA基礎語法-DAY24-Stream流、方法引用

第一章 Stream流 說到Stream便容易想到I/O Stream&#xff0c;而實際上&#xff0c;誰規定“流”就一定是“IO流”呢&#xff1f;在Java 8中&#xff0c;得益于Lambda所帶來的函數式編程&#xff0c;引入了一個全新的Stream概念&#xff0c;用于解決已有集合類庫既有的弊端。 …

python 高級技巧 0708

python 33個高級用法技巧 使用裝飾器計時函數 裝飾器是一種允許在一個函數或方法調用前后運行額外代碼的結構。 import timedef timer(func):"""裝飾器函數&#xff0c;用于計算函數執行時間并打印。參數:func (function): 被裝飾的函數返回:function: 包裝后…

軟件架構之開發方法

軟件架構之開發方法 第6章&#xff1a;開發方法6.1 軟件生命周期6.2 軟件開發模型6.2.1 瀑布模型6.2.2 演化模型6.2.3 螺旋模型6.2.4 增量模型6.2.5 構件組裝模型 6.3 統一過程6.4 敏捷方法6.4.1 極限編程6.4.2 特征驅動開發6.4.3 Scrum6.4.4 水晶方法6.4.5 其他敏捷方法 6.5 軟…

vmware lun回收引起的IO問題

起初并沒人關注的小問題,正常不過的虛機存儲遷移操作,引起的延遲卻引發一連串的變化。 環境 vsphere 6.7 + 華為集中式存儲 開始 下午5:17 業務反饋,存在數據超時,頻繁在1秒鐘以內,正常在200ms。需運維排查虛機的狀態與IO情況等硬件使用情況。下午5:30 隨手翻開zabbix 打開…

vue在線預覽excel、pdf、word文件

安裝 //docx文檔預覽組件 npm install vue-office/docx vue-demi//excel文檔預覽組件 npm install vue-office/excel vue-demi//pdf文檔預覽組件 npm install vue-office/pdf vue-demi使用示例 docx文檔的預覽 <template><vue-office-docx :src"src" ren…

【嵌入式Linux】<知識點> 虛擬地址空間

前言 在Linux中&#xff0c;新創建的進程都擁有獨立的虛擬地址空間。為深入多進程多線程的理解&#xff0c;了解虛擬地址空間分區十分有必要。 一、概念 虛擬地址空間分為4G空間&#xff0c;其中1G為內核區&#xff0c;3G為用戶區。虛擬地址空間的地址從0開始&#xff0c;且該…