アーキテクチャ
音楽用語の読み替え
このページでは音楽用語をデータモデル上の用語として使います。声部は旋律ストリーム、和声は時間に沿った和音プラン、形式は作曲テンプレートです。短い定義はエンジニアのための音楽用語入門にまとめています。
概要
MIDI Sketch Bachとは?
MIDI Sketch Bach は、機械学習ではなく規則ベースの作曲によってバロック風器楽曲の MIDIを生成するアルゴリズム作曲エンジンです。すべてのノートは和声プランと対位法制約によって決定され、あらゆるDAW にインポートできる編集可能な MIDIを生成します。
C++の作曲エンジンがWebAssemblyにコンパイルされ、その上にJavaScript APIが載っています。
作曲エンジン
単一のコンポーザーサブシステムが、形式ごとの専用ビルダーを通じてすべての形式を処理します。各ビルダーは形式を和声プラン上のボイスインテントのレイアウトとして表現し、コンポーザーがそのレイアウトを組み立て、検証し、レンダリングします。テクスチュア(声部数・拍子・基準長)は形式が決定し、声部数オプションは存在しません。
ボイスインテントと和声プラン
ボイスインテントは、ある小節範囲で一つの旋律ストリームに割り当てる役割です。主題、応答、グラウンドバス、音型などが該当します。和声プランは、素材の構築と検証に使う和音のロードマップです。
パイプラインは次のとおりです。
- 作曲リクエスト — 設定を解決・検証し、シードを解決し、形式から声部数/拍子/長さを固定。
- 形式ディレクター — 形式別のボイスインテント(主題、グラウンド、定旋律、音型、変奏)を小節スパンに割り当て。
- 候補探索 — 各スパンを振り分ける。出荷時の既定スパンはすべて、作譜済みキャリア素材をそのまま再生する。
- 生成検証とレンダラー — 対位法・構造の失敗をまとめて記録し、組み立てた声部をトラックへレンダリングする。
- 装飾と最終検証 — 決定論的な装飾を加え、完成したスコアを検証する。
- ベロシティ、CC、テンポ — ベロシティを適用して再レンダリングし、CC 7/CC 11 とテンポイベントを加える。
- MIDI とイベント出力 — ピッチを出力調へ移調し、標準 MIDI ファイルと公開イベントデータを出力する。
採点付き探索は既定で無効であり、通常の出力には1音も加えません。--free-counterpoint が探索へ切り替えるのは passacaglia の V1(voice == 1)だけです。ほかの形式では自由対位法を利用できないというエラーになります。
段階ごとの詳細は生成パイプラインを参照してください。
デザイン値のアーク
構造は固定のデザインアーク — 提示 → 展開 → クライマックス(スパンの約80%)→ 解決 — に従い、密度・音域・ベロシティの段階を制御します。アークは形式の性質であり、シードごとに探索されるものではないため、出力は音楽的に整い再現可能に保たれます。
密度、音域、ベロシティ
密度は一定範囲にどれだけ多くの音があるかです。音域は低音・高音のような高さの範囲です。ベロシティはMIDIの音の強さです。アークはこれらを上下させ、単調な音列ではなくフレーズ感のある出力にします。
形式ファミリー
形式ディレクターはいくつかのレイアウトファミリーを処理します。
- フーガ系(
fugue、prelude_and_fugue、toccata_and_fugue、fantasia_and_fugue) — エピソードを伴う主題/応答の提示。 - グラウンドバス変奏(
passacaglia、chaconne、goldberg_variations) — 不変のバスと連続する変奏サイクル。ゴルトベルクの基準20小節レイアウトはアリアと4変奏、128小節のfullレイアウトはアリア、全30変奏、アリア・ダ・カーポで構成されます。passacaglia/chaconneはサイクルを3/4で展開します。 - 定旋律(
chorale_prelude) — 固定されたコラール線、装飾音型声部、独立したバス。 - 線的/音型(
trio_sonata、cello_prelude) — 相互作用する声部、または連続的な音型。
決定論性
エンジンは完全に決定論的です。同じ設定とシードはバイト単位で同一の出力を生成します。作曲と検証は内部的に C で行われます。出力時に指定調と出力オクターヴシフトが適用されるため、MIDI ファイルと getEvents() のピッチはどちらも出力調です。内部診断用の generated.v1 は C のピッチを保持します。
二つのイベント表現
選択した出力調で鳴る音が必要なら getEvents() を使います。調が異なってもピッチを比較できる内部診断には generated.v1 を使います。
WASM統合
- 初期化:
init()がWASM モジュールをロードしインスタンス化します。 - メモリ管理:
BachGeneratorがWASM メモリを確保し、destroy()が解放します。 - データ転送: MIDI 出力はWASM メモリからJavaScript の
Uint8Arrayへコピーされ、イベントデータはWASM からシリアライズされてJavaScript でパースされます。