Compare commits
No commits in common. "9ea4fec06c1b84194cfed82126ebed1b893c5077" and "8283dd0d8336f3cf144c2b08fd954824044dbc22" have entirely different histories.
9ea4fec06c
...
8283dd0d83
@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
date: 2024-11-12 14:36
|
|
||||||
---
|
|
||||||
#programming
|
|
||||||
|
|
||||||
時間変化する信号を取り扱うプログラミングの方法
|
|
||||||
|
|
||||||
[[Functional Reactive Animation]]という論文で初めて提示された
|
|
||||||
|
|
||||||
ナイーブに実装すると、時間経過するごとに実行コストがどんどん増えていくTime Leakという現象と、メモリが解放されず溜まっていくSpace Leakというのが発生する。
|
|
||||||
|
|
||||||
(ただ、この辺よくわかってないんだけどこれってHaskellのようなcall-by-needな言語でやるとそうなるってことなのかな?)
|
|
||||||
|
|
||||||
|
|
||||||
[[Sodium]] Java用のFRPライブラリ。表示的意味論の設計自体はHaskellで厳密に行っている。
|
|
||||||
|
|
@ -51,7 +51,7 @@ ChuckもボイスごとにShredを生やす方向で対応してるからちょ
|
|||||||
|
|
||||||
現実的には、[[Faust]]のように、ボイスアロケーターは外側で実装してしまい、非同期に更新されうるAtomicな値のセルをノートやccのデータとして受け取れるようにすれば当面は十分
|
現実的には、[[Faust]]のように、ボイスアロケーターは外側で実装してしまい、非同期に更新されうるAtomicな値のセルをノートやccのデータとして受け取れるようにすれば当面は十分
|
||||||
|
|
||||||
が、最終的にはMIDIエフェクト(MIDI信号自体のディレイやクォンタイズ、スロットリングとか)を[[Functional Reactive Programming|FRP]]っぽく書けると嬉しい
|
が、最終的にはMIDIエフェクト(MIDI信号自体のディレイやクォンタイズ、スロットリングとか)を[[FUnctional Reactive Programming|FRP]]っぽく書けると嬉しい
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -114,69 +114,5 @@ fn bind(f1,f2){
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### FRPっぽい感じで考えてみる
|
|
||||||
|
|
||||||
|
|
||||||
課題:4ポリのMIDIボイスアロケーターを考える
|
|
||||||
|
|
||||||
アロケーターを実行すると4つのCell(Behavior)が返ってくる
|
|
||||||
いや、ストリームを返すべき?
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn alloc_midi_voice_4(channel)->[Stream<Note>;4]
|
|
||||||
```
|
|
||||||
|
|
||||||
状態のフィードバックはSodiumでは次の2つを持って実行できる
|
|
||||||
|
|
||||||
- hold: 任意のStreamが発火した時に最後の値をキープしたCellを作る
|
|
||||||
- snapshot:任意のStreamが発火したとき、Cellをサンプリングして別のStreamとして発火する
|
|
||||||
|
|
||||||
状態の保持として必要なのは、`Busymap([Option<Key>;4])`みたいなやつ。
|
|
||||||
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn bind_midi_event()->Stream<Byte>
|
|
||||||
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)
|
|
||||||
|> merge(busymap |> snapshot, |(note,busycell)| {
|
|
||||||
busycell.hold
|
|
||||||
} )
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
Loading…
Reference in New Issue
Block a user