今回は複数サウンドを鳴らします 複数サウンドを鳴らすためには DirectSoundの初期化を行うDirectSoundクラスと 今回使うファイルは次のようになってます。どぞー(-ω-)つ旦 #define _CRT_SECURE_NO_WARNINGS // DirectSoundに必要なヘッダーとライブラリ #define DIRECTSOUND_VERSION 0x800 // DirectSoundのバージョン #pragma comment(lib, "dsound.lib") #pragma comment(lib, "d3dxof.lib") #pragma comment(lib, "dxguid.lib") #include <comdef.h> #include <dsound.h> #include <tchar.h> #include <d3d9.h> #include <d3dx9.h> //////////////////////////////////////// #include <Windows.h> #include <vector> /////////////////////////////////////////// // DirectSoundクラス class DirectSound { public: IDirectSound8* pDirectSound8; // DirectSoundデバイス // コンストラクタ DirectSound(); // デストラクタ ~DirectSound(); bool Create(HWND hWnd); }; // コンストラクタ DirectSound::DirectSound() { pDirectSound8 = NULL; // DirectSoundデバイス } // デストラクタ DirectSound::~DirectSound() { if(pDirectSound8 != NULL) pDirectSound8->Release(); } bool DirectSound::Create(HWND hWnd) { // サウンドデバイス作成 DirectSoundCreate8(NULL, &pDirectSound8, NULL); // 協調レベルのセット(ここで音を鳴らすウィンドウを指定する必要がある) if (FAILED(pDirectSound8->SetCooperativeLevel(hWnd, DSSCL_PRIORITY))) { // 失敗 return false; } return true; } //////////////////////////////////////////// class Wave{ public: WAVEFORMATEX WaveFormat; // Waveフォーマット byte* WaveData; // 音の生データ int DataSize; // データサイズ // コンストラクタ Wave(); // デストラクタ ~Wave(); // Wavファイル読み込み bool Load(TCHAR* FileName); }; // コンストラクタ Wave::Wave() { memset(&WaveFormat,0,sizeof(WAVEFORMATEX)); WaveData = NULL; DataSize = 0; } // デストラクタ Wave::~Wave() { if(WaveData != NULL) delete[] WaveData; } // Wavファイル読み込み bool Wave::Load(TCHAR* FileName) { // バイナリ読み込みモードで開く FILE* fp; if (!(fp = ::_tfopen(FileName, _T("rb") ))) return false; char chunkId[5] = {}; char tmp[5] = {}; unsigned int chunkSize = 0; // RIFFチャンク読み込み fread(chunkId, sizeof(char) * 4, 1, fp); fread(&chunkSize, sizeof(unsigned int), 1, fp); fread(tmp, sizeof(char) * 4, 1, fp); if (strcmp(chunkId, "RIFF") || strcmp(tmp, "WAVE")){ return false; // Waveファイルじゃない } // 子チャンク読み込み bool fmtchunk = false; bool datachunk = false; while (true) { fread(chunkId, sizeof(char) * 4, 1, fp); fread(&chunkSize, sizeof(unsigned int), 1, fp); if (!strcmp(chunkId, "fmt ")) { if (chunkSize >= sizeof(WAVEFORMATEX)) { fread(&WaveFormat, sizeof(WAVEFORMATEX), 1, fp); int diff = chunkSize - sizeof(WAVEFORMATEX); fseek(fp, diff, SEEK_CUR); } else { memset(&WaveFormat, 0, sizeof(WAVEFORMATEX)); fread(&WaveFormat, chunkSize, 1, fp); } fmtchunk = true; } else if (!strcmp(chunkId, "data")) { // データサイズ確保 DataSize = chunkSize; WaveData = new byte[chunkSize]; // データ読み込み if (fread(WaveData, sizeof(byte), chunkSize, fp) != chunkSize) { fclose(fp); return false; // ファイルが壊れている } datachunk = true; } else { fseek(fp, chunkSize, SEEK_CUR); } if (fmtchunk && datachunk) break; // ファイルサイズチェックも行なった方がいいかも } fclose(fp); return true; } //////////////////////////////////////////////// class SoundBuffer { public: IDirectSoundBuffer8* pSecondaryBuffer; // セカンダリバッファ // コンストラクタ SoundBuffer(); // デストラクタ ~SoundBuffer(); bool Create(IDirectSound8* pDirectSound8,WAVEFORMATEX& WaveFormat,byte* WaveData,int DataSize); void Play(bool isLoop); void Stop(); }; // コンストラクタ SoundBuffer::SoundBuffer() { pSecondaryBuffer = NULL; } // デストラクタ SoundBuffer::~SoundBuffer() { Stop(); // セカンダリバッファは破棄する前に再生停止すること if(pSecondaryBuffer != NULL) pSecondaryBuffer->Release(); } bool SoundBuffer::Create(IDirectSound8* pDirectSound8,WAVEFORMATEX& WaveFormat,byte* WaveData,int DataSize) { DSBUFFERDESC desc = {}; // セカンダリバッファ作成用設定 // チャンネル数での分岐、モノラルは1チャンネル、ステレオは2チャンネル if(WaveFormat.nChannels == 1){ desc.dwFlags = DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_STATIC; desc.guid3DAlgorithm = DS3DALG_NO_VIRTUALIZATION; } else{ desc.dwFlags = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_CTRLPAN | DSBCAPS_STATIC; // | DSBCAPS_CTRLFX; エフェクトを追加すると Duplicate できない desc.guid3DAlgorithm = GUID_NULL; } desc.dwSize = sizeof(DSBUFFERDESC); desc.dwBufferBytes = DataSize; // 音データサイズ指定 desc.lpwfxFormat = &WaveFormat; // フォーマット指定 IDirectSoundBuffer* pPrimaryBuffer = NULL; // プライマリバッファ // プライマリバッファ作成 pDirectSound8->CreateSoundBuffer(&desc,&pPrimaryBuffer,NULL); // プライマリバッファからセカンダリバッファ作成 pPrimaryBuffer->QueryInterface(IID_IDirectSoundBuffer8, (void**)&pSecondaryBuffer); pPrimaryBuffer->Release(); // セカンダリバッファが作成できれば、プライマリバッファは破棄してかまわない unsigned char* block1 = NULL; unsigned char* block2 = NULL; unsigned long blockSize1 = 0; unsigned long blockSize2 = 0; // セカンダリバッファをロックしてデータ書き込み pSecondaryBuffer->Lock(0, DataSize, (void**)&block1, &blockSize1, (void**)&block2, &blockSize2, DSBLOCK_ENTIREBUFFER); // セカンダリバッファに音データコピー memcpy(block1, WaveData, DataSize); // セカンダリバッファロック解除 pSecondaryBuffer->Unlock(block1, blockSize1, block2, 0); return true; } void SoundBuffer::Play(bool isLoop) { // サウンド再生 if(pSecondaryBuffer != NULL){ DWORD LoopFlag = (isLoop ? DSBPLAY_LOOPING : 0); pSecondaryBuffer->Play(0,0,LoopFlag); } } void SoundBuffer::Stop() { if(pSecondaryBuffer != NULL) pSecondaryBuffer->Stop(); } //////////////////////////////////////////////// // ウィンドウプロシージャ、ウィンドウに対するメッセージ処理を行う LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ switch(msg){ // ウィンドウが破棄されたとき case WM_DESTROY: PostQuitMessage(0); // WM_QUITメッセージをメッセージキューに送る return 0; } // デフォルトのメッセージ処理を行う return DefWindowProc(hWnd, msg, wParam, lParam); } // WinMain関数(アプリケーションの開始関数) // コンソールアプリケーションと違い、コンソールを開かない int _stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { //////////////////////////// // ウィンドウ作成 //////////////////////////// const TCHAR* WC_BASIC = _T("BASIC_WINDOW"); // シンプルウィンドウクラス設定 WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,WndProc, 0,0,hInstance, (HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED), (HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED), (HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , NULL}; // シンプルウィンドウクラス作成 if(!RegisterClassEx(&wcex)) return false; // ウィンドウ幅、高さはディスプレイに依存する。普通は4:3 const int WINDOW_WIDTH = 640; const int WINDOW_HEIGHT = 480; // ウィンドウの作成 HWND hWnd = CreateWindowEx(0,WC_BASIC, _T("Application"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE,CW_USEDEFAULT, CW_USEDEFAULT,WINDOW_WIDTH,WINDOW_HEIGHT,NULL,NULL,hInstance,NULL); //////////////////////////////// // DirectSoundデバイス作成 //////////////////////////////// DirectSound directsound; directsound.Create(hWnd); /////////////////////////////////////////////// // Waveファイル読込み /////////////////////////////////////////////// Wave wave[2]; wave[0].Load(_T("katana.wav")); wave[1].Load(_T("bomb.wav")); ///////////////////ファイル読込みはここまで ///////////////////////////////// // セカンダリバッファの作成 // (読み込んだ音データをコピー) ///////////////////////////////// SoundBuffer sb[2]; for(int i = 0;i < 2;++i) sb[i].Create(directsound.pDirectSound8,wave[i].WaveFormat,wave[i].WaveData,wave[i].DataSize); /////////////////////////////////////////// // メッセージループ /////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // ループ再生 sb[0].Play(true); // 再生 sb[1].Play(false); ///////////////////////////////////////////////////////////////////////////// MSG msg = {}; while(msg.message != WM_QUIT) { // アプリケーションに送られてくるメッセージをメッセージキューから取得する if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){ DispatchMessage(&msg); // アプリケーションの各ウィンドウプロシージャにメッセージを転送する } // メッセージ処理をしていないとき else{ } } return 0; } 今回の実行結果は複数サウンド再生なので
|