FC2ブログ

ホーム > WAVEファイルフォーマット > WAVEファイルの再生 第2部

WAVEファイルの再生 第2部



前章WAVEファイルの再生 第1部の続きです。




マルチメディアファイル入出力関数を使ってWAVEファイルを開き、CWaveFile::ReadHeader関数を呼び出します。

//WAVEファイルを開く
BOOL CWaveFile::OpenFile(LPCTSTR lpszFileName)
{
Delete();
//マルチメディア関数を使ってファイルを開きます。
HMMIO hmmio=::mmioOpen((LPTSTR)lpszFileName,NULL,MMIO_READ);
if (!hmmio) return FALSE;
//WAVEファイルヘッダーを読み込みます。
if (!ReadHeader(hmmio)){
::mmioClose(hmmio,0);
return FALSE;
}
//ファイルオープンに成功した場合は、
//ファイルのパス名を保存しておきます。

m_strPathName=lpszFileName;
return TRUE;
}


WAVEファイルからWAVEFORMATEX構造体を取得し、演奏のための準備をします。

//WAVEファイルヘッダーを読み込み、WAVEFORMATEX構造体を取得します。
BOOL CWaveFile::ReadHeader(HMMIO hmmio)
{
ASSERT(hmmio);

//WAVEデータ読み込みのための設定
MMCKINFO mmckRiff,mmckFmt,mmckData;
MMRESULT mmr;
LONG size;

//WAVEファイルかのチェック
//RIFFチャンクに進入してWAVEチャンクを探します。

mmckRiff.fccType=::mmioStringToFOURCC(_T("WAVE"), 0);
mmr=::mmioDescend(hmmio,&mmckRiff,NULL,MMIO_FINDRIFF);
//WAVEチャンクがなければFALSEを返して終了する。
if (mmr!=MMSYSERR_NOERROR) return FALSE;

//fmtチャンクに進入します。
mmckFmt.ckid=::mmioStringToFOURCC(_T("fmt "),0);
mmr=::mmioDescend(hmmio,&mmckFmt,NULL,MMIO_FINDCHUNK);
//進入に失敗したらFALSEを返して終了します。
if (mmr!=MMSYSERR_NOERROR) return FALSE;
//fmtチャンクを読み込む。
size=::mmioRead(hmmio,(HPSTR)&m_wfx,mmckFmt.cksize);
if (size!=mmckFmt.cksize) return FALSE;
//fmtチャンクにはないcbSize要素を設定します。
m_wfx.cbSize=sizeof(WAVEFORMATEX);

//fmtチャンクから退出する。
if (::mmioAscend(hmmio,&mmckFmt,0)!=MMSYSERR_NOERROR) return FALSE;

//dataチャンクに進入します。
mmckData.ckid=::mmioStringToFOURCC(_T("data"),0);
mmr=::mmioDescend(hmmio,&mmckData,NULL,MMIO_FINDCHUNK);
//進入に失敗したらFALSEを返して終了します。
if (mmr!=MMSYSERR_NOERROR) return FALSE;

//音源データの先頭位置を保存します。
m_posStart=::mmioSeek(hmmio,0,SEEK_CUR);
//ファイルハンドルをメンバ変数に保存します。
m_hmmioIn=hmmio;
//RIFFチャンクのMMCKINFO構造体
::CopyMemory(&m_ckRiffIn,&mmckRiff,sizeof(MMCKINFO));
//dataチャンクのMMCKINFO構造体
::CopyMemory(&m_ckDataIn,&mmckData,sizeof(MMCKINFO));
//音源データサイズにdataチャンクサイズを代入します。
m_nDataSize=mmckData.cksize;
//ファイル末尾に移動して、実際のファイルサイズを取得します。
LONG posEndFile=::mmioSeek(hmmio,0,SEEK_END);
//音源データの先頭位置に戻ります。
::mmioSeek(hmmio,m_posStart,SEEK_SET);
//実際にファイルに書かれたデータバイト数を算出します。
m_nDataSaved=posEndFile-m_posStart;
//実際のデータバイト数がデータサイズより大きい場合は、
//データサイズに代入します。

if (m_nDataSize<m_nDataSaved) m_nDataSize=m_nDataSaved;
//オーナーウィンドウがあれば、プログレスバーの位置を通知します。
if (m_pWndOwner) m_pWndOwner->PostMessage(PBM_SETPOS,m_nDataSaved,0);

return TRUE;
}


演奏中に基底クラスCWaveOutクラスからバッファへの音源データ読み込み要求があるたびに呼び出される、WAVEストリーム読み込み関数です。

