FC2ブログ

ホーム > AACファイルフォーマット > AACファイルの再生

AACファイルの再生



faad2ライブラリーを使用してAACファイルのデコードを行い、同時に再生するプログラムについて解説します。



AACファイルをデコードするために必要なインクルードファイルとライブラリです。
尚ライブラリーについては前回のfaad2-2.7のインストールで作成したものです。

extern "C"
{
#include "..\\faad2-2.7\include\neaacdec.h"
}
#pragma comment(lib,"SoundLib\\libfaad-vc7.lib")


AACファイルを再生するために必要なインクルードファイルです。

#include "SoundLib\MP3File.h"


上記インクルード定義で必要となるファイルです。

devioctl.h
ntddcdrm.h
ntddstor.h
WaveFile.h WaveFile.cpp
WaveOut.h WaveOut.cpp
CDDAFile.h CDDAFile.cpp
MP3File.h MP3File.cpp


倍精度実数から四捨五入した整数を求めるマクロです。

//四捨五入した整数を求める
#define ROUND(data) ((int)((double)data+(double)0.5))


AACファイル周波数設定時に参照する定数テーブルです。

//周波数テーブル
static const long g_aacFreq[]={
96000,88200,64000,48000,44100,32000,
24000,22050,16000,12000,11025, 8000,
-1, -1, -1, -1
};


ADTSヘッダーを解析して、デコードに必要な各値を格納する構造体とstdcall関数です。

//ADTS_HEADER構造体
typedef struct tagADTS_HEADER{
int iVersion; //4:MPEG4,2:MPEG2
BOOL bProtect; //保護属性 0:なし,1:有り
int iProfile; //音質と圧縮率 0:main,01:LC,2:SSR,3:(予約)
DWORD sampleRate; //周波数
WORD nChannel; //チャンネル数
BOOL bCopy; //0:オリジナル,1:コピー
DWORD nFrameSize; //AACフレーム長(バイト、ヘッダ込み)
DWORD nFullness; //ADTSバッファ残量 0x7FF VBR
}ADTS_HEADER;

//ADTSヘッダーを解析して、デコードに必要な各値をADTS_HEADER構造体に格納します。
BOOL __stdcall _ParseADTSHeader(const PBYTE pHeader,ADTS_HEADER* pADTSHeader)
{
ASSERT(AfxIsValidAddress(pHeader,7,FALSE));
ASSERT(AfxIsValidAddress(pADTSHeader,sizeof(ADTS_HEADER),TRUE));

//先頭バイトは0xFF
if ((pHeader[0]&0xFF)!=0xFF) return FALSE;
//次のバイトの上位3ビットは1
if ((pHeader[1]&0xF0)!=0xF0) return FALSE;

//MPEGバージョン番号を取得します。
//header[1]:b3=0:MPEG4,1:MPEG2

int version=4-((pHeader[1]>>3)&1)*2;

//layer (常に00)
//header[1]:b2b1=00

int layer=(pHeader[1]>>1)&3;
if (layer!=0) return FALSE;

//保護属性を取得します。
//header[1]:b0

BOOL bProtect=pHeader[1]&1;

//音質と圧縮率を取得します。
//header[2]:b7b6

int profile=(pHeader[2]>>6)&3;


//周波数を取得します。
//header[2]:b5b4b3b2

int index=(pHeader[2]>>2)&0x0F;
int sampleRate=g_aacFreq[index];
if (sampleRate==-1) return FALSE;

//private bit
//header[2]:b1

BOOL bPrivateBit=(pHeader[2]>>1)&1;

//チャンネル数を取得します。
//header[2]:b0,header[3]:b7b6

int channel=((pHeader[2]&1)<<2)|((pHeader[3]>>6)&3);
if (channel==0) return FALSE;

//0:オリジナル,1:コピー
//header[3]:b5

BOOL bCopy=(pHeader[3]>>5)&1;

//home
//header[3]:b4

BOOL bHome=(pHeader[3]>>4)&1;

//copyright identification bit
//header[3]:b3

BOOL bCopyrightIDbit=(pHeader[3]>>3)&1;

//copyright identification start
//header[3]:b2

BOOL bCopyrightIDstart=(pHeader[3]>>2)&1;

//フレームサイズ
//header[3]:b1b0
//header[4]:b7~b0
//header[5]:b7b6b5

DWORD frameSize=((((DWORD)pHeader[3])<<11)&0x1800)|
((((DWORD)pHeader[4])<<3)&0x7F8)|
((((DWORD)pHeader[5])>>5)&0x007);

//ADTSバッファ残量
//header[5]:b4~b0
//header[6]:b7~b2

DWORD nFullness=((((DWORD)pHeader[5])<<6)&0x7c0)|
((((DWORD)pHeader[6])>>2)&0x03F);

//no raw data blocks in frame
//header[6]:b1b2

int remainBlocks=pHeader[6]&3;

//データをADTS_HEADER構造体に格納します。
pADTSHeader->iVersion=version;
pADTSHeader->bProtect=bProtect;
pADTSHeader->iProfile=profile;
pADTSHeader->sampleRate=sampleRate;
pADTSHeader->nChannel=channel;
pADTSHeader->bCopy=bCopy;
pADTSHeader->nFrameSize=frameSize;
pADTSHeader->nFullness=nFullness;
return TRUE;
}


