[1.1] 行いたいこと
→XAudio2(Windowsの音声API)を使って、WAVファイルを再生したい。
[1.2] どのように取り組んだか
http://princess-tiara.biz/directx/?chapter=19
上記のページを参考に(というかほぼ一緒です)作成しました。
#pragma comment(lib, "winmm.lib")
#include <windows.h>
#include <xaudio2.h>
#include <vector>
#include <cmath>
#include <iostream>
#include <time.h>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
#include <mmsystem.h>
//-----------------------------------------------------------------
// Global Variables.
//-----------------------------------------------------------------
IXAudio2 *g_pXAudio2 = NULL;
IXAudio2MasteringVoice *g_pMasteringVoice = NULL;
IXAudio2SourceVoice *g_pSourceVoice = NULL;//音声ファイル1つにつき1つ用意する
#define fourccRIFF 'RIFF'
#define fourccDATA 'data'
#define fourccFMT 'fmt '
#define fourccWAVE 'WAVE'
#define fourccXWMA 'XWMA'
#define fourccDPDS 'dpds'
//-----------------------------------------------------------------
// Prototypes.
//-----------------------------------------------------------------
HRESULT FindChunk( HANDLE , DWORD , DWORD* , DWORD* );
HRESULT ReadChunkData( HANDLE , void* , DWORD , DWORD );
//-----------------------------------------------------------------
// Main.
//-----------------------------------------------------------------
int main(int argc, char** argv){
//音声処理
HRESULT hr;
HANDLE hFile;
DWORD dwChunkSize;
DWORD dwChunkPosition;
DWORD filetype;
WAVEFORMATEXTENSIBLE wfx;
XAUDIO2_BUFFER buffer;
BYTE *pDataBuffer;
XAUDIO2_VOICE_STATE xa2state;
//*********初期化***************
CoInitializeEx( NULL , COINIT_MULTITHREADED );
//**********XAudio2作成**************
hr = XAudio2Create( &g_pXAudio2 , 0 ); //XAudioの作成
if ( FAILED( hr ) ){
CoUninitialize();
return -1;
}
//**********マスタリングボイスの作成*************
hr = g_pXAudio2->CreateMasteringVoice( &g_pMasteringVoice );
if ( FAILED( hr ) ){
if ( g_pXAudio2 ) g_pXAudio2->Release();
CoUninitialize();
return -1;
}
//*************読み込み部分***********************
memset( &wfx , 0 , sizeof( WAVEFORMATEXTENSIBLE ) );
memset( &buffer , 0 , sizeof( XAUDIO2_BUFFER ) );
hFile = CreateFile( "flute1.wav", GENERIC_READ , FILE_SHARE_READ , NULL ,
OPEN_EXISTING , 0 , NULL );
if ( hFile == INVALID_HANDLE_VALUE ){
return HRESULT_FROM_WIN32( GetLastError() );
}
if ( SetFilePointer( hFile , 0 , NULL , FILE_BEGIN ) == INVALID_SET_FILE_POINTER ){
return HRESULT_FROM_WIN32( GetLastError() );
}
// Check Wave File.
hr = FindChunk( hFile , fourccRIFF , &dwChunkSize , &dwChunkPosition );
if ( FAILED( hr ) ) return S_FALSE;
hr = ReadChunkData( hFile , &filetype , sizeof( DWORD ) , dwChunkPosition );
if ( FAILED( hr ) ) return S_FALSE; //①ここで読み込みが終わってしまう模様。
if ( filetype != fourccWAVE ) return S_FALSE;
// Get Format.
hr = FindChunk( hFile , fourccFMT , &dwChunkSize , &dwChunkPosition );
if ( FAILED( hr ) ) return S_FALSE;
hr = ReadChunkData( hFile , &wfx , dwChunkSize , dwChunkPosition );
if ( FAILED( hr ) ) return S_FALSE;
// Load Sound.
hr = FindChunk( hFile , fourccDATA , &dwChunkSize , &dwChunkPosition );
if ( FAILED( hr ) ) return S_FALSE;
pDataBuffer = (BYTE*)malloc( dwChunkSize );
hr = ReadChunkData( hFile , pDataBuffer , dwChunkSize , dwChunkPosition );
if ( FAILED( hr ) ) return S_FALSE;
//************音声ファイルの設定*******************
g_pXAudio2->CreateSourceVoice( &g_pSourceVoice , &(wfx.Format) );
buffer.AudioBytes = dwChunkSize;//音声データのサイズ
buffer.pAudioData = pDataBuffer;//音声データが入っているメモリ領域のアドレス
buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.LoopCount = XAUDIO2_LOOP_INFINITE;//繰り返しの再生回数
g_pSourceVoice->SubmitSourceBuffer( &buffer );//ソースボイスの設定
//************音声の再生*******************
g_pSourceVoice->GetState( &xa2state );
if ( xa2state.BuffersQueued != 0 ){
g_pSourceVoice->Stop( 0 );
g_pSourceVoice->FlushSourceBuffers();
g_pSourceVoice->SubmitSourceBuffer( &buffer );
}
g_pSourceVoice->Start( 0 );
Sleep( 5000 );
//***********音声の停止*********************
g_pSourceVoice->Stop( 0 );
g_pSourceVoice->FlushSourceBuffers();
g_pSourceVoice->SubmitSourceBuffer( &buffer );
//**********終了処理*************
g_pSourceVoice->Stop( 0 );
g_pSourceVoice->DestroyVoice();
free( pDataBuffer );
g_pMasteringVoice->DestroyVoice();
if ( g_pXAudio2 ) g_pXAudio2->Release();
CoUninitialize();
return 0;
}
//******************************************************************************
// Find Chunk.
//******************************************************************************
HRESULT FindChunk( HANDLE hFile , DWORD forucc , DWORD *dwChunkSize , DWORD *dwChunkDataPosition )
{
HRESULT hr;
DWORD dwRead;
DWORD dwChunkType;
DWORD dwChunkDataSize;
DWORD dwRIFFDataSize = 0;
DWORD dwFileType;
DWORD bytesRead = 0;
DWORD dwOffset = 0;
hr = S_OK;
if ( SetFilePointer( hFile , 0 , NULL , FILE_BEGIN ) == INVALID_SET_FILE_POINTER )
return HRESULT_FROM_WIN32( GetLastError() );
while( hr == S_OK ){
if ( ReadFile( hFile , &dwChunkType , sizeof( DWORD ) , &dwRead , NULL ) == 0 )
hr = HRESULT_FROM_WIN32( GetLastError() );
if ( ReadFile( hFile , &dwChunkDataSize , sizeof( DWORD ) , &dwRead , NULL )
== 0 )
hr = HRESULT_FROM_WIN32( GetLastError() );
switch( dwChunkType ){
case fourccRIFF:
dwRIFFDataSize = dwChunkDataSize;
dwChunkDataSize = 4;
if ( ReadFile( hFile ,
&dwFileType , sizeof( DWORD ) , &dwRead , NULL ) == 0 )
hr = HRESULT_FROM_WIN32( GetLastError() );
break;
default:
if ( SetFilePointer( hFile ,
dwChunkDataSize , NULL , FILE_CURRENT )
== INVALID_SET_FILE_POINTER )
return HRESULT_FROM_WIN32( GetLastError() );
}
dwOffset += sizeof( DWORD ) * 2;
if ( dwChunkType == forucc ){
*dwChunkSize = dwChunkDataSize;
*dwChunkDataPosition = dwOffset;
return S_OK;
}
dwOffset += dwChunkDataSize;
if ( bytesRead >= dwRIFFDataSize ) return S_FALSE;
}
return S_OK;
}
//******************************************************************************
// Read Chunk Data.
//******************************************************************************
HRESULT ReadChunkData( HANDLE hFile , void *buffer , DWORD buffersize , DWORD bufferoffset )
{
DWORD dwRead;
if ( ReadFile( hFile , buffer , buffersize , &dwRead , NULL ) == 0 )
return HRESULT_FROM_WIN32( GetLastError() );
if ( SetFilePointer( hFile , bufferoffset , NULL , FILE_BEGIN )
== INVALID_SET_FILE_POINTER )
return HRESULT_FROM_WIN32( GetLastError() );
if ( ReadFile( hFile , buffer , buffersize , &dwRead , NULL ) == 0 )
return HRESULT_FROM_WIN32( GetLastError() );
return S_OK;
}
→エラーは出てないのですが、①(100行目)のところで、wavファイルの読み込みが終わってしまうため、再生できない。
[1.4] 今何がわからないのか、知りたいのか
→上記の原因を知りたい。WAVファイルの置き場所は、実行ファイルのあるVCプロジェクトフォルダ内に置いてある。おそらく、WAVファイル(82行目flute1.wav)は読み込めているのだと思っている(読み込めない場合、100行より前の
if ( FAILED( hr ) ) return S_FALSE;
ではじかれるため。)。
[2] 環境
[2.1] OS : Windows, Linux等々
→OS:Windows7
[2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
コンパイラ名→Microsoft Visual C++ 2008
[3] その他
・どの程度C言語を理解しているか
・if、for、while、ポインタなどの基本的なことは理解しているつもり。
・ライブラリを使っている場合は何を使っているか
・Microsoft DirectX SDK (June 2010)
・openCV(上記のプログラムには、まだ利用していないが、インクルードはしている)
以上、ご協力できる方よろしくお願いします。