//音源ストリームの入力(CWaveOutクラスのStreamIn関数をオーバーライドします。)
UINT CWaveFile::StreamIn(LPVOID pBuffer,UINT nBufSize)
{
ASSERT(AfxIsValidAddress(pBuffer,nBufSize));

UINT readBytes=0;
//ファイルとWAVE出力デバイスのWAVEFORMATEX構造体要素のうち、
//サンプル当りのバイト数、1秒あたりのサンプル数、サンプル当りのビット数が
//いずれも等しければ、読み込んだ音源をそのまま返して関数を終了します。

if ((CWaveOut::m_wfx.nBlockAlign==m_wfx.nBlockAlign)&&
(CWaveOut::m_wfx.nSamplesPerSec==m_wfx.nSamplesPerSec)&&
(CWaveOut::m_wfx.wBitsPerSample==m_wfx.wBitsPerSample))
{
readBytes=StreamIn(pBuffer,nBufSize,&m_indexSample);
}
else
{
//入力バッファのサイズから、加工前の入力バイト数を算出します。
UINT nSamples=nBufSize/CWaveOut::m_wfx.nBlockAlign;
UINT inputBytes=nSamples*m_wfx.nBlockAlign;

//入力用バッファ(CByteArrayクラス)のサイズが入力バイト数より小さい場合、
//入力用バッファのサイズを入力バイト数に合わせます。

if ((UINT)m_byteInBuf.GetSize()<inputBytes)
m_byteInBuf.SetSize(inputBytes);
//入力用バッファへのポインタを取得します。
PBYTE pInBuf=m_byteInBuf.GetData();
//入力用バッファをゼロクリアします。
::ZeroMemory(pInBuf,inputBytes);
UINT indexSafe=m_indexSample;
UINT sizeBytes=StreamIn(pInBuf,inputBytes,&m_indexSample);
//音源データに擬似ステレオ加工を施します。
readBytes=DoStereo(pBuffer,nBufSize,indexSafe,sizeBytes,&m_wfx);
}
return readBytes;
}

//Waveストリームの読み込み
UINT CWaveFile::StreamIn(LPVOID pBuffer,UINT nBufSize,UINT* pIndexSample)
{
ASSERT(AfxIsValidAddress(pBuffer,nBufSize));
ASSERT(m_hmmioIn);
ASSERT(m_posStart);
ASSERT(AfxIsValidAddress(pIndexSample,sizeof(UINT)));

//指定の演奏位置からファイル読み込み位置を算出して、
//その位置にシークします。

LONG offset=m_posStart+*pIndexSample*m_wfx.nBlockAlign;
LONG pos=::mmioSeek(m_hmmioIn,offset,SEEK_SET);
//シークに失敗したら、FALSEを返して終了します。
if (pos!=offset) return FALSE;

//dataチャンクの音源データを読み込みます。
LONG readBytes=::mmioRead(m_hmmioIn,(HPSTR)pBuffer,nBufSize);
//読み込みに失敗したら、FALSEを返して終了します。
if (readBytes==-1) return FALSE;
//指定の演奏位置を読み込んだ分だけ進めます。
*pIndexSample+=readBytes/m_wfx.nBlockAlign;
//読み込んだバイト数を返して終了します。
return readBytes;
}


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

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

上記のzipファイルをダウンロードしてからWinRAR等で解凍し、WaveFileTest01フォルダー内にある「WaveFileTest.sln」を開きます。
「F5」キーを押すと、ビルド確認のダイヤログが表示されるので「Yes」を選択してソリューションをビルドします。



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



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



resフォルダー内の「Sample1.wav」を選択し、「開く」ボタンを押すと、コンボボックスにファイル名が表示され、スライドバーの動きに合わせて、WAVEファイルが再生されるか確認します。



「PAUSE」ボタンを押して演奏を一時停止させ、メニューから「ツール」/「WAVEフォーマットの変更」を選択し、「WAVEフォーマットの変更」ダイヤログで「サンプル周波数」を変更してから「適用する」ボタンを押し、音が変わるのを確認して下さい。



<<WAVEファイルの再生 第1部ページの先頭WAVE再生時の音量変更>>



スポンサーサイト



コメント: 0

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

Trackback+Pingback: 0

TrackBack URL for this entry
http://hiroshi0945.blog75.fc2.com/tb.php/63-7860ad39
Listed below are links to weblogs that reference
WAVEファイルの再生 第2部 from マルチメディアファイルフォーマット

Home > WAVEファイルフォーマット > WAVEファイルの再生 第2部

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

この人とブロともになる

ブロとも一覧

このページの先頭へ戻る