AACファイルの再生をWAVEファイルと同様の操作にするために、CWaveFileクラスの派生クラスであるCMP3Fileクラスを基底クラスとする、CAACFileクラスを独自に定義しました。

//このヘッダーでneaacdec.hのインクルードは避けたいので、構造体の型のみ宣言しておきます。
typedef struct faacEncConfiguration faacEncConfiguration;
typedef faacEncConfiguration *faacEncConfigurationPtr;
typedef void *NeAACDecHandle;

class CAACFile : public CMP3File
{
public:
//コンストラクタ
CAACFile(CWnd* pWndOwner=NULL);
//デストラクタ
virtual ~CAACFile();

//メンバー変数の初期化
void Init();
//メンバー変数の削除
void Delete();

enum streamFormat {
RAW_STREAM=0,
ADTS_STREAM=1,
};

//AACファイルがオープンされているかどうか?
virtual BOOL IsAACFile(){return (m_hDecoder!=0);};
//読み込み中のデバイスハンドルの有効/無効を基底クラスに返します。
virtual BOOL IsOpen(){return (m_hDecoder)? TRUE:CMP3File::IsOpen();};

//AACファイルを開く
// lpszFileName:ファイルのパス名
virtual BOOL OpenFile(LPCTSTR lpszFileName);
//音楽ファイルからWave音源に変換してストリーム読み込み
virtual UINT StreamIn(LPVOID pBuffer,UINT nBufSize,UINT* pIndexSample);

//AACファイルの書き込み
virtual BOOL SaveFile(LPCTSTR lpszFileName);
//AACファイル(ID3tag)の書き込み
BOOL SaveAACFile(LPCTSTR lpszFileName);
//AACストリームの書き込み
BOOL StreamOut(CFile* outfile,faacEncConfigurationPtr pConfig=NULL);

//faacEncConfiguration構造体の初期化
void InitEncConfiguration();
//faacEncConfiguration構造体の取得
virtual BOOL GetEncConfiguration(faacEncConfigurationPtr pConfigAAC,faacEncConfigurationPtr pConfigMP4=NULL);
//faacEncConfiguration構造体の設定
virtual BOOL SetEncConfiguration(faacEncConfigurationPtr pConfigAAC,faacEncConfigurationPtr pConfigMP4=NULL);

//faacバージョンの取得
const char* GetFaacVersion(){return m_pszFaacId;};
//faacエンコーダー名の取得
const char* GetFaacCopyright(){return m_pszFaacCopyright;};

protected:
//ヘッダーの読み込み
BOOL ReadHeader(CFile* infile);

//デコーダー
NeAACDecHandle m_hDecoder;
DWORD m_bytesConsumed;
int m_bytesInBuffer;
int m_indexBuffer;
int m_headerType; //0:RAW,1:ADIF,2:ADTS

//エンコーダー
char* m_pszFaacId; //バージョン
char* m_pszFaacCopyright; //著作権
faacEncConfiguration* m_pConfig;//エンコーダー構成

//基底クラスに書き込み用のバッファサイズを戻します。
virtual UINT GetSizeOfSaveBuffer();
};


