--- date: "2023-12-06T03:51:12+0900" --- #programming-language #sound https://github.com/tomoyanonymous/otopoiesis DAWをプログラマブルにする試み ``` #[param("hoge",0..8)] let p1 = 1.0; ``` --- ## 思想 Brandt(2002) の[[Temporal Type Constructor]](以下TTC)という概念を使う。 TTCはジェネリックなタイプ`A`に対して、以下の3つの型コンストラクタを用意することでジェネリックに時間信号を取り扱う思想。 以下はRustの擬似コード。 ```rust type time = Real; //時間に紐づいたイベント。MIDIノートとか struct Event{v:A, t:time} //有限ベクトル。オーディオクリップとか type Vec = std::Vec //無限ベクトル、またはストリーム。1論理時刻毎にA型のものを返す漸化式(内部状態を持つかもしれない) type iVec = BoxA> ``` 例えばMIDIの記録されたデータは ```rust type NOTE= Event<(u8,u8)>//ノート番号、ベロシティ type MIDI = Vec ``` みたいになる ## 構造 基本的なイメージはこんな感じ? ``` type Project = Vec> -> iVec type Track = Device * Device //デバイス情報 *( Vec> | Vec> | Generator ) type Region = (time*time)* //start,duration (Vec // オーディオデータ | Generator | Project) //プロジェクトも再帰的に埋め込める type Generator = iVec ``` なんだけど、TrackAで使われてるGeneratorの中のParameterとしてTrackBの値をアサインしたい、みたいなことを表現できたらプログラミングとして面白くなる、という話 ``` //Freq440Hz,Gain1.0,Phase0.0 let Track1 = Generator::SineWave(Constant(440),Constant(1.0),Constant(0.0)); let Track2 = Generator::SineWave(Track1,Constant(1.0),Constant(0.0)); ``` これをあんまり動的ディスパッチじゃない感じで実装したい。そしてこの辺までは別にMaxとかと同じレベルの話 ここからがDAWをプログラミングで操作できる面白いとこで、例えばリージョンに対するフェードインアウトとかを`Region->Region`の関数として定義できるところ CubaseにおけるインストゥルメントトラックとかはMIDIトラック+シンセサイザーの合成なので、 `Track`に`Vec->iVec