.wav再生(DirectSound)

DirectSound で .wav を再生します。

これまでと同様にウインドウハンドルを取得すれば
freeglut と DirectSound を組み合わせて使用できます。

#pragma comment(linker, "/SUBSYSTEM:WINDOWS /ENTRY:mainCRTStartup")
#pragma comment(lib,"winmm.lib")
#pragma comment(lib,"dsound.lib")

#include <GL/freeglut/freeglut.h>
#include <mmsystem.h>
#include <dsound.h>
#include <stdio.h>

#define SAFE_RELEASE(p) {if(p){(p)->Release();(p)=NULL;}}//安全に解放する

#define FileName L"test.wav"

#define WIDTH 320
#define HEIGHT 240

HWND hWnd2=NULL;        //ウィンドウハンドル
HINSTANCE hinstance;       //インスタンスのハンドル

LPDIRECTSOUND8 lpDS = NULL; // DirectSound8
LPDIRECTSOUNDBUFFER lpPrimary = NULL; // プライマリサウンドバッファ
LPDIRECTSOUNDBUFFER lpSecondary = NULL; // セカンダリサウンドバッファ

//ウィンドウを検索してHWNDとHINSTANCEを得る
BOOL CALLBACK enumWindowsProc(HWND hWnd,LPARAM lParam)
{
 HANDLE hModule=(HANDLE)GetWindowLong(hWnd,GWL_HINSTANCE);

 if(GetModuleHandle(NULL)==hModule){
  wchar_t ClassName[256];
  GetClassNameW(hWnd,ClassName,sizeof(ClassName)/sizeof(ClassName[0]));
  if(wcsncmp(ClassName,L"FREEGLUT",wcslen(ClassName))==0){
   hWnd2=hWnd;
   hinstance=(HINSTANCE)GetWindowLong(hWnd,GWL_HINSTANCE);
   return FALSE;
  }
 }
 return TRUE;
}

// DirectSound初期化
bool InitDS( void ){
HRESULT ret;
// DirectSound8を作成
ret = DirectSoundCreate8( NULL,&lpDS,NULL );
if( FAILED(ret) ) {
printf("サウンドオブジェクト作成失敗\n");
return false;
}
// 強調モード
ret = lpDS->SetCooperativeLevel( hWnd2,DSSCL_EXCLUSIVE|DSSCL_PRIORITY );
if( FAILED(ret) ) {
printf("強調レベル設定失敗\n");
return false;
}
return true;
}

// プライマリサウンドバッファの作成
bool CreatePrimaryBuffer( void ){
HRESULT ret;
WAVEFORMATEX wf;
// プライマリサウンドバッファの作成
DSBUFFERDESC dsdesc;
ZeroMemory( &dsdesc,sizeof(DSBUFFERDESC) );
dsdesc.dwSize = sizeof( DSBUFFERDESC );
dsdesc.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsdesc.dwBufferBytes = 0;
dsdesc.lpwfxFormat = NULL;
ret = lpDS->CreateSoundBuffer( &dsdesc,&lpPrimary,NULL );
if( FAILED(ret) ) {
printf("プライマリサウンドバッファ作成失敗\n");
return false;
}
// プライマリバッファのステータスを決定
wf.cbSize = sizeof( WAVEFORMATEX );
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = 2;
wf.nSamplesPerSec = 44100;
wf.wBitsPerSample = 16;
wf.nBlockAlign = wf.nChannels * wf.wBitsPerSample / 8;
wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
ret = lpPrimary->SetFormat( &wf );
if( FAILED(ret) ) {
printf("プライマリバッファのステータス失敗\n");
return false;
}
return true;
}

