PCM(Pulse Code Modulation) です
PCM は波形データを圧縮しない形式のもので、CD や Windows で使われています
MP3 等も波形オーディオですが、圧縮されているため PCM とは異なります
音声と数値でータの入出力には、それぞれ専用のハードウェアが使われます
波形を数値に変換するには、ADC(Analog-to-Digital Converter) が使われ
PCM データを音として出力するには、DAC(Digital-toAnalog Converter) が使われます
音声とDIBの違いのひとつに、音声は「時間」が関係してくるということがあります
波形の振り幅を1秒間に何回保存するかということをサンプリングレートと呼び
例えば、1秒間に1000回の割合で、音声を数値化するならば 1000 サンプルであり
サンプル数はヘルツ Hz で表すので 1000Hz、または 1kHz と表します
波形オーディオがサポートするサンプリングレートは
一般的に 8kHz、11.025kHz、22.05kHz、44.1kHz などがあります
例えば、CD は 44.1kHz を用いています。
このような、奇妙な数値のサンプリングレートは、物理的理由で決められています
人間の耳に正確に音が再生されたように聴かせるには 44.1kHz あれば十分です
音をデジタルに録音するとは、波形データの「波」を連続した数値の「点」に変換することで
これを再び音にするには、連続した「点」を繋ぎ合わせて「波」に変換します
|
---|
物理的な音の「波」
|
---|
|
---|
論理的な音の「点」
|
---|
この図のように、波形は連続した数値として保存されます
数値を音に変換する時は DAC が数値を読み取り電子波形に変換します
当然、これは録音した音声とは論理的に異なり、完全な複製ではありません
波形を表す点の数、すなわちサンプリングレートが少なければ少ないほど
元の音声の情報が減少し、人間にとって「劣化」したような音に感じられるでしょう
綺麗は波形の線を描くには、それだけ多くの点を連続的に保存しなければならないのです
これが、良質な音声を保存するメディアファイルの容量が大きい原因です
では、コンピュータは実際に、どのような数列で音を表現するのでしょうか
音の長さは、数列の数によって決定されます
例えば、11.025kHz であれば、1秒間の音声は 11025 個の数列となります
実際のバイト数は、1つの音を表すのにどの程度の情報量を使うかでことなります
Windows の場合、8 ビット、または 16 ビットのいずれかを選択することができます
もし、8 ビットであれば、1バイトは 1/11025 秒の音声の情報をあらわすことになるでしょう
次に音の高さ、すなわち音程ですが
実世界は、これを周波数、つまり物理的振動の波の数で決定されます
波の間隔が狭ければ音は高く、波の間隔が広ければ低く感じられます
救急車が近づいた時などに発生する、ドップラー効果は、音の波を実感する良い例です
数字における音の波は、数字が高くなったり低くなったりを繰り返すことで表現します
8 ビットの場合は、符号無しで 128 という値の連続が「無音」として扱われ
16 ビットであれば、符合有りで 0 の連続が「無音」として扱われます
この基本となる値よりも高くなったり低くなったりすることで、周波が表現されます
特定の周波数を発生させたい場合、1秒間に目的の周波数だけ波を発生させます
例えば、440Hz の音を発生させたければ、1秒間に 440 回だけ数値が上下します
この時の数値が上下する間隔をサイクルと呼びます
1サイクルのサンプル数を計算するには、サンプリングレートに周波数を除算します
例えば 11,025 kHz に 440 Hz の音を発生させる場合、11025÷440 を計算し
1サイクルに約 25 サンプル必要になるという事がわかります
残念ながら、波形の世界では「ミ」の音を出したいという要求はこたえられません
そもそも、「ドレミファソラシド」というのは、人間の耳に合う波形の間隔に名前をつけたもので
基音の周波数に 2 を乗算するとオクターブが上がるという性質を持っています
基音に対して完全 5 度上の音は 1.5 倍、長 3 度上は 5/4 倍というように計算します
やはり、音に対してより詳しくなりたければ、音楽学と物理学を勉強する必要がでてきますね
物理学的な音の性質の最後は音の強さ、すなわち音量です
音量は、波形データの振幅、つまり波の高さで決定されます
数値配列で表現された波の、最上部と最下部の絶対値が振幅となります
因みに、音の強さは一般的にデシベル (dB)で表されます
1dB はかすかに聞こえる程度の音量で、100 dB にもなると、苦痛に感じる音量になります
2つの音の差をダイナミックレンジと呼び、次のように計算できます
dB = 20 log (S1/S2)
S1 と S2 には、それぞれ比較する2つの音の振幅を指定します
これで計算すればわかりますが、振幅を8ビットにするか16ビットにするかという問題は
ダイナミックレンジ、つまり音量の表現力に直接影響します
さて、では実際にプログラムで作成した数列を音として出力する方法を説明します
「波」には様々な形があり、きれいな曲線を描く正弦波(sin波)や
三角形の山が連続する三角波などが考えられます
これらの波は、人工的に作った機械的な音質を作り出します
今回のサンプルでは、ループで単純に作ることができる、ノコギリ波を用います
波形オーディオの出力に関連した関数などは mmsystem.h で宣言され
winmm.lib ファイルでインポートすることができます
環境によっては winmm.lib ファイルを明示的にインポートする必要があります
波形オーディオを出力するには、出力デバイスを開く必要があります
これには、waveOutOpen() 関数を用います
MMRESULT waveOutOpen(
LPHWAVEOUT phwo , UINT uDeviceID,
LPWAVEFORMATEX pwfx ,
DWORD dwCallback , DWORD dwCallbackInstance ,
DWORD fdwOpen
);
phwo は HWAVEOUT 型の、デバイス識別用ハンドルへのポインタを指定します
これは、ウェーブフォームオーディオ出力デバイスのハンドルで
このハンドルに、オープンした出力デバイスの識別子を格納します
以後、音声出力関数に対しては、このハンドルを用いて出力デバイスを指定します
uDeviceID には、対象の出力デバイスの識別子を指定します
この値は常に 「0 〜 インストールされている有効なデバイス数 - 1」の範囲になります
WAVE_MAPPER を指定すれば、ユーザーが選択している優先デバイスが適応されます
特別なことがない限り、通常は WAVE_MAPPAER を指定するべきです
pwfx には、WAVEFORMATEX 構造体へのポインタを指定します
この構造体には、ウェーブフォーマットやサンプリングレートなどを設定します
dwCallback は、再生中にウェーブの関連メッセージを受け取る対象を指定します
ここには、コールバック関数、ウィンドウハンドル、イベントハンドル
または、スレッドハンドルのいずれかを指定することができます
dwCallbackInstance には、コールバック関数に渡すデータを指定できます
ウィンドウハンドルによるコールバックを採用した場合、この値は使われません
fdwOpen は、デバイスを開くためのフラグを指定します
この引数には、以下の値のいずれか、または組み合わせを指定できます
定数 | 解説
|
---|
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_NOERROR が、そうでなければエラー値が返ります
エラーが発生した場合、次のいずれかの値がかえります
定数 | 解説
|
---|
MMSYSERR_ALLOCATED | リソースは、すでに割り当てられている
|
MMSYSERR_BADDEVICEID | デバイス識別子が無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
WAVERR_BADFORMAT | デバイスドライバは、指定されたフォーマットをサポートしていない
|
WAVERR_SYNC | 同期デバイスが指定されたが WAVE_ALLOWSYNC フラグが指定されていない
|
今は、コールバックメッセージを使わないので、コールバックについては後ほど説明します
WAVEFORMATEX 構造体は次のように定義されています
typedef struct {
WORD wFormatTag;
WORD nChannels;
DWORD nSamplesPerSec;
DWORD nAvgBytesPerSec;
WORD nBlockAlign;
WORD wBitsPerSample;
WORD cbSize;
} WAVEFORMATEX;
nFormatTag には、ウェーブフォームオーディオのフォーマットを指定します
ここに指定する定数は、MMREG.H ヘッダファイルに記述されています
フォーマットは圧縮アルゴリズムなどに備えて Microsoft に登録されていますが
PCM の場合は、常に WAVE_FORMAT_PCM を指定します
nChannels はチャンネルの数を指定することで、モノラルかステレオかを指定するメンバです
モノラルの場合は 1 を、ステレオの場合は 2 (右チャンネルと左チャンネル)を指定します
とりあえず、この場のサンプルプログラムはモノラルとして出力します
nSamplesPerSec にはサンプリングレートを指定します
nAvgBytesPerSec は、必須平均データ転送レートを バイト/秒 単位で指定します
PCM の場合、通常はサンプリングレート * nBlockAlign を指定します
nBlockAlign は、指定フォーマットの最小単位のデータサイズを指定します
これをブロックアラインメントと呼び
PCM の場合、このメンバには nChannels * wBitsPerSample / 8 を指定します
nBitsPerSample は、サンプルあたりのビット数を指定します
先ほど説明したように、PCM の場合は 8 ビット、または 16 ビットを指定できます
cbSize は、この構造体の末尾に追加される、拡張情報のサイズをバイト単位で指定します
このメンバは PCM フォーマットの場合は 0 を指定します
もし、waveOutOpen() 関数の dwCallback にコールバック関数を指定する場合
次の waveOutProc() と同じ型の関数でなければなりません
void CALLBACK waveOutProc(
HWAVEOUT hwo , UINT uMsg,
DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2
);
hwo には、waveOutOpen() で作成された出力デバイスのハンドルが
uMsg には、送信メッセージが格納されます
dwInstance は、関数で指定したユーザー定義の追加情報
dwParam1 と dwParam2 にはメッセージの追加情報が指定されます
音声を開いたデバイスに出力するには、まずデータブロックを準備します
適当な方法で準備された、波形データを表す数列を出力用に準備するのです
そのためには waveOutPrepareHeader() 関数を呼び出します
MMRESULT waveOutPrepareHeader(
HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh
);
hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
pwh は、WAVEHDR 構造体へのポインタです
この構造体に、音声データのバッファの情報を与えておきます
cbwh には、WAVEHDR 構造体のサイズを指定します
関数が成功すれば MMSYSERR_NOERROR が、そうでなければエラー値が返ります
この関数が返すエラー値は、以下のいずれかの定数になります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
WAVEHDR 構造体は次のように定義されています
この構造体で、入出力する音声データのバッファ情報を表すことができます
typedef struct {
LPSTR lpData;
DWORD dwBufferLength;
DWORD dwBytesRecorded;
DWORD dwUser;
DWORD dwFlags;
DWORD dwLoops;
struct wavehdr_tag * lpNext;
DWORD reserved;
} WAVEHDR;
lpData には、ウェーブフォームバッファへのポインタを指定します
dwBufferLength に、指定したバッファのサイズをバイト単位で指定します
dwBytesRecorded 入力バッファとして使用する場合に
指定したバッファ内のデータ要領を指定します
dwUser は、オプションのユーザーデータを指定することができます
dwFlags には、バッファに付いての追加情報をフラグで指定します
このメンバには、以下の定数の組み合わせを指定することができます
定数 | 解説
|
---|
WHDR_BEGINLOOP | このバッファはループ内の先頭バッファである
|
WHDR_DONE | このフラグはデバイスドライバが設定する ドライバがバッファの使用を終了したことを表す
|
WHDR_ENDLOOP | このバッファはループ内の最後のバッファである
|
WHDR_INQUEUE | このフラグは Windows が設定する バッファが再生キューに入ることを表す
|
WHDR_PREPARED | このフラグは Windows が設定する バッファが準備されたことを表す
|
dwLppps には、出力ループ回数を指定します
lpNext メンバと reserved メンバは使用しません
それぞれ 0 で初期化してください
バッファを準備した後も、この構造体の dwBufferLength、dwFlags、dwLoops は変更できます
ただし、再生中にメンバを変更してはいけません
バッファの準備ができたら、後は再生するだけです
再生するには waveOutWrite() 関数を使います
MMRESULT waveOutWrite(
HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh
);
hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
pwh には、準備済みの WAVEHDR 構造体へのポインタを
cbwh には、WAVEHDR 構造体のサイズを指定します
関数が成功すれば MMSYSERR_NOERROR が、そうでなければエラー値が返ります
この関数が返すエラー値は、以下のいずれかの定数になります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
WAVERR_UNPREPARED | pwh が指すバッファが準備されていない
|
さて、これでバッファ内のデータを音声としてデバイスに出力できます
次に、再生が終了した時点で解放処理を行う必要があります
再生を終了するには waveOutReset() 関数を用います
この関数は、再生を終了し、現在の位置を 0 に戻します
MMRESULT waveOutReset(HWAVEOUT hwo);
hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
関数が成功すれば MMSYSERR_NOERROR が、それ以外の場合はエラー値がかえります
この関数が返すエラー値は、以下のいずれかの定数になります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
MMSYSERR_NOTSUPPORTED | 関数がサポートされていない
|
次に、バッファの解放を行う必要がありますが
waveOutPrepareHeader() で準備済みのバッファは解放してはいけません
解放するには waveOutUnprepareHeader() で準備を終了します
MMRESULT waveOutUnprepareHeader(
HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh
);
hwo にはウェーブフォームオーディオ出力デバイスのハンドルを指定します
pwh には、準備済みの WAVEHDR 構造体へのポインタを
cbwh には、WAVEHDR 構造体のサイズを指定します
関数が成功すれば MMSYSERR_NOERROR が、そうでなければエラー値が返ります
この関数が返すエラー値は、以下のいずれかの定数になります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
この関数で準備を終了すれば、バッファを解放することができます
最後に waveOutClose() 関数で、不用になったデバイスを解放します
MMRESULT waveOutClose(HWAVEOUT hwo);
hwo には、ウェーブフォームオーディを出力デバイスのハンドルを指定します
関数が成功すれば MMSYSERR_NOERROR が、そうでなければエラー値が返ります
この関数が返すエラー値は、以下のいずれかの定数になります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
今説明したこれらの関数を使えば、簡単に波形データを出力することができます
プログラムで作成した数値データを、直接出力するという芸当は、低レベル API の特権です
#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 秒間出力されます
11025 バイトのバッファを用意し、これに振幅 8 ビットの波形データを格納しています
このバッファが1秒間の音声を表す波形データで、これを 5 回リピートしているのです
バッファは、次の一文で初期化していることがわかります
for (dwCount = 0 ; dwCount < SRATE ; dwCount++ , dwWave += 10) {
if (dwWave == 256) dwWave = 0;
*(bWave + dwCount) = dwWave;
}
このループは、数値を 0 〜 250 まで 10 ずつ加算し、その後 0 に再び戻します
これで、1つの山が 25 サンプルのノコギリ波を生成しています
440 Hz が標準的な「ラ」の音なので、この音はラよりもやや低い音になります
waveOutOpen()
MMRESULT waveOutOpen(
LPHWAVEOUT phwo , UINT uDeviceID,
LPWAVEFORMATEX pwfx ,
DWORD dwCallback , DWORD dwCallbackInstance ,
DWORD fdwOpen
);
ウェーブフォームオーディオ出力デバイスを開きます
phwo - デバイス識別用ハンドルへのポインタを指定します
uDeviceID - 対象の出力デバイスの識別子を指定します
pwfx - WAVEFORMATEX 構造体へのポインタを指定します
dwCallback - 再生中にウェーブの関連メッセージを受け取る対象を指定します
dwCallbackInstance - コールバック関数に渡すデータを指定できます
fdwOpen - デバイスを開くためのフラグを指定します
戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値
fdwOpen には以下のいずれかの値、または組み合わせを指定します
WAVE_ に組みあわせることができるのは 1 つの CALLBACK_ だけです
定数 | 解説
|
---|
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 フラグが指定されていない
|
waveOutProc()
void CALLBACK waveOutProc(
HWAVEOUT hwo , UINT uMsg,
DWORD dwInstance,
DWORD dwParam1, DWORD dwParam2
);
waveOutOpen() 関数が呼び出すアプリケーション定義のコールバック関数です
hwo - waveOutOpen() で作成された出力デバイスのハンドルを指定します
uMsg - 送信メッセージを指定します
dwInstance - 関数で指定したユーザー定義の追加情報を指定します
dwParam1 - メッセージの追加情報を指定します
dwParam2 - メッセージの追加情報を指定します
waveOutPrepareHeader()
MMRESULT waveOutPrepareHeader(
HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh
);
再生に使う出力バッファブロックを準備します
hwo - ウェーブフォームオーディオ出力デバイスのハンドルを指定します
pwh - WAVEHDR 構造体へのポインタを指定します
cbwh - WAVEHDR 構造体のサイズを指定します
戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値
この関数が返すエラー値は、以下の定数のいずれかになります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
waveOutWrite()
MMRESULT waveOutWrite(
HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh
);
データバッファブロックを指定出力デバイスに送信します
hwo - ウェーブフォームオーディオ出力デバイスのハンドルを指定します
pwh - WAVEHDR 構造体へのポインタを指定します
cbwh - WAVEHDR 構造体のサイズを指定します
戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値
この関数が返すエラー値は、以下の定数のいずれかになります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
WAVERR_UNPREPARED | pwh が指すバッファが準備されていない
|
waveOutReset()
MMRESULT waveOutReset(HWAVEOUT hwo);
再生を停止し、現在位置をリセットします
hwo - ウェーブフォームオーディオ出力デバイスのハンドルを指定します
戻り値 - 成功すれば MMSYSERR_NOERROR、それ以外の場合はエラー値
この関数が返すエラー値は、以下の定数のいずれかになります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
MMSYSERR_NOTSUPPORTED | 関数がサポートされていない
|
waveOutUnprepareHeader()
MMRESULT waveOutUnprepareHeader(
HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh
);
準備済みのバッファブロックを解放できるように、準備の終結処理を行います
hwo - ウェーブフォームオーディオ出力デバイスのハンドルを指定します
pwh - WAVEHDR 構造体へのポインタを指定します
cbwh - WAVEHDR 構造体のサイズを指定します
戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値
この関数が返すエラー値は、以下の定数のいずれかになります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|
waveOutClose()
MMRESULT waveOutClose(HWAVEOUT hwo);
ウェーブフォームオーディオ出力デバイスを閉じます
hwo - ウェーブフォームオーディを出力デバイスのハンドルを指定します
戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値
この関数が返すエラー値は、以下の定数のいずれかになります
定数 | 解説
|
---|
MMSYSERR_HANDLEBUSY | 別のスレッドがハンドルを使用中である
|
MMSYSERR_INVALHANDLE | デバイスハンドルが無効である
|
MMSYSERR_NODRIVER | デバイスドライバがない
|
MMSYSERR_NOMEM | メモリを割り当てられない、またはロックできない
|