ライブコーディング

ライブコーディング #

mimium v3では、オーディオを途切れさせることなく実行中にコードを変更できる画期的なライブコーディング機能を導入しています。

概要 #

従来のオーディオプログラミング環境では、コードを変更した場合、オーディオ処理を停止して再起動する必要がありました。しかし、mimium v3のライブコーディング機能では、以下のようなことが可能です:

  • 音の途切れなし: ディレイのテールやリバーブが自然に続きます
  • 内部状態の保持: フィードバックループや自己発振システムが継続します
  • リアルタイム編集: パラメータや構造をリアルタイムで変更できます

この機能により、mimiumは非常に低レイヤーなDSPのコーディングを聴感上違和感なくライブコーディングすることができる、数ある音楽プログラミング言語の中でも唯一無二といっても良い機能を獲得しました。

仕組み #

多段階計算による基盤 #

多段階計算の導入により、ほとんどの信号処理での必要なメモリレイアウトはコンパイル時に決定できるようになりました。dsp関数からの関数コール、ディレイ呼び出し、selfの使用などを静的解析することにより、ソースコードに変更を加えてもディレイやフィードバックの内部状態を可能な限り保つように動作します。

更新プロセス #

新しいmimium-cliでは、変更されたmimiumファイルを上書き保存すると、ファイル変更を自動検知して以下のステップでDSPを更新します:

  1. 再コンパイル: コンパイラがワーカースレッドでコードを再コンパイル
  2. VM比較: 新しいプログラムが実行中のVMのプログラムと比較される
  3. 状態ツリー構築: 内部状態(ディレイ、フィードバックなど)のツリーを作成し、構造で変化がない部分を抽出して新しいVMの内部状態メモリを作成
  4. シームレス切り替え: オーディオスレッドで新しいVMにシームレスに切り替わる

独自のアプローチ #

mimium v3のライブコーディングは、ライブコーディング的な機能でありつつも、毎回ソースコードを丸ごとコンパイルし直して新しいバイトコードとVMインスタンスを生成しつつ音を途切れさせないという、独特の方式をとっています。

これにより、ディレイのテールやリバーブが再評価時にも自然に続き、音楽的な連続性が保たれます。

また全ての構文木を比較する必要がなく、単に定数を変更した場合など、内部状態ツリー構造に変化がない場合は単にメモリを丸ごとコピーするだけでよくなります。

さらに、多段階計算でオシレータを複製するような、マクロへの引数でのコンパイル時定数を編集する際のオーディオグラフの変化にさえ自然に追従できます。

使用例 #

基本的な例 #

初期コード:

fn dsp() {
  let freq = 440.0
  sin(phasor(freq) * 3.14159 * 2.0)
}

実行中の変更:

fn dsp() {
  let freq = 880.0  // 編集して保存するだけ - 再起動不要
  sin(phasor(freq) * 3.14159 * 2.0)
}

より複雑な変更 #

以下のような変更も音を途切れさせることなく可能です。

  • 新しいオシレータの追加
  • フィルタパラメータの変更
  • ディレイタイムの変更
  • オーディオグラフの再構築
  • モジュレーションなどさらなる内部状態を持つ処理の追加

マクロを使った構造変化 #

#stage(macro)
fn oscillator_bank(n) {
  if (n > 0) {
    `{ sinwave(440.0 * $(n|>lift_f), 0.0) + oscillator_bank!(n-1) }
  } else {
    `{ 0.0 }
  }
}

#stage(main)
fn dsp() {
  oscillator_bank!(3)  // ここの数値を変更すると、オシレータの数が変わる
}

上記のようなマクロを使った例では、oscillator_bank!(3)の引数を変更することで、オシレータの数をあたかも動的変数かのように変更でき、それでも内部状態は適切に保持されます。

技術的な実装 #

state_tree クレート #

実装は、決定論的な状態位置のための静的メモリ割り当てを持つ状態管理用のstate_treeクレートを使用します。

コンパイラは以下の要素を静的解析し、dsp関数からの内部状態使用のツリーを作成します。

  • delay関数の呼び出し
  • memの呼び出し
  • selfキーワードの使用
  • これらを伴う非クロージャ関数の再帰的呼び出し

バージョン違いのプログラム同士でツリーを比較し、変更がない部分だけ前のVMから内部状態のメモリをコピーするようなパッチ列を生成します。パッチの適用直前まではオーディオスレッドをブロックすることなく計算することができます。

使用方法 #

特別なオプションなどは必要ありません。mimium-cliは実行中のファイル検知して、上書き保存のタイミングで自動でファイルを再コンパイルします。

内部状態の木の比較は、ソースコードへのあまり大きな構造変化が伴わないこと(例えば、ある一箇所への挿入や削除程度の操作)を前提に比較を最適化しています。一気に大部分を書き換えるよりも、細かく再評価していく方が効率的になります。