「バッファリング」を考える
今回の「バッファリング」というのは、
波形をバッファに書き込んで、
再生用キューに波形をぶちこむまでのこと。
ちょっとFMが重過ぎる(涙)ので
バッファリング方式(?)を変えてみようかと。
で、文章だけだと極めて意味不明になりそうなので、
・「書き込み用のバッファ」 → 「コップ」
・「再生用キュー」 → 「底に穴の開いたドラム缶」
みたいな感じで
(微妙な)比喩っぽい図(?)を交えていこうかと。
↑こんな感じで。
今回の場合は、
・「音(波形データ)」 → 「水」
・「音が鳴る」 → 「ドラム缶の底から水が漏れる」
ということになるんですが…、
細かい所をすっ飛ばして(何)
実際に使うとなるとどういう感じになるかというと、
・「コップに水を注ぐ」(バッファに波形を書き込む)
・「コップの水をドラム缶に移す」(waveOutWrite()で再生用キューに放り込む)
・「水がこぼれる」(音が鳴る)
というわけで、↑のようになると。
ちなみに、
キュー(ドラム缶)が一瞬でも空の状態になってしまうと、
いわゆる「音飛び」が発生します。
これがアバウトな
「鳴らし方」
になります。
で、ここからが本題。
現状のバッファリングはどうしているかというと、
各バッファ毎に一定量分だけ確保しておき、
必要になったら次々キューに放り込む。
というもの。
こんな感じで。
「一定量」の部分はテンポ等で変動します。
この方法のいい所は何と言っても
「実装が楽」
であること。
少し待つ → 書き込む → 少し待つ ...
を繰り返すだけでOK。
そのかわり、見てわかる通り
「保持しておけるデータ量が少ない」
のが大きな欠点。
特にMIDI並みの精度を求めようとすると、
バッファx1あたりのデータ量は
本当に雀の涙ほどの極めて少ない量になってしまうので
音飛びの危険性が増大してしまいます。
これに対し、新規に実装しようとしている方法は
各バッファ毎満タンになるまで書き込み*1、
満タンになり次第、キューに放り込んでいく。
というもの。
こんな感じで。
…何と言うか、SDLのサウンド系も多分この手法。
この方法のウリは
「音飛びの少なさ」と「安定した動作速度」の二点。
図の通りバッファをフルに使うので、
多くのデータが保持できるだけでなく、
書き込みにも余裕が出来るので、
頻繁に書き込む必要がなくなって、
そっちに処理を持っていかれずに済む。
…という、何か一見するとPERFECTな方法。
ただ、一応欠点も存在して、
「実装が若干面倒」
だったりする。
例えば、
↑のように中途半端に余剰がある場合。
この場合は
↑のように分割して書き込む必要があるし、
それ以前に、
そもそもキューに放り込むタイミングが
書き込み処理のフレームと一致しているとも限らないので、
キューに放り込むタイミングを計る必要性も出てくる。
上記の中途書き込みの場合の
余剰を書き込む余地がない(ややこしい…(苦笑))場合
も考える必要がある。
………まぁ、面倒ですよ…と(汗)
後、多分サウンドボードによると思うんだけど、
キューに放り込むバッファのサイズや数によって
実際に再生されるまでにラグが生じることがあるみたい。
もちろん、大きかったり多かったりする方が
ラグが発生する確率は高いので、
これに関しては現状の方が有利だったり。
後(再度)、現状の用途だと
比較的どうでもいいことだけど、
「リアルタイムな入力への反応の良さ」
何かも現状の方がいい(はず)。
…と言っても、コレに関しては
保持できるバッファサイズが直接影響していて、
「音飛び」とのトレードオフになるので何とも言えませんが…。
…で、大体書き終わったので両方の長所と短所をまとめてみる。
>>>>現状
・実装が簡素
---「フレームと同期」
「テンポ変更が容易」等
・リアルタイム入力との相性がいい(*2)
・キューに放り込んでからのラグはまず発生しない(*1)
※音飛びが(やや)発生しやすい
---保持可能データ量が少ないため
※動作速度がやや不安定
>>>>新規
(*1 … ハードウェア系の相性もあるかも)
・音飛びの心配がほとんどない
---保持可能なデータ量が安定しているため
・動作速度が安定している
※実装が面倒
---「フレーム制との相性が悪い」
「中途書き込み時の余剰の心配」等
※リアルタイム入力の際に(多分)遅延がある(*2)
※キューに放り込んでから
実際になるまでに多少ラグが発生することが…。(*1)
(*2 … 現在では全く意味無し)
…んー、やっぱり、新規の方がいい…かなぁ…。
…いやま、一応試作版は作ったんだけど、
何故かゴミが入るんですよ。
丁度SDL版と同じ感じで
バッファ幾つかごとに1〜3サンプル分だけ。
…何なんだろうな…。
……後、何かものすごい不安定…(苦笑)
*1:書き込み終わるまでは、そのバッファは使用不可。