View on GitHub

tonejs-json-sequencer

tonejs-json-sequencer

tonejs-json-sequencer

DeepWiki Japanese English Demo Streaming Demo

状況

3行で説明

Why

Tone.js は、Web 上で豊かな音楽表現を可能にするライブラリです。シンセの構築、エフェクトチェーン、トリガーのスケジューリングなど、高度な音響設計が JavaScript で自由に行えます。

ただその柔軟さゆえに、音色やパターンの構造がプログラムに深く埋め込まれやすく、再利用や連携がしづらくなることもあります。

tonejs-json-sequencer は、Tone.js をそのまま活かしながらも、音色定義・演奏内容・タイミング情報などを JSON として外部化し、データドリブンな音楽再生を可能にする小さな仕組みです。

シーケンスは SMF のように、「時間順にすべてのイベントを明示的に並べた構造」

音色は Tone.js の synth/chain/params を柔軟に JSON で定義可能

演奏中にも音色パラメータを動的に変更できるため、ディレイビブラートやフィルターの開閉などの奏法表現も可能

外部ツールやライブ生成エンジンからの NDJSON ストリームをそのまま受け取り、リアルタイム再生が可能

これにより、構造を持った音楽データを UI やネットワーク越しに操作・再生・交換するという流れを、Tone.js 上でシンプルに実現できます。

Design Philosophy

tonejs-json-sequencer では、Tone.js の構成要素(シンセ、エフェクトチェーン、パラメータ変更など)を、そのまま JSON に記述するというアプローチを取っています。

独自の音楽記述言語や抽象レイヤーは導入せず、そうした高度なロジックは、より上位のプログラム層に委ねる設計です。

音色定義は、Tone.Synth や Tone.FMSynth などのコンストラクタ名と引数オブジェクトを指定する形式

イベント定義も、triggerAttackRelease などの Tone.js の呼び出し内容に近い構造

演奏中のパラメータ変更も、関数名と引数をイベントのタイムスタンプとともに列挙する形式

これにより、Tone.js の持つ音響表現力を損なうことなく、再生ロジックをデータに移し、外部から構成可能にするという目標を実現しています。

コアとなる scheduleOrExecuteEvent は単一elementを受け取るだけのシンプルなソースファイルとし、上位レイヤーでシーケンスやNDJSON ストリーミングを扱う

これにより、Tone.jsとつながる低レイヤーと、シーケンスやストリーミングなどの高レイヤーを、切り分けて柔軟に開発できます。

ライブラリとして利用する

tonejs-json-sequencerは、他のプロジェクトからライブラリとして利用できます。

インストール

npm を使用する場合

npm install tonejs-json-sequencer tone

dist/ ディレクトリを直接参照する場合

このリポジトリをクローンまたはダウンロードして、dist/ ディレクトリ内のファイルを直接参照できます。

ES Modules(推奨)

import { SequencerNodes, playSequence } from './path/to/tonejs-json-sequencer/dist/index.mjs';

CommonJS

const { SequencerNodes, playSequence } = require('./path/to/tonejs-json-sequencer/dist/cjs/index.js');

TypeScript

TypeScript を使用する場合、型定義ファイルも dist/ ディレクトリに含まれています:

import { SequencerNodes, playSequence, SequenceEvent } from './path/to/tonejs-json-sequencer/dist/index.mjs';

型定義ファイル: dist/index.d.ts

CDN を使用する場合

<script type="module">
  import { SequencerNodes, playSequence } from 'https://cdn.jsdelivr.net/npm/tonejs-json-sequencer@1.0.0/dist/index.mjs';
</script>

または unpkg を使用:

<script type="module">
  import { SequencerNodes, playSequence } from 'https://unpkg.com/tonejs-json-sequencer@1.0.0/dist/index.mjs';
</script>

基本的な使用例

import * as Tone from 'tone';
import { SequencerNodes, playSequence } from 'tonejs-json-sequencer';

// JSONでシーケンスを定義
const sequence = [
  {
    eventType: 'createNode',
    nodeId: 0,
    nodeType: 'Synth',
    args: { oscillator: { type: 'sine' } }
  },
  {
    eventType: 'connect',
    nodeId: 0,
    connectTo: 'toDestination'
  },
  {
    eventType: 'triggerAttackRelease',
    nodeId: 0,
    args: ['C4', '8n', '0']
  },
  {
    eventType: 'triggerAttackRelease',
    nodeId: 0,
    args: ['E4', '8n', '0:0:2']
  },
  {
    eventType: 'triggerAttackRelease',
    nodeId: 0,
    args: ['G4', '8n', '0:1:0']
  }
];

// ノードマネージャを作成
const nodes = new SequencerNodes();

// シーケンスを再生
async function play() {
  await Tone.start();
  await playSequence(Tone, nodes, sequence);
}

// ボタンクリックに紐付け
document.getElementById('playButton').addEventListener('click', play);

ブラウザでの使用例(CDN使用)

<!DOCTYPE html>
<html>
<head>
  <title>Tonejs JSON Sequencer Example</title>
  <script src="https://cdn.jsdelivr.net/npm/tone@15.0.4/build/Tone.js"></script>
</head>
<body>
  <button id="playButton">Play</button>
  
  <script type="module">
    import { SequencerNodes, playSequence } from 'https://cdn.jsdelivr.net/npm/tonejs-json-sequencer@1.0.0/dist/index.mjs';

    const sequence = [
      {
        eventType: 'createNode',
        nodeId: 0,
        nodeType: 'Synth',
        args: { oscillator: { type: 'sine' } }
      },
      {
        eventType: 'connect',
        nodeId: 0,
        connectTo: 'toDestination'
      },
      {
        eventType: 'triggerAttackRelease',
        nodeId: 0,
        args: ['C4', '4n', '0']
      }
    ];

    const nodes = new SequencerNodes();

    document.getElementById('playButton').addEventListener('click', async () => {
      await Tone.start();
      await playSequence(Tone, nodes, sequence);
    });
  </script>
</body>
</html>

dist/ ディレクトリの構造

dist/ ディレクトリには以下のファイルが含まれています:

プロジェクトの要件に応じて、適切な形式のファイルを選択できます。

サンプル

より詳細な使用例については、examples/ ディレクトリを参照してください:

NDJSON ストリーミング

tonejs-json-sequencerは、リアルタイム再生、ライブ編集、ループ再生をサポートするNDJSON(改行区切りJSON)ストリーミングに対応しています。

機能

基本的な使い方

import * as Tone from 'tone';
import { SequencerNodes, NDJSONStreamingPlayer } from 'tonejs-json-sequencer';

// ノードマネージャーを作成
const nodes = new SequencerNodes();

// 設定付きでストリーミングプレーヤーを作成
const player = new NDJSONStreamingPlayer(Tone, nodes, {
  lookaheadMs: 50,    // 先読み時間(ミリ秒)
  loop: true,         // ループ再生を有効化
  onLoopComplete: () => {
    console.log('ループ完了!');
  }
});

// NDJSON文字列またはイベント配列で再生開始
const ndjson = `
{"eventType":"createNode","nodeId":0,"nodeType":"Synth"}
{"eventType":"connect","nodeId":0,"connectTo":"toDestination"}
{"eventType":"triggerAttackRelease","nodeId":0,"args":["C4","8n","0"]}
{"eventType":"triggerAttackRelease","nodeId":0,"args":["E4","8n","0:0:2"]}
`;

await Tone.start();
await player.start(ndjson);

// 再生中にシーケンスを更新(ライブ編集)
const updatedNdjson = `
{"eventType":"createNode","nodeId":0,"nodeType":"Synth"}
{"eventType":"connect","nodeId":0,"connectTo":"toDestination"}
{"eventType":"triggerAttackRelease","nodeId":0,"args":["G4","8n","0"]}
`;
await player.start(updatedNdjson);  // 停止せずに更新

// 再生を停止
player.stop();

デモ

ライブ編集とループ再生の完全なインタラクティブデモについては、demo/streaming.html を参照してください。

Tone.js コンポーネントのJSON対応

tonejs-json-sequencerは、Tone.jsの主要なコンポーネントをJSONで記述できるようにします。

対応状況の概要

現在対応済み(✅)

計画中(🚧)

今後検討予定(⏳)

詳細ドキュメント

全コンポーネントの詳細な対応状況、実装優先順位、実装方針については、以下のドキュメントを参照してください:

📄 Tone.js コンポーネント JSON対応ロードマップ(詳細版)

このドキュメントには以下の情報が含まれています:

ロードマップ

開発メモ、随時更新

検討中の課題

優先すること

スコープ外

自動英訳

README.md は README.ja.md を元にGeminiの翻訳でGitHub Actionsで自動生成しています。