2013年03月29日

AC3ファイルの書き込み

AC3ACMのインストールで紹介したAC3ACMドライバーを使用して、WAVE音源データをエンコードして、AC3ファイルを作成する方法を解説します。

CWaveFile::SaveFile関数から呼び出されるCWaveFile::WriteFile関数にオーバーライドして、現在演奏中のファイルをAC3ファイルに保存します。

//AC3ファイルの書き込み(重ね書き不可&オーバーライド)
BOOL CAC3File::WriteFile(LPCTSTR lpszFileName)
{
ASSERT(IsOpen());
ASSERT(m_strPathName!=lpszFileName);

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

if (::StrCmpNI(pExt,_T(".ac3"),4)!=0)
return CAACFile::WriteFile(lpszFileName);

//ファイルを開きます。
CFile outfile;
if (!outfile.Open(lpszFileName,CFile::modeCreate|CFile::modeReadWrite)) return FALSE;

//AC3ファイルの場合は、AC3データの内容をそのまま書き写します。
if (IsAC3File()){
//AC3データを書き込む為のバッファを作成します。
CByteArray array;
UINT sizeBuf=GetSizeOfSaveBuffer();
array.SetSize(sizeBuf);
BYTE* buffer=array.GetData();

//AC3データを書き込みます。
UINT readSize=0;
m_infile->Seek(m_dwSkipOffset,CFile::begin);
while(readSize<m_dwStreamSize){
UINT sizeToRead=min(sizeBuf,m_dwStreamSize-readSize);
UINT readBytes=m_infile->Read(buffer,sizeToRead);
if (!readBytes) break;
outfile.Write(buffer,readBytes);
readSize+=readBytes;
}
}
//それ以外の場合は、エンコードし直します。
else if (!AC3StreamOut(&outfile)){
outfile.Close();
::DeleteFile(lpszFileName);
return FALSE;
}

outfile.Close();

return TRUE;
}


引数で指定したDOLBYAC3WAVEFORMAT構造体に従って、WAVE音源データAC3エンコードする関数です。

