Files
quartz-research-note/content/mimiumでのIOパラメーター.md
松浦 知也 Matsuura Tomoya 61c062531e
All checks were successful
Build / build (push) Successful in 7m26s
[obsidian] vault backup: 2025-08-18 12:10:15[
2025-08-18 12:10:15 +09:00

143 lines
5.0 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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-07-01 18:43
---
#mimium
マルチスレッド前提の場合、Shared State全般がRwLockとかで包まれることになってしまう
しかし、大概の場合グローバルな状態共有はAtomicな単一パラメーターで済む
あくまで、普通のグローバル変数宣言はスレッドローカルな扱いにして、メインスレッドと協調しないといけない場合は"shared"みたいなキーワードをつけるようにするとか(構文増やしたくないけど)
だし、これだと結局OSC送るサーバークライアント構成と実質的に変わらないかも
```rust
let hoge = 100;
```
みたいなのの代わりに、別のキーワードを持たせる
```rust
global hoge = 100
```
プリミティブな型であれば、Atomicな書き換えでOK。hogeへの書き込みをオーディオコンテキストの中でやると毎サンプル実行される保証がない、みたいな仕様
タプルとか合成型だと、マルチスレッドで書き換えたときに片方のパラメーターが更新されてない時に読み取られる可能性が厳密にはある
グローバルに宣言された配列型とか、合成型をどうやって扱う?
単に、グローバルな値への書き込みがいつ行われるか保証はされませんよ、という仕様にするならそれでも十分か
もしくは、
```rust
let hoge = param(100)
```
みたいなラップの仕方を考える。hogeは`Param<Number>`型をもち、Number型に自動キャストできる。
パラメトリックフィルタ複製で、個々の周波数を外側からコントロールしたいとするとどうなるか
```rust
fn replicate(n,gen){
let g = gen(n, n*100)
if (n>0.0){
let c = replicate(n - 1.0,gen)
| | g() + c()
}else{
| | g()
}
}
fn mygen(freq){
osc(freq)
}
fn gen(n,init_f){
let channel = param("freq_%n",init_f);
| | mygen(channel)
}
let myfilter = replicate(5,gen)
fn dsp(){
myfilter()
}
```
まあこうなるか 自動グループ化みたいなのできるか?実行してる関数の深さ的に`global::replicate::gen::(args)`で自動ネーミング自体は不可能ではなさそうだが/自動グループをやりたければ、`Param<T>`の中身をレコード型にすればいいのか
paramがジェネリックな関数`T->Param<T>`であることが重要になってくる。範囲の制限とかはRanged型みたいなのをmimium側で定義すればよくなる・・・はずまあIO周りは結局命令型になるのかなあ
```rust
let channel = param("freq_%n",init_f);
set_param("freq_%n",1000.0)
channel = 1000;//
```
最後の行のように、普通にAssign書き込むのもできるようにしておきたい。これできるようにするには、Assignをオーバーロードできるような型システムが必要なのかな`param(コンストラクタ)``get_param_name``get_param``set_param`の4種類があれば十分か
## ParamよりControllerの方が良くないか
Parameterは単に関数の引数という意味合いにもとれてしまう
Inputだとプログラムの入力という意味は伝わりやすいが、オーディオインプットとの区別がつきづらくなってしまう
ので、Controllerがわかりやすいかもしれない
## [[mimiumのレコード型]]の実装と組み合わせる
デフォルト実装、関数のデフォルト引数の組み合わせに対して自動でパラメーターが作られるようにしたい
```rust
//自動キャストとジェネリクスの組み合わせさえうまくいけばこのくらいのことはできそう
let p = controller({..});
fn dsp(){
p |>
|gate = 0,freq = 1000,gain = 1.0|{
...//do something
}
}
```
これを実行すると、隠れレコード構造体定義とグローバルなデフォルト引数が作られる
```rust
...
type defaultarg = {
gate:number = 0,
freq:number = 1000,
gain:number = 1.0
}
let p = param(defaultarg::default());//p is higher order function
fn dsp(){
mysynth(p())
}
```
dsp内で`mysynth({..})`と実行してしまうと、これがグローバルなコンテキストで作られない可能性がある・・のか?いや、でも基本的に書き換えられる心配はないからいいのかな
デフォルト引数構造体のインスタンスは必ずグローバル評価で行う、だとパラメトリックな生成はできないし問題起きそう
## [[mimiumの多段階計算]]と組み合わせる
`controller`関数がジェネリックな`Code`型を返す関数であれば、関数内に直接埋め込むこともできそう
```rust
//これが
fn dsp(){
controller!({..})
|> |gate = 0,freq = 1000,gain = 1.0|{
...//do something
}
}
//こう展開される(本当にジェネリックにできるかは要検討)
fn dsp(){
__get_generated_controller_value(uuid)
|> |gate = 0,freq = 1000,gain = 1.0|{
...//do something
}
}
```