プログラミング
ペトリネットを音楽シーケンサーとして利用する
Petri Nets as a Music Sequencer (blog.stackdump.com)
要約
この記事では、ペトリネットというシステムモデリング手法を用いて音楽を生成する「beats.bitwrap.io」という音楽シーケンサーを紹介しています。ペトリネットのトークン移動を音符やコマンドに見立て、各楽器や楽曲構造を独立したネットとして表現することで、多様なジャンルの音楽を生成し、視覚的なデバッグやモジュール性を実現しています。
全文翻訳
Home petri-nets music beats-bitwrap tone-js
ペトリネットを音楽シーケンサーとして利用する
beats.bitwrap.io にアクセスしてください。ジャンルを選択してください — techno、jazz、ambient、drum & bass、合計19種類です。Generate をクリックしてください。ドラム、ベース、メロディ、アルペジオを含むフルトラックが聞こえます。シードを変更すると、別のトラックが得られます。同じシードを再生すると、全く同じものが得られます。これにはピアノロールはありません。タイムライングリッドも、DAWもありません。すべてがペトリネット上で動作します — 矢印で繋がれた円で、トークンがそれらを移動します。すべての音符は文字通り、ダイアグラムを1ステップ移動するトークンです。
トークンで作られたドラムマシン
矢印で繋がれた8つの円のリングを想像してください。1つの点 — トークン — が最初の円にあります。毎ティック、それは次の円に飛び移ります。いくつかの円は、トークンが着地したときにキックドラムをトリガーします。残りは無音です。トークンはぐるぐると周回します。これでビートができます。ヒットのパターンはBjorklundアルゴリズムから来ています — これはNステップにKヒットを可能な限り均等に広げます。8ステップに3ヒットで、アフロ・キューバン・ソンからリアーナまで、どこにでも現れるリズム、tresillo が得られます。あの円のリングは何と呼ばれるでしょうか?それはペトリネットと呼ばれます。円はプレース(場所)、矢印はトランジション(遷移)、そして点はトークンです。それがすべての語彙です。数字を変えてください — 16ステップに4ヒット — すると、フォー・オン・ザ・フロアのテクノが得られます。同じ構造、異なるリズムです。各楽器は独自のリングを受け取ります。キック、スネア、ハイハット、クラップ — すべてが並列で実行されます。リングの長さを変えると、それらは同期したり外れたりして、ポリリズムが無料で得られます。16ステップのキックの上に6ステップのハイハットは、アフロ・キューバン音楽や西アフリカ音楽のクロスリズムのように聞こえます。なぜなら、それは同じ数学だからです。
すべてはリングである
メロディも同じように機能します。ドラムヒットの代わりに、各ステップは音符 — ピッチ、ベロシティ、デュレーション — を運びます。音楽理論は、コードに対して意味のある音符を選び(強いビートではコードトーン、弱いビートでは経過音、息抜きのための休符)、それをリングに配置します。ベースラインは?リングです。アルペジオは?ご想像の通りです。ハーモニーパッドは?ご想像の通りです。ジャンルを選んでください — techno、jazz、ambient、drum & bass — プリセットが詳細を設定します:スケール、コード、ドラムパターン、スイングの量、ヒューマナイズの量。ジェネレーターは多くのリングを組み立て、シーケンサーはそれを…実行するだけです。AIもサンプルもありません — 音楽理論とシード付きの乱数です。同じシード、同じトラック、毎回。
ループから楽曲へ
ループは簡単です — トークンが周回し、パターンが繰り返されます。しかし、楽曲にはイントロ、ドロップ、ブレークダウンが必要です。ハイハットは8小節間消え、その後戻ってくるべきです。ベースは2番目のヴァースで忍び込むべきです。そこで、サウンドを作らないが「ハイハットをミュート」や「ベースを導入」のようなコマンドを発火させるリング、コントロールネットを追加しました。円と矢印で作られた小さなステージディレクターです。最初のバージョンは、ひどく無駄が多かったです:1536個の個別のステップのチェーンで、1ティックごとに1ステップ、数百ステップごとにコマンドがあり、その間には何もありませんでした。動きました!しかし、プロジェクトファイルは3分間のトラックで22MBでした。修正:カウントダウンタイマーです。セクション変更の前に384個の空のステップを持つ代わりに、1つの円に384個のトークンを入れ、1ティックごとに1つずつ消費します。特別な接続(インヒビターアークと呼ばれる)が、カウントダウンがゼロに達するまでコントロールイベントを保持します。同じ結果、はるかに少ないダイアグラム:Before 37,148 Places, 37,120 Transitions, 22 MB File size -> After 800 Places, 800 Transitions, 242 KB File size。多くのトークンを持つ1つの円が、それぞれ1つのトークンを持つ多くの円の仕事をこなします。ペトリネットは柔軟です。
トランジションは単なるネット
Auto-DJ は境界で新しいトラックを再生成し、私たちはダウンビートに着地するキュレーションされたフィルタースイープ、ホワイトノイズウォッシュ、またはライザーを求めていました — プロジェクトの切り替えがメインスレッドで競合するのではなく。最初の試みは、メインスレッドのタイマーとワーカー側の再生状態を調整しました。ほとんどの場合機能しましたが、ユーザー操作が境界と重なり、マクロがサイレントにドロップされることがありました。ランタイムと戦っていました。修正は、トランジションをサイドチャネルとして扱うのをやめることでした。各Auto-DJトランジションは、現在、1トランジションのコントロールネットとして、マクロバインディングを発火させて注入されます。t0 は新しいトラックのティック1で発火し、ワーカーは control-fired をエミットし、メインスレッドは通常キューを通じてマクロを実行します。構築によってティック同期され、ペトリネットエグゼキューターはすでにスケジューラーです。2つのタイミングバグ — プロジェクトスワップレースとマクロキューのドロップ — が1つの構造に収束しました。トランジションは、グラフを通過する別のトークンにすぎません。詳細は v1.1.0 リリースノートにあります。キュレーションされたトランジションプール自体は v1.0.8 で出荷されました。
構造が私たちに与えたもの
トークン状態が唯一の状態なので、同じシードはどのマシンでも同じトラックを生成します — 隠されたカウンターやドリフトはありません。音楽を実行するのと同じダイアグラムを画面に描画して監視できます。何かが間違っているように聞こえるとき、トークンが間違った場所にスタックしているか、リングが位相ずれしているのを見ることができます。そして、各楽器が独自のネットであり、楽曲構造が別のレイヤーであるため、1つを引き抜いたり追加したりしても、他のものは壊れません。これらはすべて追加の作業を必要としませんでした。単一のプリミティブが並行性、状態、スケジューリングを運ぶという事実から必然的に生じるものです。
試してみてください
beats.bitwrap.io デモ beats.bitwrap.io — 19ジャンル、すべてクライアントサイド、インストール不要です。オーディオ側のすべての重労働を担ってくれた Tone.js には、大きな感謝を。ペトリネットが何を再生し、いつ再生するかを決定します — Tone.js がそれを実際に良く聞こえるようにします。ポリフォニックシンセ、リバーブ、コンプレッション、サブミリ秒スケジューリング — これらすべてを実質的に無料で手に入れました。壁にぶつかることを期待し続けても、決してぶつからないライブラリの1つです。ペトリネットエグゼキューターは約400行のバニラJSで、シーケンサーワーカーにはさらに約700行あります。残りの部分 — 音楽理論、ジェネレーター、UI — はより大きいですが、フレームワークコードではありません。npmもバンドラーもありません。CDNからのTone.js、静的ファイルを配信するGoサーバー、そして pretty good sequencer になった60年前の円と矢印のアイデアです。
ソース: github.com/stackdump/beats-bitwrap-io
トークンフローが計算モデルとして機能する理由の形式理論については、Declarative Differential Models を参照してください。独自のネットを構築およびシミュレートするには、pflow.xyz を試してください。
← Home • All Posts • 📖 Book ✏️ Edit • Follow
Published: 2026-03-25T00:00:00Z | Modified: 2026-04-19T19:00:00Z
× Follow on Mastodon Follow