CAACFileクラスのコンストラクタ/デストラクタです。

//コンストラクタ
CAACFile::CAACFile(CWnd* pWndOwner)
:CMP3File(pWndOwner)
{
Init();
//faacEncConfiguration構造体の初期化
InitEncConfiguration();
}

//デストラクタ
CAACFile::~CAACFile()
{
delete m_pConfig;
Delete();
}



CAACFileクラスのメンバ関数です。

//メンバー変数の初期化
void CAACFile::Init()
{
//デコーダー
m_hDecoder=0;
m_bytesConsumed=0;
m_bytesInBuffer=0;
m_indexBuffer=0;
m_headerType=RAW;
}

//メンバー変数の削除
void CAACFile::Delete()
{
CMP3File::Delete();
if (m_hDecoder) ::NeAACDecClose(m_hDecoder);
Init();
}


MP3ファイルをオープンして、CAACFile::ReadHeader関数を呼び出します。

//AACファイルをオープンします。
// lpszFileName:オープンするファイル名。

BOOL CAACFile::OpenFile(LPCTSTR lpszFileName)
{
Delete();
if (!lpszFileName) return FALSE;

//拡張子名の取得
LPTSTR pExt=::PathFindExtension(lpszFileName);
//拡張子名が「.aac」で無い場合は、
//CMP3File::OpenFile関数を呼び出します。

if (StrCmpNI(pExt,_T(".aac"),4)!=0)
return CMP3File::OpenFile(lpszFileName);

//ファイルのオープンに失敗した場合は、FALSEを戻して終了します。
CFile* infile=new CFile;
if (!infile->Open(lpszFileName,CFile::modeRead|CFile::shareDenyNone)){
delete infile;
return FALSE;
}

//ヘッダー読み込みに失敗した場合は、CMP3File::OpenFile関数を呼び出します。
if (!ReadHeader(infile)){
infile->Close();
delete infile;
return CMP3File::OpenFile(lpszFileName);
}
m_infile=infile;
m_strPathName=lpszFileName;
return TRUE;
}


AACファイルのヘッダ情報を読み取り、その情報を元にデコーダを開き、AACファイル再生のため準備をします。

