音频demo:使用faad2将AAC数据解码出PCM数据

embedded/2024/10/19 0:21:27/

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_adtsc_65">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_adtsh_116">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.ppmy.cn/embedded/58708.html

相关文章

加密与安全_密钥体系的三个核心目标之完整性解决方案

文章目录 Pre机密性完整性1. 哈希函数&#xff08;Hash Function&#xff09;定义特征常见算法应用散列函数常用场景散列函数无法解决的问题 2. 消息认证码&#xff08;MAC&#xff09;概述定义常见算法工作原理如何使用 MACMAC 的问题 不可否认性数字签名&#xff08;Digital …

如何在 PostgreSQL 中实现数据的去重操作,尤其是对于复杂的数据结构?

文章目录 一、基本数据类型的去重二、多列数据的去重三、复杂数据结构的去重&#xff08;一&#xff09;数组类型的去重&#xff08;二&#xff09;JSON 类型的去重&#xff08;三&#xff09;结构体类型&#xff08;复合类型&#xff09;的去重 四、使用 GROUP BY 进行去重五、…

Java面试题系列 - 第7天

题目&#xff1a;Java中的反射机制及其应用场景 背景说明&#xff1a;Java的反射机制允许运行时检查类的信息和动态调用方法&#xff0c;这在很多框架和库中被广泛使用&#xff0c;例如Spring框架的依赖注入、JDBC的数据库连接、以及各种ORM框架等。理解反射机制对于深入学习J…

Android EditText+ListPopupWindow实现可编辑的下拉列表

Android EditTextListPopupWindow实现可编辑的下拉列表 &#x1f4d6;1. 可编辑的下拉列表✅步骤一&#xff1a;准备视图✅步骤二&#xff1a;封装显示方法✅步骤三&#xff1a;获取视图并监听 &#x1f4d6;2. 扩展上下箭头✅步骤一&#xff1a;准备上下箭头icon图标✅步骤二&…

【MindSpore学习打卡】应用实践-LLM原理和实践-基于MindSpore实现BERT对话情绪识别

在当今的自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;情绪识别是一个非常重要的应用场景。无论是在智能客服、社交媒体分析&#xff0c;还是在情感计算领域&#xff0c;准确地识别用户的情绪都能够极大地提升用户体验和系统的智能化水平。BERT&#xff08;Bidirec…

Windows右键没有新建Word、PPT与Excel的解决方法

本文介绍在Windows电脑中&#xff0c;右键与资源管理器的“新建”选项中&#xff0c;都没有新建Word、PPT或Excel文件的解决方法。 最近&#xff0c;发现一台重装了系统与Office的电脑中&#xff0c;无论是桌面上与资源管理器中的右键&#xff0c;还是资源管理器左侧顶部的“新…

[Linux]基本指令(二)

一些剩下的指令部分 mv指令&#xff08;重要&#xff09; mv 命令是 move 的缩写&#xff0c;可以用来移动文件或者将文件改名&#xff08; move (rename) files &#xff09;&#xff0c;是 Linux 系统下常用的命令&#xff0c; 经常用来备份文件或者目录。 语法 : mv [ 选项…

MySQL-数据库管理:优化、安全、合规与迁移的全面解析

1. 数据库设计 1.1 需求分析 数据库设计的第一步是深入理解应用的需求。这通常涉及到与项目团队&#xff08;包括产品经理、开发者、业务分析师等&#xff09;的紧密合作&#xff0c;以确保数据库设计能够准确地反映业务需求。需求分析阶段的关键活动包括&#xff1a; 收集信…