開発環境 Microsoft Visual Studio Community 2017
実行環境 Microsoft Windows 10 Home (64-bit)
プロジェクトの種類 Visual C++ / 空のプロジェクト
プロジェクト名 waveout

waveout.cpp
/*
プロジェクト・プロパティ
全般 Unicode 文字セット
 
WaveOnMessage系は無理に処理する必要はない。
*/
 
#pragma comment(lib, "winmm")
 
#include <Windows.h>
#include <wchar.h>
#include <math.h>
#include "resource.h"
 
#define SAMPLE_RATE 48000
 
// 関数プロトタイプ宣言
void Trace(PCWSTR format, ...);
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg,
	DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2);
void Play(HWND hDlg);
void Stop(HWND hDlg);
LPSTR GenerateWaveform();
 
// グローバル変数
HWAVEOUT hwo = NULL;
WAVEHDR wh;
LPSTR lpData = NULL;
DWORD dwBufferLength;
 
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);
	return 0;
}
 
void Trace(PCWSTR format, ...)
{
	va_list arg_ptr;
	WCHAR buffer[256];
 
	va_start(arg_ptr, format);
	int size = _vsnwprintf_s(buffer, _TRUNCATE, format, arg_ptr);
	va_end(arg_ptr);
	OutputDebugString(buffer);
}
 
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	INT_PTR nRet = TRUE;
 
	switch (uMsg) {
	case MM_WOM_OPEN:
		Trace(L"MM_WOM_OPEN:\n");
		break;
	case MM_WOM_CLOSE:
		Trace(L"MM_WOM_CLOSE:\n");
		break;
	case MM_WOM_DONE:
		Trace(L"MM_WOM_DONE:\n");
		//Stop(hDlg);
		break;
 
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDOK:
			Play(hDlg);
			break;
		case IDCANCEL:
			Stop(hDlg);
			break;
		}
		break;
	case WM_INITDIALOG:
		break;
	case WM_CLOSE:
		Stop(hDlg);
		EndDialog(hDlg, 0);
		break;
	default:
		nRet = FALSE;
	}
	return nRet;
}
 
void CALLBACK waveOutProc(HWAVEOUT hwo, UINT uMsg,
	DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
	switch (uMsg) {
	case WOM_OPEN:
		Trace(L"WOM_OPEN:");
		break;
	case WOM_CLOSE:
		Trace(L"WOM_CLOSE:");
		break;
	case WOM_DONE:
		Trace(L"WOM_DONE:");
		break;
	}
	Trace(L" %x\n", dwInstance);
}
 
void Play(HWND hDlg)
{
	lpData = GenerateWaveform();
 
	//
	UINT mmr;
 
	WAVEFORMATEX wfx;
	wfx.wFormatTag = WAVE_FORMAT_PCM;
	wfx.nChannels = 1;
	wfx.nSamplesPerSec = SAMPLE_RATE;
	wfx.nAvgBytesPerSec = SAMPLE_RATE;
	wfx.nBlockAlign = 1;
	wfx.wBitsPerSample = 8;
	wfx.cbSize = 0;
	//mmr = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)hDlg, NULL, CALLBACK_WINDOW);
	mmr = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc, 0xcafe, CALLBACK_FUNCTION);
	Trace(L"waveOutOpen: %u\n", mmr);
 
	wh.lpData = (LPSTR)lpData;
	wh.dwBufferLength = dwBufferLength;
	wh.dwFlags = 0;
	mmr = waveOutPrepareHeader(hwo, &wh, sizeof wh);
	Trace(L"waveOutPrepareHeader: %u\n", mmr);
 
	mmr = waveOutWrite(hwo, &wh, sizeof wh);
	Trace(L"waveOutWrite: %u\n", mmr);
 
	EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
}
 
void Stop(HWND hDlg)
{
	Trace(L"Stop()\n");
	if (hwo) {
		UINT mmr;
		mmr = waveOutReset(hwo);
		Trace(L"waveOutReset: %u\n", mmr);
		mmr = waveOutUnprepareHeader(hwo, &wh, sizeof wh);
		Trace(L"waveOutUnprepareHeader: %u\n", mmr);
		mmr = waveOutClose(hwo);
		Trace(L"waveOutClose: %u\n", mmr);
		hwo = NULL;
	}
	if (lpData) {
		free(lpData);
		lpData = NULL;
	}
	EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
}
 
LPSTR GenerateWaveform()
{
	const int note[] = { 0, 2, 4, 5, 7, 9, 11, 12 };
 
	dwBufferLength = SAMPLE_RATE * 4;
	PBYTE data = (PBYTE)malloc(dwBufferLength);
	memset(data, 0x80, dwBufferLength);
 
	int pos = 0;
	for (int i = 0; i < 8; i++) {
		int freq = (int)(440 * pow(2, (note[i] - 9) / 12.0));
		int gate = SAMPLE_RATE / 2;
		double s = 0;
		for (int j = 0; j < gate; j++) {
			s += freq;
			if (s >= SAMPLE_RATE) s -= SAMPLE_RATE;
			double t = s / SAMPLE_RATE;
			data[pos + j] += (t < 0.5 ? 1 : -1) * 8;
		}
		pos += gate;
	}
	return (LPSTR)data;
}
 

resource.h
#define IDD_MAIN	100
 
#define IDC_STATIC	-1
 

waveout.rc
// resource script
#include <windows.h>
#include "resource.h"
 
IDD_MAIN DIALOGEX 100, 100, 320, 200
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION L"waveout"
FONT 9, L"MS Pゴシック"
BEGIN
	DEFPUSHBUTTON	L"OK",IDOK,212,176,48,16
	PUSHBUTTON		L"Cancel",IDCANCEL,264,176,48,16
END
 
最終更新:2018年04月11日 12:00