//AACヘッダーの読み込み
BOOL CAACFile::ReadHeader(CFile* infile)
{
ASSERT(AfxIsValidAddress(infile,sizeof(CFile),0));

//読み飛ばし位置は、現在のファイル位置とします。
m_dwSkipOffset=(DWORD)infile->GetPosition();
//ファイルサイズを取得します。
DWORD fileSize=(DWORD)(DWORD_PTR)infile->GetLength();

//ADTSヘッダーを探します。
BYTE header[128];
ADTS_HEADER ADTSHeader={0};
int bitrate =0; //ビットレート

while(TRUE){
//読み飛ばし位置に移動してから8バイト読みます。
infile->Seek(m_dwSkipOffset,CFile::begin);
if (infile->Read(header,10)!=10) return FALSE;

//ADTSヘッダーがある場合。
if (_ParseADTSHeader((PBYTE)&header,&ADTSHeader)){
m_headerType=ADTS;
break;
}
//ADIFヘッダーがある場合。
else if (::memcmp(header,"ADIF",4)==0){
int skipSize=(header[4]&0x80)?9:0;
bitrate=((DWORD)(header[4+skipSize]&0x0F)<<19)|
((DWORD) header[5+skipSize]<<11)|
((DWORD) header[6+skipSize]<<3 )|
((DWORD) header[7+skipSize]&0xE0);
float length=(float)fileSize;
if (length) length=((float)length*8.f)/((float)bitrate)+0.5f;
bitrate=(int)((float)bitrate/1000.0f + 0.5f);
m_headerType=ADIF;
break;
}
//"ID3"タグがある場合。
else if (::memcmp(header,"ID3",3)==0){
//ID3V2タグサイズを算出します。
DWORD sizeTag=((header[6]&0x7F)<<21)|((header[7]&0x7F)<<14)|
((header[8]&0x7F)<< 7)|(header[9]&0x7F);
//読み飛ばし位置を算出します。
m_dwSkipOffset+=(sizeTag+10);
//バッファに生データを保存します。
BYTE* pBuffer=NULL;
switch(header[3]){
case 2: //バージョンID3v2.2
if (!m_byteID3v22.GetSize()){
m_byteID3v22.SetSize(sizeTag+10);
pBuffer=m_byteID3v22.GetData();
m_bID3v22=TRUE;
}
break;
case 3: //バージョンID3v2.3
if (!m_byteID3v23.GetSize()){
m_byteID3v23.SetSize(sizeTag+10);
pBuffer=m_byteID3v23.GetData();
m_bID3v23=TRUE;
}
break;
case 4: //バージョンID3v2.4
if (!m_byteID3v24.GetSize()){
m_byteID3v24.SetSize(sizeTag+10);
pBuffer=m_byteID3v24.GetData();
m_bID3v24=TRUE;
}
break;
default:
pBuffer=NULL;
}
if (pBuffer){
::CopyMemory(pBuffer,&header,10);
UINT size=infile->Read(pBuffer+10,sizeTag);
if (size<sizeTag) return FALSE;
}
}
//生データの場合
else if (::memcmp(header,"\xDE\x36\0\0",4)==0){
m_headerType=RAW;
break;
}
else
//フレームヘッダーではない場合は、
//読み飛ばし位置を1バイト進めてから再び読み直します。

m_dwSkipOffset++;
}

BYTE channels=2;
int sampleRate=44100;
if (m_headerType==ADTS){
//フレームヘッダーから得られた値をメンバー変数に保存します。
m_iVersion =ADTSHeader.iVersion; //MPEGバージョン番号
m_iLayer =0; //MPEGレイヤー
m_iBitRate =bitrate; //ビットレート
channels=(BYTE)ADTSHeader.nChannel;
if ((channels!=1)&&(channels!=2)) return FALSE;

sampleRate=ADTSHeader.sampleRate;
m_uFlagBitRate=(ADTSHeader.nFullness==0x7FF)?VBR:CBR;
//フレーム数
int nFrames=1;
//データ総数
m_dwStreamSize=ADTSHeader.nFrameSize;
//ファイルポインタ
DWORD offset=m_dwSkipOffset+ADTSHeader.nFrameSize;
//すべてのフレームについて調べます。
while(TRUE){
//次のフレームの先頭位置を探します。
BOOL bFind=FALSE;
while(TRUE){
//読み飛ばし位置に移動してから4バイト読みます。
infile->Seek(offset,CFile::begin);
if (infile->Read(header,8)!=8) break;
//フレームヘッダーかどうか調べます。
if (_ParseADTSHeader((PBYTE)&header,&ADTSHeader)){
bFind=TRUE;
break;
}
//見つからない場合は、ファイルポインタを1つ進めます。
offset++;
}
if (!bFind) break;
if (!ADTSHeader.nFrameSize) break;

offset+=ADTSHeader.nFrameSize;
m_dwStreamSize+=ADTSHeader.nFrameSize;
nFrames++;
}
m_nFrames=nFrames;
}
else{
//Mp3データ総サイズは、ファイル長さから読み飛ばし位置と、
//フッターサイズを差し引きます。

m_dwStreamSize=fileSize-m_dwSkipOffset-m_dwSkipBottom;
}

//ID3v1タグがあるか調べます。
//ファイル末尾から128バイト戻った位置にシークします。

infile->Seek(fileSize-128,CFile::begin);

UINT size=infile->Read(header,128);
if (size<128) return FALSE;

//"TAG"がある場合。
if (::memcmp(header,"TAG",3)==0){
//フッタサイズを保存します。
m_dwSkipBottom=128;
//バージョン番号を保存します。
m_id3v1Version=0x100|((header[125]=='\0')?1:0);
//バッファに生データを保存します。
m_byteId3v1.SetSize(128);
::CopyMemory(m_byteId3v1.GetData(),&header,128);
}

float totalTime=0;
if (m_headerType==ADTS){
float framesPerSec=(float)sampleRate/1024.0f;
float bytesPerFrame=(m_nFrames)? (float)m_dwStreamSize/(float)(m_nFrames*1000):0;
//平均ビットレート
m_iAveBitRate=(int)(8.0*bytesPerFrame*framesPerSec+0.5);
totalTime=(framesPerSec)? (float)m_nFrames/framesPerSec:1;
}
//現在のファイル位置を、読み飛ばし位置に移動します。
infile->Seek(m_dwSkipOffset,CFile::begin);

//デコーダーを開きます。
NeAACDecHandle hDecoder=::NeAACDecOpen();
if (!hDecoder) return FALSE;

//現在のデコーダー構成構造体を設定します。
NeAACDecConfigurationPtr config=::NeAACDecGetCurrentConfiguration(hDecoder);
config->defObjectType=MAIN;
config->outputFormat =1;
::NeAACDecSetConfiguration(hDecoder, config);

//デコードバッファを確保します。
DWORD cbSrcSize=FAAD_MIN_STREAMSIZE*channels;
m_byteSrcBuf.SetSize(cbSrcSize);
BYTE *buffer=m_byteSrcBuf.GetData();
::ZeroMemory(buffer,cbSrcSize);
UINT bytesInBuffer=infile->Read(buffer,cbSrcSize);

//デコーダーを初期化します。
DWORD samplerate;
int bytesconsumed=::NeAACDecInit(hDecoder,buffer,bytesInBuffer,&samplerate, &channels);
//ライブラリーのオープンに失敗した場合は終了します。
if (bytesconsumed<0){
::NeAACDecClose(hDecoder);
return FALSE;
}
int indexBuffer=0;
indexBuffer+=bytesconsumed;

//Wave再生の為のWAVEFOTMATEX構造体を作成します。
m_wfx.cbSize=sizeof(WAVEFORMATEX);
m_wfx.wFormatTag=WAVE_FORMAT_PCM;
m_wfx.nSamplesPerSec=samplerate;
m_wfx.nChannels=channels;
m_wfx.wBitsPerSample=16;
m_wfx.nBlockAlign=channels*2;
m_wfx.nAvgBytesPerSec=m_wfx.nBlockAlign*m_wfx.nSamplesPerSec;

m_bytesConsumed=bytesconsumed;
m_indexBuffer=indexBuffer;

m_bytesInBuffer=bytesInBuffer;
m_uFlagBitRate=VBR;

m_wavBlockSize=2048*m_wfx.wBitsPerSample/8;
m_hDecoder=hDecoder;

if (m_headerType==ADTS){
//AACの総演奏時間から変換後のWave総データサイズを取得します。
m_nDataSize=(int)(totalTime*(float)m_wfx.nAvgBytesPerSec+0.5);
//Waveブロックサイズの平均値を算出します。
m_nAveWaveBlockSize=m_nDataSize/m_nFrames;
m_dwFrameSize=m_dwStreamSize/m_nFrames;
}
else{
m_nDataSize=m_dwStreamSize*16;
m_dwFrameSize=cbSrcSize;
}
//音源データサイズと実際のデータバイト数を設定します。
m_nDataSaved=m_nDataSize;
//オーナーウィンドウがあれば、プログレスバーの位置を通知します。
if (m_pWndOwner) m_pWndOwner->PostMessage(PBM_SETPOS,m_nDataSaved,0);
return TRUE;
}



