Compare commits

...

2 Commits

Author SHA1 Message Date
9ea4fec06c [obsidian] vault backup: 2024-11-12 16:59:44[
All checks were successful
Build / build (push) Successful in 3m59s
2024-11-12 16:59:44 +09:00
c14078fe8d [obsidian] vault backup: 2024-11-12 15:22:04[ 2024-11-12 15:22:04 +09:00
2 changed files with 81 additions and 1 deletions

View File

@ -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で厳密に行っている。

View File

@ -51,7 +51,7 @@ ChuckもボイスごとにShredを生やす方向で対応してるからちょ
現実的には、[[Faust]]のように、ボイスアロケーターは外側で実装してしまい、非同期に更新されうるAtomicな値のセルをートやccのデータとして受け取れるようにすれば当面は十分
が、最終的にはMIDIエフェクトMIDI信号自体のディレイやクォンタイズ、スロットリングとかを[[FUnctional Reactive Programming|FRP]]っぽく書けると嬉しい
が、最終的にはMIDIエフェクトMIDI信号自体のディレイやクォンタイズ、スロットリングとかを[[Functional Reactive Programming|FRP]]っぽく書けると嬉しい
---
@ -114,5 +114,69 @@ 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
} )
}
```