Files
quartz-research-note/content/mimiumでのライブコーディングエンジン.md
松浦 知也 Matsuura Tomoya f08ff8368c
All checks were successful
Build / build (push) Successful in 12m37s
[obsidian] vault backup: 2025-09-23 01:39:19[
2025-09-23 01:39:19 +09:00

103 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
date: 2025-06-27 16:54
---
#mimium #livecoding
mimiumでも[[ライブコーディング]]がやりたいよね
一般化するとこういうモデルにならんだろうか
![[img/general-livecoding-model.png]]
Tracksの部分の抜き差しだけできるのが[[ChucK]]のShredシステム。
とりあえずはこれをRust実装してもいいけど、最終的にはこのモデル自体をmimium上で実装することもできそう
不要なトラックの削除と空きスロット再利用を実現するためには、普通の配列とは別に単方向リストかSlotmap的なものを作る必要がありそう
Reducerは基本的には全てのチャンネルの加算だけでいいので滅多にいじる必要ないけど、いじりたいケースが出てくるかも
ChucKではエフェクトのテールが更新時にぶちぎれる問題があったので、それを防ぐためのPostFX Chain
各トラックごとのエフェクトのライブ切り替えとかも実現しようと思えばできるかな
...これ、結局[[SuperCollider]]のJITLibと同じことかもな
[jitlib\_basic\_concepts\_01 \| SuperCollider 3.14.0-dev Help](https://doc.sccode.org/Tutorials/JITLib/jitlib_basic_concepts_01.html)
## 信号処理の状態持ち越し
[[Incremental Functional Reactive Programming]]の仕組みを用いることはできるだろうか
```rust
//これが
fn dsp(){
delay(100,100,input)+ delay(200,200,input)
}
//こう更新されるとする
fn dsp(){
delay(300,300,input) + delay(100,100,input)+ delay(200,200,input)
}
```
`delay(100)`にはID(delay_1)が、`delay(200)`にはID(delay_2)がそれぞれつけられる
どう増分検出してID割り振るかの仕組みは置いといて、再コンパイル時に100と200はそのまま、新しく増えたdelay(300)にID`(delay_3)`を挿入する
そうすると、StateStackのためのメモリは完全にリニアにはしないほうが良くて、ツリー状のデータ構造に戻した方が良さそう
[[Red Green Syntax Tree]]のGreen Node→状態メモリのマップだと考えるとわかりやすいのか
```
dsp
| \
delay(1) delay(2)
```
から
```
dsp
/ | \
delay(3)delay(1) delay(2)
```
に更新される
```rust
struct MemoryChunk(Vec<u64>>);
enum StateNode{
FnCall(Symbol,StateTree),//非クロージャ関数呼び出し
Delay(MemoryChunk),
FeedBack(MemoryChunk),
}
struct StateTree{
children: SlotMap<Box<StateNode>>
}
```
関数呼び出しは非クロージャなのでシンボル名は確定できる
途中でchildrenの一部が削除される可能性がある(1,2,3,4の中から2だけが削除されるケースとか)
このchildren同士の構造比較はどうするべきかDelay、Feedbackは
かつiterateも行うのでSlotmapで良さそう
Delay、feedback、Externalを区別する意味はあるのか→たまたまサイズが同じなDelayとExternalとかはあり得るので区別必要
クロージャの呼び出しの時は→コンパイル時ではなく、Closure命令でクロージャが作られる際にアロケートとIDの振り分けが起きる これは諦めて良さそう(適切にやりたければ[[多段階計算]]でコンパイル時に頑張れ)
あとはIDの振り方問題。dspから順番にnon-closure-callをトレースするのは同じとして
```rust
fn update_state_tree(oldtree:StateTree,newtree)->StateTree{
let state_changed = oldtree.children.iter().zip(newtree.children.iter()).all(|oldc,newc|newc == oldc)
}
```