Files
quartz-research-note/content/mimiumでのIOパラメーター.md
松浦 知也 Matsuura Tomoya 01d5fbac96
All checks were successful
Build / build (push) Successful in 11m37s
[obsidian] vault backup: 2025-07-01 23:06:05[
2025-07-01 23:06:05 +09:00

129 lines
4.3 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-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種類があれば十分か
[[mimiumのレコード型]]のデフォルト実装、関数のデフォルト引数の組み合わせに対して自動でパラメーターが作られるようにしたい
```rust
fn gen_synthesizer(){
let s = |gate = 0,freq=1000,gain = 1.0|{
...
}
s({..})
}
let mysynth = gen_synthesizer();
fn dsp(){
mysynth()
}
```
これを実行すると、隠れレコード構造体定義とグローバルなデフォルト引数が作られる
```rust
...
type defaultarg = {
"gate":number = 0,
"freq":number = 1000,
"gain":number = 1.0
}
let default_arg_for_mysynth = param("mysynth",defaultarg::default());
fn dsp(){
mysynth()
}
```
dsp内で`mysynth({..})`と実行してしまうと、これがグローバルなコンテキストで作られない可能性がある・・のか?いや、でも基本的に書き換えられる心配はないからいいのかな
デフォルト引数構造体のインスタンスは必ずグローバル評価で行う、だとパラメトリックな生成はできないし問題起きそう
```rust
//自動キャストとジェネリクスの組み合わせさえうまくいけばこのくらいのことはできそう
let p = param({..});
fn dsp(){
p |>
|gate = 0,freq = 1000,gain = 1.0|{
...//do something
}
}
```
ということは、とりあえず雑にParamを実装して