• ベストアンサー

スレッドのテスト

現在、音声の転送プログラムを作成中なのですが、その中でスレッドを使いたく勉強するためにテストプログラムを作ったのですが、うまく動作しません。 そのソースファイルです(C言語です) http://www.h7.dion.ne.jp/~ishix3/prog.htm ドレミファソラシドと再生したいのですが、一瞬だけ「ド」が再生されそれに続いて再生してくれません。 どこが悪いのでしょうか?どなたか教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.1

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpmltimd/html/_win32_waveoutunprepareheader.asp ここを良く読んで。 「waveOutWrite 関数でデバイスドライバにバッファを渡した後、waveOutUnprepareHeader 関数を呼び出す前に、デバイスドライバがバッファでの作業を完了するまで待たなければなりません。」 と書いてあります。つまり 「waveOutWrite 関数を呼ぶとバッファがサウンドデバイスに送られる。サウンドデバイスが再生状態であれば(一時停止状態でなければ)音声が再生される。アプリケーションはデバイスの再生が終るのを待ってwaveOutUnprepareHeader 関数で後始末を行う」 と言う事です。 質問者さんは「デバイスの再生が終るのを待って」いませんので、 「ドをセットしてドが鳴ると同時にバッファを破棄して、レをセットしてデバイスに送った瞬間にバッファを破棄して、ミをセット(以下略)」 と言う状態になります。 まずは、スレッドを作らず、ドレミファソラシドがちゃんと鳴るようにしてから、スレッド作成を試みましょう。 まずは、waveOutOpen 関数のdwCallbackにコールバック関数を、dwCallbackInstanceにインスタンスを、fdwOpenにCALLBACK_FUNCTIONを指定しての「音声再生の制御」を成功させて下さい。 waveOutOpen 関数のfdwOpenにCALLBACK_WINDOWを指定していては、スレッドでの制御が出来ません(再生終了のイベントがウィンドゥに返されるので、メインのWndProcで処理する事になり、スレッドを作る意味がない) スレッドで処理するなら ・メインスレッドで初期化のみ行ったら子スレッドを作る。初期化の時と再生終了メッセージが来た時は、PLAYボタンをイネーブルし、STOPボタンをディセーブルする ・PLAYボタンはスレッドに対してイベントを使って再生をキックする。そして、PLAYボタンをディセーブルし、STOPボタンをイネーブルする ・STOPボタンは、waveOutResetなりを呼んで、後始末して、PLAYボタンをイネーブルし、STOPボタンをディセーブルする ・子スレッドは、イベントハンドラがアクティブになるまでwaitし、イベントがアクティブになったら、イベントを非アクティブにして音声再生する ・音声再生する時は、コールバック関数を指定してwaveOutOpenする ・waveOutOpenで指定したコールバック関数で、鳴り終わったフラグが立ってコールバックされたら、後始末をして、バッファを次の音に更新して、スレッドに対してイベントを使って再生をキックする。次の音が無ければ、メインスレッドに対しメッセージを投げて終ったのを通知する と言う処理になります。 先は長いけど頑張って。

iship-
質問者

お礼

回答ありがとうございます。 すごく理解できました。 がんばります。

関連するQ&A