AACファイル再生時に音源データ読み込みのために、基底クラスから呼び出されるオーバーライド関数です。

//AACファイルからWave音源に変換してストリーム読み込み
UINT CAACFile::StreamIn(LPVOID pBuffer,UINT nBufSize,UINT* pIndexSample)
{
ASSERT(AfxIsValidAddress(pBuffer,nBufSize));
ASSERT(AfxIsValidAddress(pIndexSample,sizeof(UINT)));

//ACMストリームハンドルが無効な場合は、
//CMP3File::StreamIn関数を呼び出します。

if (!IsAACFile()) return CMP3File::StreamIn(pBuffer,nBufSize,pIndexSample);

//現在位置と指定位置を算出します。
DWORD dwPosRecent=(DWORD)m_infile->GetPosition();
UINT indexBlock=ROUND((double)(*pIndexSample*m_wfx.nBlockAlign)/(double)m_nAveWaveBlockSize);
DWORD dwPosRead=m_dwSkipOffset+(m_dwFrameSize*indexBlock);
//現在演奏中で現在位置と指定位置が100㍉秒以上違えば、指定位置にシークします。
if ((IsActivate())&&(m_headerType==ADTS)&&
((DWORD)abs((int)(dwPosRead-dwPosRecent))>(m_wfx.nAvgBytesPerSec/10))){
//前回の残りの音源データ数を0にします。
m_byteRemain.SetSize(0);

m_bytesConsumed=(DWORD)(DWORD_PTR)m_byteSrcBuf.GetSize();
m_indexBuffer=0;
m_bytesInBuffer=0;
::ZeroMemory(m_byteSrcBuf.GetData(),m_bytesConsumed);

//ADTSヘッダーを探します。
BYTE header[8];
ADTS_HEADER ADTSHeader={0};
while(TRUE){
//読み飛ばし位置に移動してから8バイト読みます。
m_infile->Seek(dwPosRead,CFile::begin);
if (m_infile->Read(header,8)!=8) return FALSE;
//ADTSヘッダーかどうか調べます。
if (_ParseADTSHeader((PBYTE)&header,&ADTSHeader)) break;
//ADTSヘッダーではない場合は、
//読み飛ばし位置を1バイト進めてから再び読み直します。

dwPosRead++;
}
//探し出したADTSヘッダーの先頭位置に移動します。
m_infile->Seek(dwPosRead,CFile::begin);
}

UINT readBytes=0;
PBYTE dst=(PBYTE)pBuffer;

//前回の残りの音源データをバッファに取り込みます。
UINT nRemain=(UINT)(UINT_PTR)m_byteRemain.GetSize();
UINT writeBytes=min(nBufSize,nRemain);
if (nRemain){
PBYTE pRemain=m_byteRemain.GetData();
::CopyMemory(dst,pRemain,writeBytes);
dst+=writeBytes;
readBytes+=writeBytes;
if (writeBytes<nRemain)
::CopyMemory(pRemain,pRemain+writeBytes,nRemain-writeBytes);
nRemain-=writeBytes;
m_byteRemain.SetSize(nRemain);
}
BOOL bDrain=FALSE;
//前回の残りがなく、まだバッファに空きがある場合。
if ((!m_nRemain)&&(readBytes<nBufSize))
{
PBYTE pbSrc=m_byteSrcBuf.GetData();
PBYTE src;
DWORD cbSrcSize=(DWORD)(DWORD_PTR)m_byteSrcBuf.GetSize();
//ファイルからAACデータを読み込み、デコードします。
UINT size=0;
while(readBytes<nBufSize){
//デコードバッファにAACデータを書き込みます。
if (m_bytesConsumed>0){
DWORD nRemain=cbSrcSize-m_bytesConsumed;
CopyMemory(pbSrc,pbSrc+m_bytesConsumed,nRemain);
size=m_infile->Read(pbSrc+nRemain,m_bytesConsumed);
if (size!=m_bytesConsumed) bDrain=TRUE;
if ((!size)&&(!m_bytesInBuffer)) break;
m_bytesInBuffer+=size;
m_bytesConsumed=0;
}

//デコードします。
NeAACDecFrameInfo frameInfo={0};
src=(PBYTE)::NeAACDecDecode(m_hDecoder,&frameInfo,pbSrc,m_bytesInBuffer);

m_bytesConsumed +=frameInfo.bytesconsumed;
m_indexBuffer +=frameInfo.bytesconsumed;
m_bytesInBuffer -=frameInfo.bytesconsumed;

//デコードエラー時の処理
if (frameInfo.error){
m_bytesConsumed=(DWORD)(DWORD_PTR)m_byteSrcBuf.GetSize();
m_indexBuffer=0;
m_bytesInBuffer=0;
}
//デコード済みデータがある場合
if (frameInfo.samples>0){
DWORD sampleBytes=frameInfo.samples*m_wfx.wBitsPerSample/8;
writeBytes=min(sampleBytes,nBufSize-readBytes);
::CopyMemory(dst,src,writeBytes);
dst+=writeBytes;
readBytes+=sampleBytes;
}
}
//バッファに書ききれなかった端数の音源データがある場合。
if ((nRemain==0)&&(readBytes>nBufSize)){
//端数の音源データを残りバッファに格納します。
nRemain=readBytes-nBufSize;
m_byteRemain.SetSize(nRemain);
PBYTE pRemain=m_byteRemain.GetData();
::CopyMemory(pRemain,src+writeBytes,nRemain);
readBytes-=nRemain;
}

//指定の演奏位置を、読み込んだMp3データに相当する音源データ分進めます。
dwPosRecent=(DWORD)m_infile->GetPosition();
if (m_headerType==ADTS){
//ADTSヘッダーがある場合。
indexBlock=(dwPosRecent-m_dwSkipOffset)/m_dwFrameSize;
*pIndexSample=(m_nAveWaveBlockSize*indexBlock)/m_wfx.nBlockAlign;
}
else{
//生データの場合。
*pIndexSample=(UINT)((float)m_nDataSize*(float)(dwPosRecent-m_dwSkipOffset)/
(float)m_dwStreamSize)/m_wfx.nBlockAlign;
}
}
return readBytes;
}


