将faad2转码方法移植到C++

本文介绍了如何将FAAD2的AAC转码功能移植到C++,主要涉及将静态方法和常量封装到类中,并在VS2012环境下进行编译配置。操作步骤包括创建MFC Dialog工程,添加libfaad和mp4ff项目,设置生成路径,添加预处理器定义,以及添加库依赖。同时提供了FAAD2和测试工程的下载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

faad2中的测试工程在文件夹frontend中,主要代码在main.c和audio.c文件中。

这里只实现AAC转码WAV的功能。

注:编译环境为VS2012,faad2-2.7。

1、main.c

分析main.c文件中的代码,将静态方法和常量分别摘取出来,放入CFaad2Helper类和Constants类。

Faad2Helper.h

#pragma once

#include "neaacdec.h"
#include "mp4ff.h"

#include <string>
using namespace std;

/* FAAD file buffering routines */
typedef struct {
	long bytes_into_buffer;
	long bytes_consumed;
	long file_offset;
	unsigned char *buffer;
	int at_eof;
	FILE *infile;
} aac_buffer;

//Faad2静态方法帮助类
class CFaad2Helper
{
public:
	CFaad2Helper(void);
	~CFaad2Helper(void);

	static int decodeAACfile(char *aacfile, char *sndfile, char *adts_fn, int to_stdout,
		int def_srate, int object_type, int outputFormat, int fileType,
		int downMatrix, int infoOnly, int adts_out, int old_format,
		float *song_length);

	static int decodeMP4file(char *mp4file, char *sndfile, char *adts_fn, int to_stdout,
		int outputFormat, int fileType, int downMatrix, int noGapless,
		int infoOnly, int adts_out, float *song_length);

	static string GetLastErrMsg();

private:
	static void faad_fprintf(const char *prefix, const char *msg);
	static void faad_fprintf(const char *msg);

	static void print_channel_info(NeAACDecFrameInfo *frameInfo);

	static int fill_buffer(aac_buffer *b);
	static void advance_buffer(aac_buffer *b, int bytes);
	static int adts_parse(aac_buffer *b, int *bitrate, float *length);
	static long aacChannelConfig2wavexChannelMask(NeAACDecFrameInfo *hInfo);
	static char *position2string(int position);
	static int FindAdtsSRIndex(int sr);
	static unsigned char *MakeAdtsHeader(int *dataSize, NeAACDecFrameInfo *hInfo, int old_format);
	static int GetAACTrack(mp4ff_t *infile);

private:
	static string m_sLastErrMsg;	//错误信息
};

Faad2Helper.cpp

#include "stdafx.h"
#include "Faad2Helper.h"
#include "Audio.h"
#include "Constants.h"

#include <cstdio>
#include <sstream>

static int adts_sample_rates[] = {96000,88200,64000,48000,44100,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0};

string CFaad2Helper::m_sLastErrMsg = "";

CFaad2Helper::CFaad2Helper(void)
{
}


CFaad2Helper::~CFaad2Helper(void)
{
}

string CFaad2Helper::GetLastErrMsg()
{
	return m_sLastErrMsg;
}

void CFaad2Helper::faad_fprintf(const char *prefix, const char *msg)
{
	std::stringstream ss;
	ss.clear();
	ss.str("");
	ss << "打开文件错误:" << msg;

	m_sLastErrMsg = ss.str();
}
void CFaad2Helper::faad_fprintf(const char *msg)
{
	m_sLastErrMsg = msg;
}

void CFaad2Helper::print_channel_info(NeAACDecFrameInfo *frameInfo)
{
	/* print some channel info */
	//将此函数置为空
#ifdef PRINT_CHANNEL_INFO
	int i;
	long channelMask = aacChannelConfig2wavexChannelMask(frameInfo);

	faad_fprintf(stderr, "  ---------------------\n");
	if (frameInfo->num_lfe_channels > 0)
	{
		faad_fprintf(stderr, " | Config: %2d.%d Ch     |", frameInfo->channels-frameInfo->num_lfe_channels, frameInfo->num_lfe_channels);
	} else {
		faad_fprintf(stderr, " | Config: %2d Ch       |", frameInfo->channels);
	}
	if (channelMask)
		faad_fprintf(stderr, " WARNING: channels are reordered according to\n");
	else
		faad_fprintf(stderr, "\n");
	faad_fprintf(stderr, "  ---------------------");
	if (channelMask)
		faad_fprintf(stderr, "  MS defaults defined in WAVE_FORMAT_EXTENSIBLE\n");
	else
		faad_fprintf(stderr, "\n");
	faad_fprintf(stderr, " | Ch |    Position    |\n");
	faad_fprintf(stderr, "  ---------------------\n");
	for (i = 0; i < frameInfo->channels; i++)
	{
		faad_fprintf(stderr, " | %.2d | %-14s |\n", i, position2string((int)frameInfo->channel_position[i]));
	}
	faad_fprintf(stderr, "  ---------------------\n");
	faad_fprintf(stderr, "\n");
#endif // PRINT_CHANNEL_INFO
}

