• ベストアンサー

waveIn、waveOutでの音声録音・再生プログラミングを作成して

waveIn、waveOutでの音声録音・再生プログラミングを作成しています。 内容は、マルチバッファリング機能で音声の取り込みを行い、同時にファイルへの書き込みと、スピーカーへの出力をするのですが、当然waveInで取り込み後にwaveOutするので、元の音声とずれて音がスピーカーへ出力されます。 WAVEFORMATEX構造体のメンバには秒単位での設定値であるため、最小1秒のずれが計算上でます。実際のズレは1秒も無いですが、かなり気になります。 同様の機能のフリーソフトでは、若干のズレはあってもこのプログラムほどではありません。どのようにすれば、このズレを少なく出来るのでしょうか。 どなたか、ご教示願いたくお願いします。

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

  • ベストアンサー
  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.2

> (wf.nAvgBytesPerSec=wf.nSamplesPerSec * wf.nBlockAlign / 10;) それはやったらダメです。 これは「ファイルフォーマット」を指定するものですので、入出力のバッファサイズ(処理時間単位)とは関係なく、常に 1秒あたりのバイト数=1秒あたりのサンプル数×1サンプルあたりのバイト数 でなければなりません。必ず wf.nAvgBytesPerSec=wf.nSamplesPerSec * wf.nBlockAlign; にする必要があります。 その上で、PrepareFormat 時の WAVEHDR で指定する dwBufferLengthを、バッファしたい秒数にあわせて、nAvgBytesPerSecの1/10のサイズにしたりする、 といったことになります。

oppenheimer
質問者

お礼

ご指摘ありがとうございます。 dwBufferLength = wf.nAvgBytesPerSec / 10; ですかね。これで出力したwavファイルも再生できました。 ご教示感謝いたします。

その他の回答 (1)

  • mtaka2
  • ベストアンサー率73% (867/1179)
回答No.1

> WAVEFORMATEX構造体のメンバには秒単位での設定値 そんなことはありません。 WAVEFORMATEX の各パラメータは「1秒あたりのデータ量」という「スペック」を指定するものであり、 実際にwaveIn/waveOutするデータ量は1秒単位である必然性はありません。 waveInPrepareHeader/waveOutPrepareHeader 時の WAVEHDR 構造体内の dwBufferLength で、 入出力するデータ量を指定していますが、これは WAVEFORMATEX のnBlockAlignの倍数であればいくらでも構いません。 たとえば、44.1kHz 16bit ステレオなら、nSamplesPerSecは44100、nBlockAlign は 4 になりますが、 176400(=44100*4)バイトのバッファを用意・指定すれば、1秒単位の入出力になりますが、 17640バイトを指定すれば0.1秒単位に、1764バイトのバッファなら0.01秒単位になります。 サイズを小さくすると、それだけタイムラグは小さくなりますが、 その代わりに、入出力処理を行う回数が増えて負荷が重くなりますし、あまりに短すぎると 処理が間に合わずに音飛びしたりする可能性もあります。どの位のサイズがちょうど良いかはプログラム次第です。 (複数のバッファをPrepareHeader しておけば、「たまたまギリギリ間に合わなかった」場合の音飛びは防ぐことができますが、その場合でも平均的にはバッファのPrepareが十分間に合っている必要があり、 「根本的に処理が追いつかない」場合の音飛びには対処できません。そういう場合は、バッファサイズを大きくするしかないです)

oppenheimer
質問者

お礼

早速のご回答ありがとうございます。 >実際にwaveIn/waveOutするデータ量は1秒単位である必然性はありません。 そうでしたか。試しに1/10で録音再生したところ、同時再生でのズレは気にならないぐらいになりました。 (wf.nAvgBytesPerSec=wf.nSamplesPerSec * wf.nBlockAlign / 10;) ただ、出力したファイルでの再生が出来なくなってしまったので、こちらは少し汗をかいてみます。 ありがとうございました。

関連するQ&A