開発環境 |
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