開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 WaveTest
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト
文字セット Unicode

WaveTest.cpp
#pragma comment(lib, "winmm")
 
#define _USE_MATH_DEFINES
 
#include <Windows.h>
#include <WindowsX.h>
#include <math.h>
#include <tchar.h>
#include "resource.h"
 
#define SAMPLING_RATE	44100
#define DATA_NUM	(SAMPLING_RATE)
#define VOL		0x3f
#define FREQ		441.0
 
// 関数プロトタイプ宣言
void Trace(LPCTSTR format, ...);
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg);
void OnDrawItem(WPARAM wParam, LPARAM lParam);
void OnRadio(HWND hDlg);
void OnOK(HWND hDlg);
void OnWomOpen(void);
void OnWomDone(HWND hDlg);
 
// 外部変数
HWAVEOUT hwo;
WAVEHDR wh;
BYTE waveformData[DATA_NUM];
int radio = 0;
 
//==============================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, DlgProc);
	return 0;
}
 
void Trace(LPCTSTR format, ...)
{
	va_list arg_ptr;
	TCHAR buffer[256];
	int size;
 
	va_start(arg_ptr, format);
	size = _vsntprintf_s(buffer, _countof(buffer), _TRUNCATE, format, arg_ptr);
	va_end(arg_ptr);
	OutputDebugString(buffer);
	if (size < 0) {
		OutputDebugString(_T("...\n"));
	}
}
 
INT_PTR CALLBACK DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	INT_PTR nRet = TRUE;	// メッセージを処理した
 
	switch (uMsg) {
	case MM_WOM_OPEN:
		OnWomOpen();
		break;
	case MM_WOM_DONE:
		OnWomDone(hDlg);
		break;
	case WM_DRAWITEM:
		OnDrawItem(wParam, lParam);
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_RADIO1:
		case IDC_RADIO2:
		case IDC_RADIO3:
		case IDC_RADIO4:
		case IDC_RADIO5:
			OnRadio(hDlg);
			break;
		case IDOK:
			OnOK(hDlg);
			break;
		case IDCANCEL:
			EndDialog(hDlg, IDCANCEL);
			break;
		}
		break;
	case WM_INITDIALOG:
		OnInitDialog(hDlg);
		break;
	case WM_CLOSE:
		EndDialog(hDlg, 0);
		break;
	default:
		nRet = FALSE;	// メッセージを処理しなかった
	}
	return nRet;
}
 
void OnInitDialog(HWND hDlg)
{
	Button_SetCheck(GetDlgItem(hDlg, IDC_RADIO1), BST_CHECKED);
	OnRadio(hDlg);
}
 
void OnDrawItem(WPARAM wParam, LPARAM lParam)
{
	LPDRAWITEMSTRUCT pdi = (LPDRAWITEMSTRUCT)lParam;
	HDC hdc = pdi->hDC;
 
	RECT rc;
	GetClientRect(pdi->hwndItem, &rc);
	FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW));
 
	HPEN pen = CreatePen(PS_SOLID, 0, RGB(0,0,255));
	HGDIOBJ penOld = SelectObject(hdc, pen);
	for (int i = 0; i < rc.right; i++) {
		MoveToEx(hdc, i, rc.bottom / 2, NULL);
		LineTo(hdc, i, rc.bottom * (255 - waveformData[i]) / 256);
	}
	SelectObject(hdc, penOld);
	DeleteObject(pen);
}
 
void OnRadio(HWND hDlg)
{
	int newRadio = 0;
	for (int i = 0; i < 5; i++) {
		if (Button_GetCheck(GetDlgItem(hDlg, IDC_RADIO1 + i))) {
			newRadio = i + 1;
			break;
		}
	}
	if (radio == newRadio) return;
 
	radio = newRadio;
	switch (radio) {
	case 1:	// Sine
		for (int i = 0; i < DATA_NUM; i++) {
			double t = fmod(i * FREQ / SAMPLING_RATE, 1.0);
			double y = sin(2 * M_PI * t);
			waveformData[i] = (BYTE)(128 + VOL * y);
		}
		break;
	case 2:	// Triangle
		for (int i = 0; i < DATA_NUM; i++) {
			double t = fmod(i * FREQ / SAMPLING_RATE, 1.0);
			double y;
			if (t < 0.25) {
				y = t * 4;
			} else if (t < 0.75) {
				y = (0.5 - t) * 4;
			} else {
				y = (t - 1) * 4;
			}
			waveformData[i] = (BYTE)(128 + VOL * y);
		}
		break;
	case 3:	// Sawtooth
		for (int i = 0; i < DATA_NUM; i++) {
			double t = fmod(i * FREQ / SAMPLING_RATE, 1.0);
			double y = t < 0.5 ? t * 2 : (t - 1) * 2;
			waveformData[i] = (BYTE)(128 + VOL * y);
		}
		break;
	case 4:	// Square 0.5
		for (int i = 0; i < DATA_NUM; i++) {
			double t = fmod(i * FREQ / SAMPLING_RATE, 1.0);
			double y = t < 0.5 ? 1 : -1;
			waveformData[i] = (BYTE)(128 + VOL * y);
		}
		break;
	case 5:	// Square 0.25
		for (int i = 0; i < DATA_NUM; i++) {
			double t = fmod(i * FREQ / SAMPLING_RATE, 1.0);
			double y = t < 0.25 ? 1 : -1;
			waveformData[i] = (BYTE)(128 + VOL * y);
		}
		break;
	}
 
	InvalidateRect(GetDlgItem(hDlg, IDC_PREVIEW), NULL, FALSE);
}
 
