Skip to content

Instantly share code, notes, and snippets.

@gekka
Last active October 9, 2022 00:02
Show Gist options
  • Save gekka/5570ad4e6a1ce591906a7f4d3cfcf3c0 to your computer and use it in GitHub Desktop.
Save gekka/5570ad4e6a1ce591906a7f4d3cfcf3c0 to your computer and use it in GitHub Desktop.
#include "pch.h"
#include "test.h"
#include <objbase.h>
#include <initguid.h>
#include <mmsystem.h>
#include <dsound.h>
#pragma comment(lib, "dsound.lib")
static BOOL ReadWav(void** ppmem, DWORD* psize, WAVEFORMATEX* pformat);
void Test(HWND hwnd)
{
void* pwav = NULL; //WAVのデータ格納
DWORD wavsize;//WAVデータの大きさ
WAVEFORMATEX format;//WAVのフォーマット
if (!ReadWav(&pwav, &wavsize, &format))//再生させたいWAVデータを取得
{
return;
}
LPDIRECTSOUNDBUFFER buffer = NULL;
LPDIRECTSOUNDNOTIFY notify = NULL;
LPDIRECTSOUND8 pds = NULL;
DirectSoundCreate8(NULL, &pds, NULL);
if (pds == NULL)
{
goto FINALLY;
}
if (pds->SetCooperativeLevel(hwnd, DSSCL_NORMAL) != DS_OK)
{
goto FINALLY;
}
DSBUFFERDESC desc;//バッファ定義
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY; //通知を有効にする
desc.dwBufferBytes = wavsize;
desc.lpwfxFormat = &format;
desc.guid3DAlgorithm = GUID_NULL;
//再生バッファ
if (pds->CreateSoundBuffer(&desc, &buffer, NULL) != DS_OK)
{
goto FINALLY;
}
//バッファにWAVを書き込み
void* pbuff[2];
DWORD sz[2];
buffer->SetCurrentPosition(0);
buffer->Lock(0, wavsize, &pbuff[0], &sz[0], &pbuff[1], &sz[1], DSBLOCK_ENTIREBUFFER);
memcpy(pbuff[0], pwav, wavsize);
buffer->Unlock(pbuff[0], sz[0], pbuff[1], sz[1]);
//通知登録用のインターフェースを取得
if (buffer->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*)&notify) != S_OK)
{
goto FINALLY;
}
DSBPOSITIONNOTIFY pos;//通知定義
memset(&pos, 0, sizeof(pos));
pos.dwOffset = DSBPN_OFFSETSTOP;//再生が終わったら通知。 // wavsize - 1; //最後(の一瞬前)まで進んだら通知
pos.hEventNotify = CreateEvent(NULL, TRUE, FALSE, NULL);//通知に使うイベントを用意
if (notify->SetNotificationPositions(1, &pos) != DS_OK)//通知されるように登録
{
goto FINALLY;
}
if (buffer->Play(0, 0, 0) != DS_OK)//一回だけ再生
{
goto FINALLY;
}
while (WaitForSingleObject(pos.hEventNotify, 100) == WAIT_TIMEOUT)
{//最後まで再生されたらイベントがTrueになるので、それまで待つ
}
FINALLY:
if (pos.hEventNotify != 0) { CloseHandle(pos.hEventNotify); }
if (notify != NULL) { notify->Release(); }
if (buffer != NULL) { buffer->Release(); }
if (pds != NULL) { pds->Release(); }
if (pwav != NULL) { free(pwav); }
}
BOOL ReadWav(void** ppmem, DWORD* psize, WAVEFORMATEX* pformat)
{
*ppmem = NULL;
*psize = 0;
HANDLE hFile = 0;
hFile = CreateFile(WAVFILEPATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == 0)
{
return FALSE;
}
DWORD read = 0;
DWORD sizeH;
DWORD sizeL;
sizeL = GetFileSize(hFile, &sizeH);
if (sizeH)
{//大きすぎ
return FALSE;
}
if (sizeL == 0)
{//データなし
return FALSE;
}
void* pmem;
pmem = malloc(sizeL);
ReadFile(hFile, pmem, sizeL, &read, NULL);
CloseHandle(hFile); hFile = NULL;
if (sizeL != read)
{
free(pmem);
return FALSE;
}
*psize = sizeL;
*ppmem = pmem;
//面倒なので固定値
pformat->cbSize = sizeof(WAVEFORMATEX);
pformat->wFormatTag = WAVE_FORMAT_PCM;
pformat->nChannels = 2;
pformat->nSamplesPerSec = 44100;
pformat->wBitsPerSample = 16;
pformat->nBlockAlign = (pformat->wBitsPerSample / 8) * pformat->nChannels;
pformat->nAvgBytesPerSec = pformat->nBlockAlign * pformat->nSamplesPerSec;
return TRUE;
}
#include "pch.h"
#include "test.h"
#include <objbase.h>
#include <initguid.h>
#include <mmsystem.h>
#include <dsound.h>
#pragma comment(lib, "dsound.lib")
typedef struct
{
HWND hwnd;
HANDLE waitHandle;
} STEMP;
LPDIRECTSOUNDBUFFER buffer = NULL;
LPDIRECTSOUND8 pds = NULL;
static BOOL ReadWav(void** ppmem, DWORD* psize, WAVEFORMATEX* pformat);
static DWORD WINAPI WaitPlay(void* arg);
void Test(HWND hwnd)
{
void* pwav = NULL; //WAVのデータ格納
DWORD wavsize;//WAVデータの大きさ
WAVEFORMATEX format;//WAVのフォーマット
if (!ReadWav(&pwav, &wavsize, &format))//再生させたいWAVデータを取得
{
return;
}
LPDIRECTSOUNDNOTIFY notify = NULL;
DirectSoundCreate8(NULL, &pds, NULL);
if (pds == NULL)
{
goto FINALLY;
}
if (pds->SetCooperativeLevel(hwnd, DSSCL_NORMAL) != DS_OK)
{
goto FINALLY;
}
DSBUFFERDESC desc;//バッファ定義
memset(&desc, 0, sizeof(desc));
desc.dwSize = sizeof(desc);
desc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY; //通知を有効にする
desc.dwBufferBytes = wavsize;
desc.lpwfxFormat = &format;
desc.guid3DAlgorithm = GUID_NULL;
//再生バッファ
if (pds->CreateSoundBuffer(&desc, &buffer, NULL) != DS_OK)
{
goto FINALLY;
}
//バッファにWAVを書き込み
void* pbuff[2];
DWORD sz[2];
buffer->SetCurrentPosition(0);
buffer->Lock(0, wavsize, &pbuff[0], &sz[0], &pbuff[1], &sz[1], DSBLOCK_ENTIREBUFFER);
memcpy(pbuff[0], pwav, wavsize);
buffer->Unlock(pbuff[0], sz[0], pbuff[1], sz[1]);
//通知登録用のインターフェースを取得
if (buffer->QueryInterface(IID_IDirectSoundNotify8, (LPVOID*)&notify) != S_OK)
{
goto FINALLY;
}
DSBPOSITIONNOTIFY pos;//通知定義
memset(&pos, 0, sizeof(pos));
pos.dwOffset = DSBPN_OFFSETSTOP;//再生が終わったら通知。 // wavsize - 1; //最後(の一瞬前)まで進んだら通知
//pos.dwOffset = wavsize - 1;
pos.hEventNotify = CreateEvent(NULL, TRUE, FALSE, NULL);//通知に使うイベントを用意
if (notify->SetNotificationPositions(1, &pos) != DS_OK)//通知されるように登録
{
goto FINALLY;
}
if (buffer->Play(0, 0, 0) != DS_OK)//一回だけ再生
{
goto FINALLY;
}
//while (WaitForSingleObject(pos.hEventNotify, 100) == WAIT_TIMEOUT)
//{//最後まで再生されたらイベントがTrueになるので、それまで待つ
//}
//typedef struct
//{
// HWND hwnd;
// HANDLE waitHandle;
//} STEMP;
STEMP* ptemp;
ptemp = (STEMP*)malloc(sizeof(STEMP));
ptemp->hwnd = hwnd;
ptemp->waitHandle = pos.hEventNotify;
if (NULL == CreateThread(NULL, 0, WaitPlay, (void*)ptemp, 0, NULL))//スレッドを作る
{
CloseHandle(pos.hEventNotify);
buffer->Release();
pds->Release();
}
FINALLY:
//if (pos.hEventNotify != 0) { CloseHandle(pos.hEventNotify); }
if (notify != NULL) { notify->Release(); }
//if (buffer != NULL) { buffer->Release(); }
//if (pds != NULL) { pds->Release(); }
if (pwav != NULL) { free(pwav); }
}
DWORD WINAPI WaitPlay(void* arg)
{
STEMP temp = *(STEMP*)arg;
free(arg);
while (WaitForSingleObject(temp.waitHandle, 100) == WAIT_TIMEOUT) //スレッドで待つ
{//最後まで再生されたらイベントがTrueになるので、それまで待つ
}
CloseHandle(temp.waitHandle);
if (buffer != NULL) { buffer->Release(); }
if (pds != NULL) { pds->Release(); }
PostMessage(temp.hwnd, WM_COMMAND, MESSAGE_ID , 0);
return 0;
}
BOOL ReadWav(void** ppmem, DWORD* psize, WAVEFORMATEX* pformat)
{
*ppmem = NULL;
*psize = 0;
HANDLE hFile = 0;
hFile = CreateFile(WAVFILEPATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == 0)
{
return FALSE;
}
DWORD read = 0;
DWORD sizeH;
DWORD sizeL;
sizeL = GetFileSize(hFile, &sizeH);
if (sizeH)
{//大きすぎ
return FALSE;
}
if (sizeL == 0)
{//データなし
return FALSE;
}
void* pmem;
pmem = malloc(sizeL);
ReadFile(hFile, pmem, sizeL, &read, NULL);
CloseHandle(hFile); hFile = NULL;
if (sizeL != read)
{
free(pmem);
return FALSE;
}
*psize = sizeL;
*ppmem = pmem;
//面倒なので固定値
pformat->cbSize = sizeof(WAVEFORMATEX);
pformat->wFormatTag = WAVE_FORMAT_PCM;
pformat->nChannels = 2;
pformat->nSamplesPerSec = 44100;
pformat->wBitsPerSample = 16;
pformat->nBlockAlign = (pformat->wBitsPerSample / 8) * pformat->nChannels;
pformat->nAvgBytesPerSec = pformat->nBlockAlign * pformat->nSamplesPerSec;
return TRUE;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment