AAC音频文件

简介

AAC是高级音频编码(Advanced Audio Coding)的缩写,出现于1997年,最初是基于MPEG-2的音频编码技术。由Fraunhofer IIS、Dolby Laboratories、AT&T、Sony等公司共同开发,目的是取代MP3格式。

AAC音频文件格式

AAC音频文件的每一帧都由一个ADTS头和AAC ES(AAC音频数据)组成。
ADTS头包含了AAC文件的采样率、通道数、帧数据长度等信息。ADTS头分为固定头信息和可变头信息两个部分,固定头信息在每个帧中的是一样的,可变头信息在各个帧中并不是固定值。ADTS头一般是7个字节((28+28)/ 8)长度,如果需要对数据进行CRC校验,则会有2个Byte的校验码,所以ADTS头的实际长度是7个字节或9个字节。
头信息分为两部分:adts_fixed_header和adts_variable_header。
其中adts_fixed_header长度固定为 28bit,并且内容是固定的,不跟随包大小变化。而adts_variable_header内容、长度可变,为28bit或44bit。

格式如下:

在这里插入图片描述
当protection_absend为1时表示无crc, ADTS可变头长度 为28bit;当protection_absend为为0时,可变头长度为44bit。

ffmpeg添加adts头


#define ADTS_HEADER__LEN 7

const int sampling_frequencies[] = {
	96000,  // 0x0
	88200,  // 0x1
	64000,  // 0x2
	48000,  // 0x3
	44100,  // 0x4
	32000,  // 0x5
	24000,  // 0x6
	22050,  // 0x7
	16000,  // 0x8
	12000,  // 0x9
	11025,  // 0xa
	8000   // 0xb
	// 0xc d e f是保留的
};