// サウンドバッファの作成
BOOL CreateSoundBuffer( LPDIRECTSOUNDBUFFER *dsb,LPWSTR file )
{
HRESULT ret;
MMCKINFO mSrcWaveFile;
MMCKINFO mSrcWaveFmt;
MMCKINFO mSrcWaveData;
LPWAVEFORMATEX wf;

// WAVファイルをロード
HMMIO hSrc;
hSrc = mmioOpen( file,NULL,MMIO_ALLOCBUF|MMIO_READ|MMIO_COMPAT );
if( !hSrc ) {
printf( "WAVファイルロードエラー\n");
return FALSE;
}

// 'WAVE'チャンクチェック
ZeroMemory( &mSrcWaveFile,sizeof(mSrcWaveFile) );
ret = mmioDescend( hSrc,&mSrcWaveFile,NULL,MMIO_FINDRIFF );
if( mSrcWaveFile.fccType!=mmioFOURCC('W','A','V','E') ) {
printf( "WAVEチャンクチェックエラー\n");
mmioClose( hSrc,0 );
return FALSE;
}

// 'fmt 'チャンクチェック
ZeroMemory( &mSrcWaveFmt,sizeof(mSrcWaveFmt) );
ret = mmioDescend( hSrc,&mSrcWaveFmt,&mSrcWaveFile,MMIO_FINDCHUNK );
if( mSrcWaveFmt.ckid!=mmioFOURCC('f','m','t',' ') ) {
printf( "fmt チャンクチェックエラー\n");
mmioClose( hSrc,0 );
return FALSE;
}

// ヘッダサイズの計算
int iSrcHeaderSize = mSrcWaveFmt.cksize;
if( iSrcHeaderSize<sizeof(WAVEFORMATEX) )
iSrcHeaderSize=sizeof(WAVEFORMATEX);

// ヘッダメモリ確保
wf = (LPWAVEFORMATEX)malloc( iSrcHeaderSize );
if( !wf ) {
printf( "メモリ確保エラー\n");
mmioClose( hSrc,0 );
return FALSE;
}
ZeroMemory( wf,iSrcHeaderSize );

// WAVEフォーマットのロード
ret = mmioRead( hSrc,(char*)wf,mSrcWaveFmt.cksize );
if( FAILED(ret) ) {
printf( "WAVEフォーマットロードエラー\n");
free( wf );
mmioClose( hSrc,0 );
return FALSE;
}
printf( "チャンネル数       = %d\n",wf->nChannels );
printf( "サンプリングレート = %d\n",wf->nSamplesPerSec );
printf( "ビットレート       = %d\n",wf->wBitsPerSample );


// fmtチャンクに戻る
mmioAscend( hSrc,&mSrcWaveFmt,0 );

// dataチャンクを探す
while(1) {
// 検索
ret = mmioDescend( hSrc,&mSrcWaveData,&mSrcWaveFile,0 );
if( FAILED(ret) ) {
printf( "dataチャンクが見つからない\n");
free( wf );
mmioClose( hSrc,0 );
return FALSE;
}
if( mSrcWaveData.ckid==mmioStringToFOURCC(L"data",0) )
break;
// 次のチャンクへ
ret = mmioAscend( hSrc,&mSrcWaveData,0 );
}
printf( "データサイズ       = %d\n",mSrcWaveData.cksize );


// サウンドバッファの作成
DSBUFFERDESC dsdesc;
ZeroMemory( &dsdesc,sizeof(DSBUFFERDESC) );
dsdesc.dwSize = sizeof( DSBUFFERDESC );
dsdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_STATIC | DSBCAPS_LOCDEFER;
dsdesc.dwBufferBytes = mSrcWaveData.cksize;
dsdesc.lpwfxFormat = wf;
dsdesc.guid3DAlgorithm = DS3DALG_DEFAULT;
ret = lpDS->CreateSoundBuffer( &dsdesc,dsb,NULL );
if( FAILED(ret) ) {
printf( "サウンドバッファの作成エラー\n");
free( wf );
mmioClose( hSrc,0 );
return FALSE;
}

// ロック開始
LPVOID pMem1,pMem2;
DWORD dwSize1,dwSize2;
ret = (*dsb)->Lock( 0,mSrcWaveData.cksize,&pMem1,&dwSize1,&pMem2,&dwSize2,0 );
if( FAILED(ret) ) {
printf( "ロック失敗\n");
free( wf );
mmioClose( hSrc,0 );
return FALSE;
}

// データ書き込み
mmioRead( hSrc,(char*)pMem1,dwSize1 );
mmioRead( hSrc,(char*)pMem2,dwSize2 );

// ロック解除
(*dsb)->Unlock( pMem1,dwSize1,pMem2,dwSize2 );

// ヘッダ用メモリを開放
free( wf );

// WAVを閉じる
mmioClose( hSrc,0 );

return TRUE;
}

void Exit()
{
SAFE_RELEASE(lpSecondary);
SAFE_RELEASE(lpPrimary);
SAFE_RELEASE(lpDS);
}

void display(void)
{
 glClearColor(1.0, 1.0, 1.0, 1.0);
 glClear(GL_COLOR_BUFFER_BIT);
 glutSwapBuffers();
}

void init()
{
EnumWindows(enumWindowsProc,0);
// DirectSound
if(!InitDS())Exit();
// プライマリサウンドバッファ
if(!CreatePrimaryBuffer())Exit();
// サウンドバッファ
if(!CreateSoundBuffer(&lpSecondary,FileName))Exit();
// 起動時の再生
lpSecondary->Play( 0,0,0 );
}

int main(int argc, char *argv[])
{
 glutInitWindowPosition(100, 100);
 glutInitWindowSize(WIDTH, HEIGHT);
 glutInitDisplayMode(GLUT_RGBA);
 glutInit(&argc, argv);
 glutCreateWindow("Hellow DirectSound World !!");
 glutDisplayFunc(display);
 init();
 glutMainLoop();
 Exit();
 return 0;
}
最終更新:2012年12月18日 15:51
添付ファイル