CAACFileクラスのインスタンスを作成した後、CAACFile::OpenFile関数AACファイルを開きます。
エラーがなければCWaveFile::Play関数で演奏を開始します。演奏を中断したり演奏終了後、WAVE出力デバイスを閉じる場合は、CWaveFile::Stop関数を呼び出して下さい。
入力したAACファイルが再生されれば成功です。

サンプルプログラム(VisualC++net2003ソリューション)AACFileTest01.zip

上記のzipファイルをダウンロードして、faad2-2.7のインストールで作成した「faad2-2.7」フォルダーと「libfaad-vc7」フォルダーがある同じフォルダー内にWinRAR等を使って解凍すると、「AACFileTest01」という名のフォルダーが作成されます。



「AACFileTest01」フォルダー内にある「AACFileTest.sln」を開いて「F5」キーを押すと、ビルド確認のダイヤログが表示されるので「Yes」を選択してソリューションをビルドします。



ビルドが終わると直ちにプログラムが自動起動して下の図にあるダイヤログが表示されます。



ダイヤログにある「ADDFile」ボタンを押すと、「ファイルを開く」ダイヤログが表示されます。



AACファイルを選択し「開く」ボタンを押すと、コンボボックスにファイル名が表示され、スライドバーの動きに合わせて、AACファイルが再生されるか確認します。同時に「MP3のプロパティ」ダイヤログが現れ、フレーム数/サイズ、平均ビットレート等の数値が表示されるか確認してください。





スポンサーサイト



コメント: 0

この記事へのコメント
ブログ著者にのみ知らせます。

Trackback+Pingback: 0

TrackBack URL for this entry
http://hiroshi0945.blog75.fc2.com/tb.php/74-7a34c945
Listed below are links to weblogs that reference
AACファイルの再生 from マルチメディアファイルフォーマット

Home > AACファイルフォーマット > AACファイルの再生

タグクラウド
ブロとも申請フォーム

この人とブロともになる

ブロとも一覧

このページの先頭へ戻る