DirectSound で .wav を再生します。
#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;
}
|