//AC3ストリームの書き込み
BOOL CAC3File::AC3StreamOut(CFile* outfile,DOLBYAC3WAVEFORMAT* pac3wf)
{
MMRESULT mmr=0;

//MPEGLAYER3WAVEFORMAT構造体の取得
if ((!::IsBadReadPtr(pac3wf,sizeof(DOLBYAC3WAVEFORMAT)))&&
((pac3wf->wfx.wFormatTag==WAVE_FORMAT_DVD_DTS)||
(pac3wf->wfx.wFormatTag==WAVE_FORMAT_DOLBY_AC3)))
{
WAVEFORMATEX wfx;
GetWaveFormat(&wfx);
mmr=::acmFormatSuggest(NULL,(LPWAVEFORMATEX)pac3wf,&wfx,sizeof(WAVEFORMATEX),
ACM_FORMATSUGGESTF_WFORMATTAG|ACM_FORMATSUGGESTF_NCHANNELS|
ACM_FORMATSUGGESTF_NSAMPLESPERSEC|ACM_FORMATSUGGESTF_WBITSPERSAMPLE);
if (mmr==MMSYSERR_NOERROR) SetEncodeFormat((LPWAVEFORMATEX)pac3wf);
}

if ((::IsBadReadPtr(m_pwfxEnc,sizeof(DOLBYAC3WAVEFORMAT)))||
((m_pwfxEnc->wFormatTag!=WAVE_FORMAT_DVD_DTS)&&
(m_pwfxEnc->wFormatTag!=WAVE_FORMAT_DOLBY_AC3)))
{

DOLBYAC3WAVEFORMAT ac3wf={0};
ac3wf.wfx.wFormatTag =WAVE_FORMAT_DOLBY_AC3;
ac3wf.wfx.cbSize =sizeof(DOLBYAC3WAVEFORMAT)-sizeof(WAVEFORMATEX);

mmr=::acmFormatSuggest(NULL,&m_wfx,&ac3wf.wfx,sizeof(DOLBYAC3WAVEFORMAT),ACM_FORMATSUGGESTF_WFORMATTAG);
if (mmr!=MMSYSERR_NOERROR) return FALSE;

SetEncodeFormat((LPWAVEFORMATEX)&ac3wf);
}

HACMSTREAM hStream;
mmr=::acmStreamOpen(&hStream,NULL,&m_wfx,m_pwfxEnc,NULL,NULL,0,ACM_STREAMOPENF_NONREALTIME);
if (mmr!=MMSYSERR_NOERROR) return FALSE;

DWORD dwSrcSize=GetSizeOfSaveBuffer();
//音源データを格納するバッファを作成します。
CByteArray byteSrcWave;
byteSrcWave.SetSize(dwSrcSize);
//バッファへのポインタを取得します。
PBYTE pSrcWave=byteSrcWave.GetData();

DWORD dwDstSize=0;
//出力バッファのサイズを取得します。
mmr=::acmStreamSize(hStream,dwSrcSize,&dwDstSize,ACM_STREAMSIZEF_SOURCE);
if (mmr!=MMSYSERR_NOERROR) return FALSE;

//エンコードデータを格納するバッファを作成します。
CByteArray byteDstMp3;
byteDstMp3.SetSize(dwDstSize);
//バッファへのポインタを取得します。
PBYTE pDstMp3=byteDstMp3.GetData();

//ストリームヘッダーの作成
ACMSTREAMHEADER AcmStreamHeader={0};
AcmStreamHeader.cbStruct =sizeof(ACMSTREAMHEADER);
AcmStreamHeader.fdwStatus =0;
AcmStreamHeader.pbSrc =pSrcWave;
AcmStreamHeader.cbSrcLength =dwSrcSize;
AcmStreamHeader.cbSrcLengthUsed =dwSrcSize;
AcmStreamHeader.pbDst =pDstMp3;
AcmStreamHeader.cbDstLength =(DWORD)dwDstSize;
AcmStreamHeader.cbDstLengthUsed =0;
mmr=::acmStreamPrepareHeader(hStream,&AcmStreamHeader,0);
if (mmr!=MMSYSERR_NOERROR) return FALSE;

//読み込み用のインデックスをゼロにします。
UINT indexSample=0;

UINT nTail=GetSamples()-1;
SaveCallBack(0,_T("AC3データストリームを書き込んでいます。"));
while(SaveCallBack(indexSample*100/nTail)){
//バッファを初期化します。
::ZeroMemory(AcmStreamHeader.pbSrc,AcmStreamHeader.cbSrcLength);
::ZeroMemory(AcmStreamHeader.pbDst,AcmStreamHeader.cbDstLength);
//現在の演奏条件での音源データを取得します。
UINT readBytes=StreamIn(AcmStreamHeader.pbSrc,AcmStreamHeader.cbSrcLength,&indexSample);
AcmStreamHeader.cbSrcLengthUsed=readBytes;
//最後まで読み込んだら、ループを抜けます。
if (!readBytes) break;
//Wave音源データからMp3データに変換します。
mmr=::acmStreamConvert(hStream,&AcmStreamHeader,0);
if (mmr!=MMSYSERR_NOERROR) return FALSE;
//ファイルに音源データを書き込みます。
outfile->Write(AcmStreamHeader.pbDst,AcmStreamHeader.cbDstLengthUsed);
}
//ACMストリームヘッダーを削除します。
::acmStreamUnprepareHeader(hStream,&AcmStreamHeader,0);
//ACMストリームをクローズします。
::acmStreamClose(hStream,0);

return TRUE;
}



WaveOut.h
WaveOut.cpp
WaveFile.h
WaveFile.cpp
CDDAFile.h
CDDAFile.cpp
MP3File.h
MP3File.cpp
AACFile.h
AACFile.cpp
MP4File.h
MP4File.cpp
AC3File.h
AC3File.cpp




posted by ひろし at 23:23| Comment(0) | AC3ファイルフォーマット | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。