diff --git a/content/FRP.md b/content/FRP.md new file mode 100644 index 00000000..a1299d64 --- /dev/null +++ b/content/FRP.md @@ -0,0 +1,6 @@ +--- +date: 2025-10-13 11:04 +--- +#alias + +[[Functional Reactive Programming]] diff --git a/content/ReactiveBalsa.md b/content/ReactiveBalsa.md new file mode 100644 index 00000000..a0604f8a --- /dev/null +++ b/content/ReactiveBalsa.md @@ -0,0 +1,7 @@ +--- +date: 2025-10-13 11:07 +--- + +[[Haskell]]の[[MIDI]]を[[FRP]]風に扱うライブラリ + +[Reactive-balsa - HaskellWiki](https://wiki.haskell.org/Reactive-balsa) diff --git a/content/midiguchi.md b/content/midiguchi.md new file mode 100644 index 00000000..20d37333 --- /dev/null +++ b/content/midiguchi.md @@ -0,0 +1,11 @@ +--- +date: 2025-10-13 11:04 +--- +#programming + +[[MIDI]]を[[FRP]]っぽくバインドするための[[JavaScript]]ライブラリ(古い) + + +[GitHub - midiguchi/midiguchi: midiguchi - MIDI I/O using Functional Reactive Programming with Bacon.js. Transpose, remap, filter, manipulate arbitrarily, or synthesize MIDI events with ease.](https://github.com/midiguchi/midiguchi) + + diff --git a/content/mimiumでMIDIインプットを実装.md b/content/mimiumでMIDIインプットを実装.md index de49a699..e3fa04d3 100644 --- a/content/mimiumでMIDIインプットを実装.md +++ b/content/mimiumでMIDIインプットを実装.md @@ -118,92 +118,41 @@ fn bind(f1,f2){ ### FRPっぽい感じで考えてみる +MIDIのバイトストリームをフィルターして、ノートオンオフのストリームを作る -課題:4ポリのMIDIボイスアロケーターを考える +最終的にはそれをHoldしてセルにして、セルをsampleして値にすれば良い -アロケーターを実行すると4つのCell(Behavior)が返ってくる -いや、ストリームを返すべき? +なんかJSには[[midiguchi]]というライブラリがあるらしい -```rust -fn alloc_midi_voice_4(channel)->[Stream;4] -``` - -状態のフィードバックはSodiumでは次の2つを持って実行できる - -- hold: 任意のStreamが発火した時に最後の値をキープしたCellを作る -- snapshot:任意のStreamが発火したとき、Cellをサンプリングして別のStreamとして発火する - -状態の保持として必要なのは、`Busymap([Option;4])`みたいなやつ。 +[[Haskell]]には[[Reactive-Banana]]使った[[ReactiveBalsa]]もある ```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 voice_mono(notes:Stream){ + let cell = notes |> hold({pitch:60,velocity:0}) } -fn alloc_midi_voice_4(channel){ - let busymap = Cell<_>([None,None,None,None]); - - bind_note_event - |> filter(|(c,_note)| c==channel) - |> merge(busymap |> snapshot, |(note,busycell)| { - busycell.hold - } ) +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に相当 +fn dsp(){ + let {pitch,velocity} = notes_cell |> sample + pitch |> midi2freq |> osc |> _ * velocty/127 } ``` +[[Computation Expression]]使ってIOの値を`let!`でバインドしていく、とかの方がわかりやすいかも? -[[Computation Expression]]使ってIOの値を`let!`でバインドしていく、とかの方がわかりやすいかも - - ---- - - -シンプルに、MIDIにコールバックを渡せるだけなら、どうやって作る? +## MIDIディレイとかどうすんの ```rust - -fn __midi_note_callback(cb:{pitch:float,vel:float}->void ){ - -} - -fn poly_midi_allocator()->()->[{pitch:float,vel:float}]{ - let channels = array_new({pitch=0,vel=0},4) - let busymap = [0,0,0,0] - __midi_note_callback(|pitch,vel| { - - }) - channels//セルをupvalueとして返す +fn delay(stream:Stream,time:float){ + stream@(now+float) } ``` +