From c14078fe8df483ea3496b0258b93f6bf5b509112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=BE=E6=B5=A6=20=E7=9F=A5=E4=B9=9F=20Matsuura=20Tomoy?= =?UTF-8?q?a?= Date: Tue, 12 Nov 2024 15:22:04 +0900 Subject: [PATCH] [obsidian] vault backup: 2024-11-12 15:22:04[ --- content/Functional Reactive Programming.md | 16 ++++++ content/mimiumでMIDIインプットを実装.md | 64 +++++++++++++++++++++- 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 content/Functional Reactive Programming.md 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) + |> + +} + +```