2

私は反応バナナを使い始めようとしていて、簡単なシンセサイザーを作りたいと思っています。GUI の例はたくさんありますが、オーディオに適用するのは難しいです。オーディオ API には「n 個のオーディオ サンプルを与えてください」というコールバックがあるので、コールバックごとに (newAddHandler が返すものの snd 部分を使用して) イベントを起動する必要があると考えます。 、および MIDI イベントを調整するためのタイミング情報。その後、再活性化に渡された IO アクションは、サンプルをポインターに書き込みます。MIDI イベントは、別のコールバックから同様に起動され、タイミング情報も含まれます。

しかし、これは私が立ち往生するところです。オーディオ信号は動作であると思われますが、サンプルを取得するために適切な時間だけ動作を「実行」するにはどうすればよいですか? もちろん、適切な量は、2 つのオーディオ コールバック間で発生する可能性のある MIDI イベントによって異なります。

4

2 に答える 2

2

意図がライブで何かを行うことであると仮定すると、コールバックごとにイベントを発生させることは非常に制限されると思います。ほとんどのオーディオ API は、これらのコールバックが非常に迅速に返されることを期待しています (たとえば、通常、malloc を呼び出したり、ブロッキング IO を 1 つで実行したりすることはありません)。FRP イベントを発生させると、非常に単純な処理でうまくいくかもしれませんが、もっと複雑なことをしようとすると、オーディオ ストリームでドロップアウトが発生すると思います。

より実行可能なアプローチは、イベントを自分で (クロックによって、または GUI イベントへの応答などで) 発生させ、オーディオのバッファーを生成し、そのバッファーからコールバック API を読み取ることだと思います。一部のオーディオ API (portaudio など) には、これらの一部を自動的に処理するバッファー モードがあることを知っています。コールバック API しかない場合でも、その上にバッファーを追加するのはそれほど難しくありません。

于 2014-02-15T18:30:21.663 に答える
1

このような問題にアプローチするには、セマンティックな視点を取ることが役立つと思います: オーディオ信号とは? それを表すためにどのタイプを使用できますか?

基本的に、オーディオ信号は時変振幅です

Audio = Time -> Double

これは、行動としての表現を示唆しています

type Audio = Behavior Double

次に、<@>コンビネータを使用して、特定の瞬間、つまりイベントが発生したときの振幅を照会できます。

ただし、効率上の理由から、オーディオ データは一般に 64 バイト (または 128、256) のブロックに格納されます。結局、処理は高速である必要があり、タイトな内部ループを使用することが重要です。これは、音声データを動作としてモデル化することを示唆しています

type Audio = Behavior (Vector Double)

その値はオーディオ データの 64 バイト ブロックであり、64 バイトに対応する期間が終了するたびに変化します。

他の API への接続は、セマンティック モデルが明確になった後にのみ行われます。この場合、ビヘイビアーからのオーディオ データをバッファーに書き込むことをお勧めします。このバッファーの内容は、外部 API がコールバックを呼び出すたびに表示されます。


ところで、reactive-banana-0.8 がサンプル レベルのオーディオ処理に役立つほど十分に高速であるかどうかはわかりません。それほど悪くはありませんが、かなり大きなブロック サイズを選択する必要がある場合があります。

于 2014-02-19T13:57:11.760 に答える