int CFaad2Helper::fill_buffer(aac_buffer *b)
{
	int bread;

	if (b->bytes_consumed > 0)
	{
		if (b->bytes_into_buffer)
		{
			memmove((void*)b->buffer, (void*)(b->buffer + b->bytes_consumed),
				b->bytes_into_buffer*sizeof(unsigned char));
		}

		if (!b->at_eof)
		{
			bread = fread((void*)(b->buffer + b->bytes_into_buffer), 1,
				b->bytes_consumed, b->infile);

			if (bread != b->bytes_consumed)
				b->at_eof = 1;

			b->bytes_into_buffer += bread;
		}

		b->bytes_consumed = 0;

		if (b->bytes_into_buffer > 3)
		{
			if (memcmp(b->buffer, "TAG", 3) == 0)
				b->bytes_into_buffer = 0;
		}
		if (b->bytes_into_buffer > 11)
		{
			if (memcmp(b->buffer, "LYRICSBEGIN", 11) == 0)
				b->bytes_into_buffer = 0;
		}
		if (b->bytes_into_buffer > 8)
		{
			if (memcmp(b->buffer, "APETAGEX", 8) == 0)
				b->bytes_into_buffer = 0;
		}
	}

	return 1;
}

void CFaad2Helper::advance_buffer(aac_buffer *b, int bytes)
{
	b->file_offset += bytes;
	b->bytes_consumed = bytes;
	b->bytes_into_buffer -= bytes;
	if (b->bytes_into_buffer < 0)
		b->bytes_into_buffer = 0;
}

int CFaad2Helper::adts_parse(aac_buffer *b, int *bitrate, float *length)
{
	int frames, frame_length;
	int t_framelength = 0;
	int samplerate;
	float frames_per_sec, bytes_per_frame;

	/* Read all frames to ensure correct time and bitrate */
	for (frames = 0; /* */; frames++)
	{
		fill_buffer(b);

		if (b->bytes_into_buffer > 7)
		{
			/* check syncword */
			if (!((b->buffer[0] == 0xFF)&&((b->buffer[1] & 0xF6) == 0xF0)))
				break;

			if (frames == 0)
				samplerate = adts_sample_rates[(b->buffer[2]&0x3c)>>2];

			frame_length = ((((unsigned int)b->buffer[3] & 0x3)) << 11)
				| (((unsigned int)b->buffer[4]) << 3) | (b->buffer[5] >> 5);

			t_framelength += frame_length;

			if (frame_length > b->bytes_into_buffer)
				break;

			advance_buffer(b, frame_length);
		} else {
			break;
		}
	}

	frames_per_sec = (float)samplerate/1024.0f;
	if (frames != 0)
		bytes_per_frame = (float)t_framelength/(float)(frames*1000);
	else
		bytes_per_frame = 0;
	*bitrate = (int)(8. * bytes_per_frame * frames_per_sec + 0.5);
	if (frames_per_sec != 0)
		*length = (float)frames/frames_per_sec;
	else
		*length = 1;

	return 1;
}

long CFaad2Helper::aacChannelConfig2wavexChannelMask(NeAACDecFrameInfo *hInfo)
{
	if (hInfo->channels == 6 && hInfo->num_lfe_channels)
	{
		return SPEAKER_FRONT_LEFT + SPEAKER_FRONT_RIGHT +
			SPEAKER_FRONT_CENTER + SPEAKER_LOW_FREQUENCY +
			SPEAKER_BACK_LEFT + SPEAKER_BACK_RIGHT;
	} else {
		return 0;
	}
}

char* CFaad2Helper::position2string(int position)
{
	switch (position)
	{
	case FRONT_CHANNEL_CENTER: return "Center front";
	case FRONT_CHANNEL_LEFT:   return "Left front";
	case FRONT_CHANNEL_RIGHT:  return "Right front";
	case SIDE_CHANNEL_LEFT:    return "Left side";
	case SIDE_CHANNEL_RIGHT:   return "Right side";
	case BACK_CHANNEL_LEFT:    return "Left back";
	case BACK_CHANNEL_RIGHT:   return "Right back";
	case BACK_CHANNEL_C
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值