diff --git a/content/Functional Reactive Programming.md b/content/Functional Reactive Programming.md new file mode 100644 index 00000000..19da0f93 --- /dev/null +++ b/content/Functional Reactive Programming.md @@ -0,0 +1,16 @@ +--- +date: 2024-11-12 14:36 +--- +#programming + +時間変化する信号を取り扱うプログラミングの方法 + +[[Functional Reactive Animation]]という論文で初めて提示された + +ナイーブに実装すると、時間経過するごとに実行コストがどんどん増えていくTime Leakという現象と、メモリが解放されず溜まっていくSpace Leakというのが発生する。 + +(ただ、この辺よくわかってないんだけどこれってHaskellのようなcall-by-needな言語でやるとそうなるってことなのかな?) + + +[[Sodium]] Java用のFRPライブラリ。表示的意味論の設計自体はHaskellで厳密に行っている。 + diff --git a/content/mimiumでMIDIインプットを実装.md b/content/mimiumでMIDIインプットを実装.md index 86217f94..75a67b79 100644 --- a/content/mimiumでMIDIインプットを実装.md +++ b/content/mimiumでMIDIインプットを実装.md @@ -51,7 +51,7 @@ ChuckもボイスごとにShredを生やす方向で対応してるからちょ 現実的には、[[Faust]]のように、ボイスアロケーターは外側で実装してしまい、非同期に更新されうるAtomicな値のセルをノートやccのデータとして受け取れるようにすれば当面は十分 -が、最終的にはMIDIエフェクト(MIDI信号自体のディレイやクォンタイズ、スロットリングとか)を[[FUnctional Reactive Programming|FRP]]っぽく書けると嬉しい +が、最終的にはMIDIエフェクト(MIDI信号自体のディレイやクォンタイズ、スロットリングとか)を[[Functional Reactive Programming|FRP]]っぽく書けると嬉しい --- @@ -114,5 +114,67 @@ fn bind(f1,f2){ } ``` +--- + +### FRPっぽい感じで考えてみる +課題:4ポリのMIDIボイスアロケーターを考える + +アロケーターを実行すると4つのCell(Behavior)が返ってくる +いや、ストリームを返すべき? + +```rust +fn alloc_midi_voice_4(channel)->[Stream;4] +``` + +状態のフィードバックはSodiumでは次の2つを持って実行できる + +- hold: 任意のStreamが発火した時に最後の値をキープしたCellを作る +- snapshot:任意のStreamが発火したとき、Cellをサンプリングして別のStreamとして発火する + +状態の保持として必要なのは、`Busymap([Option;4])`みたいなやつ。 + + +```rust +fn bind_midi_event()->Stream +fn bind_note_event()->Stream<(Channel,Note)>{ + bind_midi_event + |> filter(|byte| byte |> is_note_event ) + |> map(|byte| (byte[0],Note(byte[1],byte[2]) ) ) +} +fn overwrite_arr(idx,v){ + |arr| { + let mut narr = arr; + narr[idx] = v + narr + } +} +fn get_4_voice(note){ + let (last_stream,last_busymap) = self; + if last_busymap |> is_busy{ + (last_stream,last_busymap) + }else{ + match note{ + Note::On(pitch,vel)=>{ + let voice_idx = last_busymap|>find_available_voice; + let new_busymap = last_busymap |> overwritearr(voice_idx,pitch); + let new_str = last_stream |> overwritearr(idx,(pitch,vel)) + } + Note::Off=>{ + + } + } + } +} + +fn alloc_midi_voice_4(channel){ + let busymap = Cell<_>([None,None,None,None]); + + bind_note_event + |> filter(|(c,_note)| c==channel) + |> + +} + +```