int adts_header(char* const p_adts_header, const int data_length,
	const int profile, const int samplerate,
	const int channels)
{

	int sampling_frequency_index = 3; // 默认使用48000hz
	int adtsLen = data_length + 7;

	int frequencies_size = sizeof(sampling_frequencies) / sizeof(sampling_frequencies[0]);
	int i = 0;
	for (i = 0; i < frequencies_size; i++)
	{
		if (sampling_frequencies[i] == samplerate)
		{
			sampling_frequency_index = i;
			break;
		}
	}
	if (i >= frequencies_size)
	{
		printf("unsupport samplerate:%d\n", samplerate);
		return -1;
	}

	p_adts_header[0] = 0xff;         //syncword:0xfff                          高8bits
	p_adts_header[1] = 0xf0;         //syncword:0xfff                          低4bits
	p_adts_header[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
	p_adts_header[1] |= (0 << 1);    //Layer:0                                 2bits
	p_adts_header[1] |= 1;           //protection absent:1                     1bit

	p_adts_header[2] = (profile) << 6;            //profile:profile               2bits
	p_adts_header[2] |= (sampling_frequency_index & 0x0f) << 2; //sampling frequency index:sampling_frequency_index  4bits
	p_adts_header[2] |= (0 << 1);             //private bit:0                   1bit
	p_adts_header[2] |= (channels & 0x04) >> 2; //channel configuration:channels  高1bit

	p_adts_header[3] = (channels & 0x03) << 6; //channel configuration:channels 低2bits
	p_adts_header[3] |= (0 << 5);               //original:0                1bit
	p_adts_header[3] |= (0 << 4);               //home:0                    1bit
	p_adts_header[3] |= (0 << 3);               //copyright id bit:0        1bit
	p_adts_header[3] |= (0 << 2);               //copyright id start:0      1bit
	p_adts_header[3] |= ((adtsLen & 0x1800) >> 11);           //frame length:value   高2bits

	p_adts_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
	p_adts_header[5] = (uint8_t)((adtsLen & 0x7) << 5);       //frame length:value    低3bits
	p_adts_header[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
	p_adts_header[6] = 0xfc;      //11111100      //buffer fullness:0x7ff 低6bits
	// number_of_raw_data_blocks_in_frame:
	//    表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。

	return 0;
}

大家可以用AAC Audio ES Viewer工具来查看AAC的ADTS Header。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在 MFC 框架下读取 AAC 音频文件并进行解码,可以使用开源的解码库如 FFMPEG 或者 OpenAL,这些库都提供了相应的 API 接口,可以在 MFC 中调用。 以下是一个简单的示例代码,使用 FFMPEG 库实现读取 AAC 音频文件并解码: ```c++ #include <iostream> #include <string> #include <vector> #include <fstream> #include <sstream> // FFmpeg 头文件 extern "C" { #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libswresample/swresample.h> } int main() { const char* input_filename = "test.aac"; // AAC 音频文件路径 const char* output_filename = "output.pcm"; // 输出解码后的 PCM 数据路径 // 1. 初始化 FFmpeg 库 av_register_all(); avcodec_register_all(); // 2. 打开输入音频文件 AVFormatContext* format_ctx = nullptr; if (avformat_open_input(&format_ctx, input_filename, nullptr, nullptr) != 0) { std::cerr << "Error: could not open input file " << input_filename << std::endl; return -1; } // 3. 获取音频流信息 if (avformat_find_stream_info(format_ctx, nullptr) < 0) { std::cerr << "Error: could not find stream information" << std::endl; avformat_close_input(&format_ctx); return -1; } // 4. 查找音频流 int audio_stream_index = -1; for (unsigned int i = 0; i < format_ctx->nb_streams; i++) { if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audio_stream_index = i; break; } } if (audio_stream_index == -1) { std::cerr << "Error: could not find audio stream" << std::endl; avformat_close_input(&format_ctx); return -1; } // 5. 获取音频解码器 AVCodecParameters* codecpar = format_ctx->streams[audio_stream_index]->codecpar; AVCodec* codec = avcodec_find_decoder(codecpar->codec_id); if (codec == nullptr) { std::cerr << "Error: could not find decoder for codec ID " << codecpar->codec_id << std::endl; avformat_close_input(&format_ctx); return -1; } // 6. 打开音频解码器 AVCodecContext* codec_ctx = avcodec_alloc_context3(codec); if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) { std::cerr << "Error: could not copy codec parameters to decoder context" << std::endl; avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); return -1; } if (avcodec_open2(codec_ctx, codec, nullptr) < 0) { std::cerr << "Error: could not open decoder" << std::endl; avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); return -1; } // 7. 初始化音频重采样器 SwrContext* swr_ctx = swr_alloc_set_opts(nullptr, codec_ctx->channel_layout, AV_SAMPLE_FMT_S16, codec_ctx->sample_rate, codec_ctx->channel_layout, codec_ctx->sample_fmt, codec_ctx->sample_rate, 0, nullptr); if (swr_ctx == nullptr) { std::cerr << "Error: could not allocate resampler context" << std::endl; avcodec_close(codec_ctx); avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); return -1; } if (swr_init(swr_ctx) < 0) { std::cerr << "Error: could not initialize resampler context" << std::endl; swr_free(&swr_ctx); avcodec_close(codec_ctx); avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); return -1; } // 8. 打开输出文件 std::ofstream output_file(output_filename, std::ios::binary); if (!output_file.is_open()) { std::cerr << "Error: could not open output file " << output_filename << std::endl; swr_free(&swr_ctx); avcodec_close(codec_ctx); avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); return -1; } // 9. 解码音频数据 AVPacket packet; av_init_packet(&packet); packet.data = nullptr; packet.size = 0; AVFrame* frame = av_frame_alloc(); while (av_read_frame(format_ctx, &packet) >= 0) { if (packet.stream_index == audio_stream_index) { if (avcodec_send_packet(codec_ctx, &packet) == 0) { while (avcodec_receive_frame(codec_ctx, frame) == 0) { // 重采样音频数据 std::vector<uint8_t> buffer(codec_ctx->channels * frame->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)); uint8_t* output_data[1] = { buffer.data() }; int output_samples = swr_convert(swr_ctx, output_data, frame->nb_samples, (const uint8_t**)frame->extended_data, frame->nb_samples); if (output_samples > 0) { output_file.write((char*)buffer.data(), output_samples * codec_ctx->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)); } } } } av_packet_unref(&packet); } // 10. 释放资源 av_frame_free(&frame); swr_free(&swr_ctx); avcodec_close(codec_ctx); avcodec_free_context(&codec_ctx); avformat_close_input(&format_ctx); return 0; } ``` 该示例程序会把读取的 AAC 音频文件解码并重采样成 16 位 PCM 数据,然后保存到输出文件中。你可以根据需要修改代码,以满足你的具体需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

都市无名者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值