![]() |
|---|
| 物理的な音の「波」 |
|
| 論理的な音の「点」 |
MMRESULT waveOutOpen( LPHWAVEOUT phwo , UINT uDeviceID, LPWAVEFORMATEX pwfx , DWORD dwCallback , DWORD dwCallbackInstance , DWORD fdwOpen );phwo は HWAVEOUT 型の、デバイス識別用ハンドルへのポインタを指定します
| 定数 | 解説 |
|---|---|
| CALLBACK_EVENT | dwCallback はイベントハンドルである |
| CALLBACK_FUNCTION | dwCallback はコールバック関数のポインタである |
| CALLBACK_NULL | コールバックは使用しない |
| CALLBACK_THREAD | dwCallback はスレッドハンドルである |
| CALLBACK_WINDOW | dwCallback はウィンドウハンドルである |
| WAVE_ALLOWSYNC | このフラグが指定されていれば 同期したウェーブオーディオを開くことができる 指定されていなければ、失敗する |
| WAVE_FORMAT_DIRECT | このフラグが指定されていれば ACM ドライバは音声データを転送しない |
| WAVE_FORMAT_QUERY | このフラグが指定されていれば 関数はデバイスに、指定フォーマットをサポートしているか求める ただし、実際にデバイスはオープンされない |
| WAVE_MAPPED | このフラグが指定されていれば uDeviceID は、ウェーブマっパによってマップされる ウェーブフォームオーディオデバイスを指定する |
| 定数 | 解説 |
|---|---|
| MMSYSERR_ALLOCATED | リソースは、すでに割り当てられている |
| MMSYSERR_BADDEVICEID | デバイス識別子が無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| WAVERR_BADFORMAT | デバイスドライバは、指定されたフォーマットをサポートしていない |
| WAVERR_SYNC | 同期デバイスが指定されたが WAVE_ALLOWSYNC フラグが指定されていない |
typedef struct {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
nFormatTag には、ウェーブフォームオーディオのフォーマットを指定しますvoid CALLBACK waveOutProc( HWAVEOUT hwo , UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );hwo には、waveOutOpen() で作成された出力デバイスのハンドルが
MMRESULT waveOutPrepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
typedef struct {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
struct wavehdr_tag * lpNext;
DWORD reserved;
} WAVEHDR;
lpData には、ウェーブフォームバッファへのポインタを指定します| 定数 | 解説 |
|---|---|
| WHDR_BEGINLOOP | このバッファはループ内の先頭バッファである |
| WHDR_DONE | このフラグはデバイスドライバが設定する ドライバがバッファの使用を終了したことを表す |
| WHDR_ENDLOOP | このバッファはループ内の最後のバッファである |
| WHDR_INQUEUE | このフラグは Windows が設定する バッファが再生キューに入ることを表す |
| WHDR_PREPARED | このフラグは Windows が設定する バッファが準備されたことを表す |
MMRESULT waveOutWrite( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| WAVERR_UNPREPARED | pwh が指すバッファが準備されていない |
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| MMSYSERR_NOTSUPPORTED | 関数がサポートされていない |
MMRESULT waveOutUnprepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
#include <windows.h>
#define TITLE TEXT("Kitty on your lap")
#define SRATE 11025
LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wp , LPARAM lp) {
static HWAVEOUT hWave;
static BYTE *bWave;
static WAVEHDR whdr;
DWORD dwCount , dwWave = 0;
WAVEFORMATEX wfe;
switch (msg) {
case WM_DESTROY:
waveOutReset(hWave);
waveOutUnprepareHeader(hWave , &whdr , sizeof(WAVEHDR));
free(bWave);
waveOutClose(hWave);
PostQuitMessage(0);
return 0;
case WM_CREATE:
bWave = malloc(SRATE);
for (dwCount = 0 ; dwCount < SRATE ; dwCount++ , dwWave += 10) {
if (dwWave > 256) dwWave = 0;
*(bWave + dwCount) = dwWave;
}
wfe.wFormatTag = WAVE_FORMAT_PCM;
wfe.nChannels = 1;
wfe.nSamplesPerSec = SRATE;
wfe.nAvgBytesPerSec = SRATE;
wfe.wBitsPerSample = 8;
wfe.nBlockAlign = wfe.nChannels * wfe.wBitsPerSample / 8;
waveOutOpen(&hWave ,
WAVE_MAPPER , &wfe , 0 , 0 , CALLBACK_NULL);
whdr.lpData = bWave;
whdr.dwBufferLength = SRATE;
whdr.dwFlags = WHDR_BEGINLOOP | WHDR_ENDLOOP;
whdr.dwLoops = 5;
waveOutPrepareHeader(hWave , &whdr , sizeof(WAVEHDR));
waveOutWrite(hWave , &whdr , sizeof(WAVEHDR));
return 0;
}
return DefWindowProc(hWnd , msg , wp , lp);
}
int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
PSTR lpCmdLine , int nCmdShow) {
HWND hWnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL , IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL , IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("KITTY");
if (!RegisterClass(&winc)) return 1;
hWnd = CreateWindow(
TEXT("KITTY") , TITLE ,
WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
CW_USEDEFAULT , CW_USEDEFAULT ,
CW_USEDEFAULT , CW_USEDEFAULT ,
NULL , NULL , hInstance , NULL
);
if (hWnd == NULL) return 1;
while (GetMessage(&msg , NULL , 0 , 0 )) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
このプログラムを実行すると、420 Hz 前後の波形音声が 5 秒間出力されますfor (dwCount = 0 ; dwCount < SRATE ; dwCount++ , dwWave += 10) {
if (dwWave == 256) dwWave = 0;
*(bWave + dwCount) = dwWave;
}
このループは、数値を 0 〜 250 まで 10 ずつ加算し、その後 0 に再び戻しますMMRESULT waveOutOpen( LPHWAVEOUT phwo , UINT uDeviceID, LPWAVEFORMATEX pwfx , DWORD dwCallback , DWORD dwCallbackInstance , DWORD fdwOpen );ウェーブフォームオーディオ出力デバイスを開きます
| 定数 | 解説 |
|---|---|
| CALLBACK_EVENT | dwCallback はイベントハンドルである |
| CALLBACK_FUNCTION | dwCallback はコールバック関数のポインタである |
| CALLBACK_NULL | コールバックは使用しない |
| CALLBACK_THREAD | dwCallback はスレッドハンドルである |
| CALLBACK_WINDOW | dwCallback はウィンドウハンドルである |
| WAVE_FORMAT_DIRECT | このフラグが指定されていれば ACM ドライバは音声データを転送しない |
| WAVE_FORMAT_QUERY | このフラグが指定されていれば 関数はデバイスに、指定フォーマットをサポートしているか求める ただし、実際にデバイスはオープンされない |
| WAVE_MAPPED | このフラグが指定されていれば uDeviceID は、ウェーブマっパによってマップされる ウェーブフォームオーディオデバイスを指定する |
| 定数 | 解説 |
|---|---|
| MMSYSERR_ALLOCATED | リソースは、すでに割り当てられている |
| MMSYSERR_BADDEVICEID | デバイス識別子が無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| WAVERR_BADFORMAT | デバイスドライバは、指定されたフォーマットをサポートしていない |
| WAVERR_SYNC | 同期デバイスが指定されたが WAVE_ALLOWSYNC フラグが指定されていない |
void CALLBACK waveOutProc( HWAVEOUT hwo , UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2 );waveOutOpen() 関数が呼び出すアプリケーション定義のコールバック関数です
MMRESULT waveOutPrepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );再生に使う出力バッファブロックを準備します
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
MMRESULT waveOutWrite( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );データバッファブロックを指定出力デバイスに送信します
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| WAVERR_UNPREPARED | pwh が指すバッファが準備されていない |
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| MMSYSERR_NOTSUPPORTED | 関数がサポートされていない |
MMRESULT waveOutUnprepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );準備済みのバッファブロックを解放できるように、準備の終結処理を行います
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |
| 定数 | 解説 |
|---|---|
| MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である |
| MMSYSERR_INVALHANDLE | デバイスハンドルが無効である |
| MMSYSERR_NODRIVER | デバイスドライバがない |
| MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない |