diff --git a/content/mimiumでMIDIインプットを実装.md b/content/mimiumでMIDIインプットを実装.md index b924aa39..731cb40b 100644 --- a/content/mimiumでMIDIインプットを実装.md +++ b/content/mimiumでMIDIインプットを実装.md @@ -122,20 +122,26 @@ MIDIのバイトストリームをフィルターして、ノートオンオフ 最終的にはそれをHoldしてセルにして、セルをsampleして値にすれば良い +ジェネリックなholdの実装をどうするかがキモ + +最終的にはMIDI inにコールバックを登録する形になるから、依存性が逆転する + なんかJSには[[midiguchi]]というライブラリがあるらしい [[Haskell]]には[[Reactive-Banana]]使った[[ReactiveBalsa]]もある ```rust - -fn voice_mono(notes:Stream){ - let cell = notes |> hold({pitch:60,velocity:0}) +let hold = |i|{ + let cell = i + |input| {cell =input, cell} } + let midiinput = midi_open_port("from Max 1"); -let notes = midiinput |> filter_map(_,is_byte_note) -let notes_cell = notes |> voice_mono //ここまでが今のbind_midi_note_monoに相当 +let notes_cell = midiinput + ~> |x|filter_map(x,is_byte_note) + ||> hold(_,{pitch:60,velocity:0}) //ここまでが今のbind_midi_note_monoに相当 fn dsp(){ let {pitch,velocity} = notes_cell |> sample @@ -144,9 +150,13 @@ fn dsp(){ ``` +~>はHaskellの$のような、 a(b(c))を a ~> b~> cで結合弱く描けるようにする + [[Computation Expression]]使ってIOの値を`let!`でバインドしていく、とかの方がわかりやすいかも? -MIDI入力がトリガーになってクロージャのupvalueを書き換えることでCellの中身を書き換えるとなると、現実的にはオーディオスレッドとMIDI(イベント)スレッドを跨いでupvalueを操作することになる。`get_closure_mut`でクロージャをゲットして実行することはできるけど、その時には結局VMがオーディオスレッドにいるから、VMがクロージャ実行予約の命令を受け取るmpscチャネルを持っておいて、予約されたらオーディオブロックの頭で実行する、みたいな感じにする?? +Holdは組み込みの関数で、ArcSwapで包まれた値のセルを保持する -Arcでupvalueを全部包んで、closed upvalueの中身をAtomicU64にする、みたいな方法もあるにはあるが、そうするとClosureのストレージはVMそのものというよりもVMインスタンス間で共有される感じになるのかな +グローバル関数はメインスレッドで実行されて、クロージャIDを渡す + +とはいえVMインスタンスがオーディオスレッドに渡ってしまうとなるとな diff --git a/content/private b/content/private index 1c5c1828..b7b2247f 160000 --- a/content/private +++ b/content/private @@ -1 +1 @@ -Subproject commit 1c5c182873d4cbf3a927e676791cd33e9ad53896 +Subproject commit b7b2247f3903d6f4debd5a512bde9c73624425e6