No.003 - 01 WAVE再生の前フリ解説 |
筆者音楽系は苦手なのになぜかまたこんなコーナー。
WAVE再生のちゃんとしたソース置いてるサイトってあんまナイですね。
ページ目次 |
1.手順 2.サンプリングレートとダブルバッファリング解説 3.関数解説 |
1.WAVEデバイスを開く | 2.メモリのスワップアウト不可化 | 3.音データを送る | 4.メモリのスワップアウト不可化の解除 | 5.WAVEデバイスを閉じる |
参考:
|
サンプリングレート |
音はアナログな波形です。 1つの音は連続して途切れることなく流れていきます。 しかし途切れることなく音を処理させることなんてことはコンピュータにはできません。 そこで音の波形を数万分の一秒くらいの一定周期ごとに波形の振幅を数値化し、コンピュータで処理します。 これをサンプリングと呼び 1秒間のサンプリング数をサンプリングレートと呼びます 例えば、1秒間に10000回の割合で、音声を数値化するならば サンプリングレートは10000Hz、または 10kHz となります。 サンプリングレートが高ければ高いほど高品質な音になりますが、その分コンピュータには負担になります。 1930年代の技術者ナイキストさんによれば サンプリングレートはサンプリング音の最大周波数の2倍でなければならないと いうことから 人間の耳が認識できるのは20kHzなので全音域を拾うには 40kHz必要です。 しかし再生ハードウェアのローパス・フィルタ(高音域を排除し波形のスムーズにするフィルタ)で 波形が削られてしまうため10%周波数を上げる必要があり、ここで44kHzとなります。 更に欧米のテレビのフレーム率にあわせ、米30Hz, 欧25Hzの整数倍から 44.1kHzとなります。 CD は 44.1kHz を使ってますが、 44.1kHzはデータサイズとしてはかなり大きなもので音声の録音には不向きです。 サンプリングレートを半分の22.05kHzにすれば高音域1オクターブ分(10KHz)減ります。 さらに半分の11.025kHz、さらに半分の8kHzといったカンジで 一般的なデバイスは 8kHz、11.025kHz、22.05kHz、44.1kHz が標準サポートになってます。 |
|
ダブルバッファリング |
ダブルバッファリングは音が途切れ途切れになるのを防ぐテクニックです。 WAVEデバイスは送られたデータの再生が終わるとコールバック関数にMM_WOM_DONEメッセージ(WOM_DONE)を送ります。 したがってMM_WOM_DONEメッセージ(WOM_DONE)で次に再生するデータを送るわけですが このメッセージはデータの再生が終わってから送られて来るので次のデータの再送までわずかに無音状態が発生します。 そこで最初に2回waveOutWriteで音データを送ります。 すると最初に送った音と2回目に送ったデータの分で2回 MM_WOM_DONEメッセージ(WOM_DONE)が送られます。 1回目のMM_WOM_DONEメッセージ(WOM_DONE)が送られたとき、まだ2回目の分の音データが再生されているので無音状態にならなくて済む仕組みです。 あとは再生の終わった音データが交互に送られてくるのでもう一方のデータの再生が終わらないうちにwaveOutWriteで再送してやるだけです。 |
<mmsystem.h> typedef UINT MMRESULT; /* error return code, 0 means no error */ waveOutOpen()
MMRESULT waveOutOpen( LPHWAVEOUT phwo , UINT uDeviceID, LPWAVEFORMATEX pwfx , DWORD dwCallback , DWORD dwCallbackInstance , DWORD fdwOpen );ウェーブ出力デバイスを開きます phwo - デバイス・ハンドルへのポインタ uDeviceID - 対象の出力デバイスの指定ID pwfx - WAVEFORMATEX 構造体へのポインタ dwCallback - 再生中にウェーブの関連メッセージを受け取る対象を指定します dwCallbackInstance - コールバック関数に渡すユーザ定義データ fdwOpen - デバイスを開くためのフラグを指定します 戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値 fdwOpen には以下のいずれかの値、または組み合わせを指定します WAVE_ に組みあわせることができるのは 1 つの CALLBACK_ だけです
この関数が返すエラー値は、以下の定数のいずれかになります
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 );再生に使う出力バッファをスワップ・アウト(HDDなどへのメモリ退避)させなくする。 hwo - ウェーブ出力デバイスのハンドル pwh - WAVEHDR 構造体へのポインタを指定します cbwh - WAVEHDR 構造体のサイズを指定します 戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値 この関数が返すエラー値は、以下の定数のいずれかになります
waveOutWrite()
MMRESULT waveOutWrite( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );データバッファを指定出力デバイスに送信し、音を鳴らします。 そしてコールバック関数にMM_WOM_OPENメッセージ(ウィンドウ・プロシージャ)またはWOM_OPENメッセージ(コールバック関数)を送ります。 hwo - ウェーブ出力デバイスのハンドルを指定します pwh - WAVEHDR 構造体へのポインタを指定します cbwh - WAVEHDR 構造体のサイズを指定します 戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値 この関数が返すエラー値は、以下の定数のいずれかになります
waveOutReset()
MMRESULT waveOutReset(HWAVEOUT hwo); 再生を停止し、現在位置をリセットします そしてコールバック関数にMM_WOM_OPENメッセージ(ウィンドウ・プロシージャ)またはWOM_OPENメッセージ(コールバック関数)を送ります。 hwo - ウェーブ出力デバイスのハンドルを指定します 戻り値 - 成功すれば MMSYSERR_NOERROR、それ以外の場合はエラー値 この関数が返すエラー値は、以下の定数のいずれかになります
waveOutUnprepareHeader()
MMRESULT waveOutUnprepareHeader( HWAVEOUT hwo , LPWAVEHDR pwh , UINT cbwh );waveOutPrepareHeaderでおこなったスワップ・アウト不可状態を解除します。 hwo - ウェーブ出力デバイスのハンドルを指定します pwh - WAVEHDR 構造体へのポインタを指定します cbwh - WAVEHDR 構造体のサイズを指定します 戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値 この関数が返すエラー値は、以下の定数のいずれかになります
waveOutClose()
MMRESULT waveOutClose(HWAVEOUT hwo);ウェーブ出力デバイスを閉じます hwo - ウェーブフォームオーディを出力デバイスのハンドルを指定します 戻り値 - 成功すれば MMSYSERR_NOERROR、そうでなければエラー値 この関数が返すエラー値は、以下の定数のいずれかになります
|