void OnOK(HWND hDlg)
{
	MMRESULT mmr;
 
	WAVEFORMATEX wfx;
	wfx.wFormatTag		= WAVE_FORMAT_PCM;
	wfx.wBitsPerSample	= 8;
	wfx.nChannels		= 1;
	wfx.nSamplesPerSec	= SAMPLING_RATE;
	wfx.nBlockAlign		= (wfx.wBitsPerSample / 8) * wfx.nChannels;
	wfx.nAvgBytesPerSec	= wfx.nSamplesPerSec * wfx.nBlockAlign;
	wfx.cbSize		= 0;
	mmr = waveOutOpen(&hwo, WAVE_MAPPER, &wfx, (DWORD_PTR)hDlg, 0, CALLBACK_WINDOW);
	if (mmr != MMSYSERR_NOERROR) {
		Trace(_T("waveOutOpen\n"));
		return;
	}
	EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
}
 
void OnWomOpen(void)
{
	MMRESULT mmr;
 
	wh.lpData		= (LPSTR)waveformData;
	wh.dwBufferLength	= DATA_NUM;
	wh.dwBytesRecorded	= 0;
	wh.dwUser		= 0;
	wh.dwFlags		= 0;
	wh.dwLoops		= 0;
	wh.lpNext		= NULL;
	wh.reserved		= 0;
	mmr = waveOutPrepareHeader(hwo, &wh, sizeof wh);
	if (mmr != MMSYSERR_NOERROR) {
		Trace(_T("waveOutPrepareHeader\n"));
		return;
	}
 
	wh.dwFlags		|= WHDR_BEGINLOOP | WHDR_ENDLOOP;
	wh.dwLoops		= 1;
	mmr = waveOutWrite(hwo, &wh, sizeof wh);
	if (mmr != MMSYSERR_NOERROR) {
		Trace(_T("waveOutWrite\n"));
	}
}
 
void OnWomDone(HWND hDlg)
{
	Trace(_T("OnWomDone\n"));
	waveOutReset(hwo);
	waveOutUnprepareHeader(hwo, &wh, sizeof wh);
	waveOutClose(hwo);
	EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
}
 

resource.h
#define IDD_MAIN	100
 
#define IDC_STATIC	-1
#define IDC_PREVIEW	1000
#define IDC_RADIO1	1001
#define IDC_RADIO2	1002
#define IDC_RADIO3	1003
#define IDC_RADIO4	1004
#define IDC_RADIO5	1005
 

WaveTest.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 "WaveTest"
FONT 9, "MS Pゴシック"
BEGIN
	LTEXT		"",IDC_PREVIEW,5,5,310,160,WS_BORDER | SS_OWNERDRAW
	CONTROL		"Sine",IDC_RADIO1,"button",BS_AUTORADIOBUTTON | WS_GROUP,10,170,50,12
	CONTROL		"Triangle",IDC_RADIO2,"button",BS_AUTORADIOBUTTON,60,170,50,12
	CONTROL		"Sawtooth",IDC_RADIO3,"button",BS_AUTORADIOBUTTON,110,170,50,12
	CONTROL		"Square 0.5",IDC_RADIO4,"button",BS_AUTORADIOBUTTON,160,170,50,12
	CONTROL		"Square 0.25",IDC_RADIO5,"button",BS_AUTORADIOBUTTON,210,170,50,12
	DEFPUSHBUTTON	"Play",IDOK,260,182,50,16,WS_GROUP
END
 
最終更新:2013年01月29日 16:02