l

o

a

d

i

n

g

.

.

.

独自のMIDIツール開発記 #6「AIに作曲させる機能の巻」

2026/05/30

Javascript MIDI

t f B! P L
eyecatch 作曲系AIが盛り上がっている中、独自のMIDIシステムでの作曲はできないものかと考えていたところ、 なんと、できることが判明。 ただ、精度は「非常に良い」とは言いがたく、悪くない旋律を作る程度の普通の出来なのだが、 「まるでできない」という状態じゃないことがわかったので、 クオリティアップの方法は事後に考えるとして、 今回は、AIとの接点機能を構築してみました。

AIに食わせる為のJSON

これまで構築してきたこのシステムは、 「cdefgab」 のように音階をアルファベットで記述したら、ブラウザ音源で音を鳴らすというテキストコードを用いてきましたが、 これだと独自機能すぎて、仕様も含めて、AIへの説明が非常に困難になるという指摘をAIからもらいました。 そりゃあ、自分がそういうんだったらそうなんだと、深く認識することができたので、それではどうすれば良いのかというと、その答えも教えてくれたんですね。 やっぱり、困ったときのJSONです。 現状のテキストコードとJSONを相互にエンコード、デコードできるようにすることで、既存のシステムで扱いやすくなるし、 他のシステムとの受け渡しなどもJSONフォーマットでできるので、安定したデータのやり取りが可能になります。 何より、JSONというデータフォーマットにすることで、細かな他のデータを含ませることもできるので、今後の汎用性の為の機能追加や、情報追加などもできるようになり便利です。

インターフェイス

importとexportのボタンを設置して、実際のデータは、独自のテキストMIDIデータでシステム処理をするような流れになります。

Import

importボタンを押すと、このダイアログが表示されて、JSONデータを貼り付けることができます。 さらに「import」ボタンを押すと、テキストMIDIにコンバートされますが、その前に、「Format」ボタンを押すことで、貼り付けられたJSONフォーマットを整形してくれて、かつフォーマットエラーがあるかどうかのチェックを行なってくれます。

Export

exportボタンをクリックすると、このダイアログが表示されます。 テキストMIDIデータを、JSON形式で表示してくれるので、コピーして、別のファイルなどに自由に書き込むことができます。

AIを使った作曲プロンプト

実際にAIに次のプロンプトを送ってみました。
あなたは作曲AIです。以下のJSON形式で楽曲データを出力してください。 複数パート(メロディ、ベース、コード等)はレイヤーとして分離してください。 ## 出力フォーマット ### 複数レイヤー形式(推奨) { "format_version": "2.0", "layers": [ { "name": "Melody", "oscillatorType": "square", "volume": 70, "bpm": 120, "notes": [ { "pitch": "C5", "duration": "4n" }, { "pitch": "E5", "duration": "4n" } ] }, { "name": "Bass", "oscillatorType": "triangle", "volume": 50, "bpm": 120, "notes": [ { "pitch": "C3", "duration": "2n" }, { "pitch": "G2", "duration": "2n" } ] } ] } ### 単一レイヤー形式(シンプルな効果音向け) { "bpm": 120, "notes": [ { "pitch": "C4", "duration": "4n" }, { "pitch": "rest", "duration": "8n" }, { "pitch": ["C4", "E4", "G4"], "duration": "4n" } ] } ## フィールド仕様 ### format_version "2.0" を指定。複数レイヤー形式の場合に必須。 ### layers (複数レイヤー形式の場合に必須) レイヤーの配列。各レイヤーは独立したパートを表す。 ### layers[].name レイヤー名。"Melody", "Bass", "Chord", "Percussion" 等。 ### layers[].oscillatorType 音色の種類。以下の4種類から選択: - "square": 矩形波(ファミコン風、メロディ向き) - "triangle": 三角波(柔らかい音、ベース向き) - "sawtooth": ノコギリ波(明るく鋭い音、リード向き) - "sine": 正弦波(純音、フルート風) パートに応じた推奨: - メロディ: "square" または "sawtooth" - ベース: "triangle" または "sine" - コード/パッド: "sine" または "triangle" - リード/ソロ: "sawtooth" または "square" ### layers[].volume 音量。0〜100。パート間のバランスを考慮して設定する。 - メロディ: 60〜80 - ベース: 40〜60 - コード/パッド: 30〜50 ### bpm (必須) 曲のテンポ。BPM(Beats Per Minute)で指定。 複数レイヤー形式では各レイヤーに指定。全レイヤーで同じ値を使用すること。 ### notes (必須) 音符の配列。時系列順に並べる。 ### notes[].pitch (必須) - 単音: "C4", "F#5", "Bb3" のように 音名 + オクターブ番号 で指定 - 音名: C, D, E, F, G, A, B - シャープ: # を付ける(例: "C#4", "F#5") - フラット: b を付ける(例: "Bb3", "Eb4") - オクターブ: 0〜10(4が中央付近、ピアノの中央ドは C4) - 和音: 配列で指定(例: ["C4", "E4", "G4"] = ドミソ) - 休符: "rest" - フェードアウト: "fade" ### notes[].duration (必須) 音符の長さを指定。 - "1n": 全音符 - "2n": 2分音符 - "4n": 4分音符 - "8n": 8分音符 - "16n": 16分音符 - "4t": 4分3連符 - 付点音符: 末尾に . を付ける(例: "2n." = 付点2分音符, "4n." = 付点4分音符) - 数値(ミリ秒): 超短い音(効果音用)は数値で直接指定(例: 20 = 20ミリ秒) ### notes[].velocity (任意) 音量。0〜127(MIDI標準)。省略時は64(中程度)。 ### layers[].mute / layers[].solo (任意) ミュート/ソロ状態。通常は false。省略可。 ## 出力ルール - JSONのみを出力してください。説明文は不要です。 - 楽曲は複数レイヤー形式(format_version: "2.0")で出力してください。 - 最低でもメロディとベースの2レイヤーに分離してください。 - 各レイヤーのnotes配列は再生順に並べてください。 - 全レイヤーの再生時間(notes の合計 duration)を揃えてください。短いレイヤーは末尾に "rest" を追加して長さを合わせてください。 - 和音は同時に鳴る音をpitch配列にまとめてください。 - 休符は明示的に "rest" で記述してください(暗黙の休符はありません)。 - 曲の最後は "fade" で終わらせてください。 ## サンプル ### コイン取得音(単一レイヤー・効果音) { "bpm": 120, "notes": [ { "pitch": "B6", "duration": 100 }, { "pitch": "E7", "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] } ### 1upサウンド(単一レイヤー・効果音) { "bpm": 120, "notes": [ { "pitch": "E7", "duration": 133 }, { "pitch": "G7", "duration": 133 }, { "pitch": "E8", "duration": 133 }, { "pitch": "C8", "duration": 133 }, { "pitch": "D8", "duration": 133 }, { "pitch": "G8", "duration": 133 } ] } ### 簡単なメロディ(複数レイヤー) { "format_version": "2.0", "layers": [ { "name": "Melody", "oscillatorType": "square", "volume": 70, "bpm": 120, "notes": [ { "pitch": "C5", "duration": "4n" }, { "pitch": "C5", "duration": "4n" }, { "pitch": "G5", "duration": "4n" }, { "pitch": "G5", "duration": "4n" }, { "pitch": "A5", "duration": "4n" }, { "pitch": "A5", "duration": "4n" }, { "pitch": "G5", "duration": "2n" } ] }, { "name": "Bass", "oscillatorType": "triangle", "volume": 45, "bpm": 120, "notes": [ { "pitch": "C3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "F3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" } ] } ] } ### RPGテーマ(複数レイヤー) { "format_version": "2.0", "layers": [ { "name": "Melody", "oscillatorType": "square", "volume": 75, "bpm": 110, "notes": [ { "pitch": "E4", "duration": "8n" }, { "pitch": "G4", "duration": "8n" }, { "pitch": "A4", "duration": "4n" }, { "pitch": "G4", "duration": "4n" }, { "pitch": "E4", "duration": "2n" }, { "pitch": "C5", "duration": "4n" }, { "pitch": "B4", "duration": "8n" }, { "pitch": "A4", "duration": "8n" }, { "pitch": "G4", "duration": "4n" }, { "pitch": "E4", "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] }, { "name": "Chord", "oscillatorType": "sine", "volume": 35, "bpm": 110, "notes": [ { "pitch": ["C4", "E4", "G4"], "duration": "2n" }, { "pitch": ["F4", "A4", "C5"], "duration": "2n" }, { "pitch": ["G3", "B3", "D4"], "duration": "2n" }, { "pitch": ["A3", "C4", "E4"], "duration": "2n" }, { "pitch": ["F4", "A4", "C5"], "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] }, { "name": "Bass", "oscillatorType": "triangle", "volume": 50, "bpm": 110, "notes": [ { "pitch": "C3", "duration": "2n" }, { "pitch": "F2", "duration": "2n" }, { "pitch": "G2", "duration": "2n" }, { "pitch": "A2", "duration": "2n" }, { "pitch": "F2", "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] } ] } ### 作曲してほしい内容 シューティングゲームのタイトルBGM
そして、出来上がった内容がこちら
{ "format_version": "2.0", "layers": [ { "name": "Melody", "oscillatorType": "sawtooth", "volume": 78, "bpm": 140, "notes": [ { "pitch": "E5", "duration": "8n" }, { "pitch": "G5", "duration": "8n" }, { "pitch": "B5", "duration": "4n" }, { "pitch": "A5", "duration": "4n" }, { "pitch": "G5", "duration": "8n" }, { "pitch": "E5", "duration": "8n" }, { "pitch": "D5", "duration": "4n" }, { "pitch": "E5", "duration": "4n" }, { "pitch": "B5", "duration": "8n" }, { "pitch": "C6", "duration": "8n" }, { "pitch": "D6", "duration": "4n" }, { "pitch": "B5", "duration": "4n" }, { "pitch": "A5", "duration": "8n" }, { "pitch": "G5", "duration": "8n" }, { "pitch": "E5", "duration": "4n" }, { "pitch": "D5", "duration": "4n" }, { "pitch": "E5", "duration": "8n" }, { "pitch": "G5", "duration": "8n" }, { "pitch": "B5", "duration": "4n" }, { "pitch": "D6", "duration": "4n" }, { "pitch": "C6", "duration": "8n" }, { "pitch": "B5", "duration": "8n" }, { "pitch": "A5", "duration": "4n" }, { "pitch": "G5", "duration": "4n" }, { "pitch": "A5", "duration": "8n" }, { "pitch": "C6", "duration": "8n" }, { "pitch": "E6", "duration": "4n" }, { "pitch": "D6", "duration": "4n" }, { "pitch": "B5", "duration": "8n" }, { "pitch": "A5", "duration": "8n" }, { "pitch": "G5", "duration": "4n" }, { "pitch": "E5", "duration": "4n" }, { "pitch": "E5", "duration": "8n" }, { "pitch": "G5", "duration": "8n" }, { "pitch": "B5", "duration": "4n" }, { "pitch": "A5", "duration": "4n" }, { "pitch": "G5", "duration": "8n" }, { "pitch": "E5", "duration": "8n" }, { "pitch": "D5", "duration": "4n" }, { "pitch": "E5", "duration": "4n" }, { "pitch": "B5", "duration": "8n" }, { "pitch": "C6", "duration": "8n" }, { "pitch": "D6", "duration": "4n" }, { "pitch": "E6", "duration": "4n" }, { "pitch": "D6", "duration": "8n" }, { "pitch": "C6", "duration": "8n" }, { "pitch": "B5", "duration": "4n" }, { "pitch": "A5", "duration": "4n" }, { "pitch": "E6", "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] }, { "name": "Bass", "oscillatorType": "triangle", "volume": 55, "bpm": 140, "notes": [ { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "C3", "duration": "2n" }, { "pitch": "D3", "duration": "2n" }, { "pitch": "E3", "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] }, { "name": "Chord", "oscillatorType": "sine", "volume": 45, "bpm": 140, "notes": [ { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "C4", "E4", "G4" ], "duration": "2n" }, { "pitch": [ "D4", "F#4", "A4" ], "duration": "2n" }, { "pitch": [ "E4", "G4", "B4" ], "duration": "2n" }, { "pitch": "fade", "duration": "2n" } ] } ] }
誰でも簡単に作れるので、是非自分の使っているAIチャットツールなどで、このプロンプトで好きな音楽を作ってみてください。 出来上がったJSONデータは、以下のデモのimportで登録すると、簡単に聞くことができるようになります。

デモ

https://yugeta.github.io/mynt_midi/src/
赤枠のところで、登録したデータの再生をすることができます。

Github

本プロジェクトは、GithubでOSS公開しています。 ご意見、ご要望、フォーク、お手伝い・・・全て受け付けております。 MYNT MIDI

あとがき

今回、大幅にアップデートをして、実際にAIに作曲をさせられるようになったので、冒頭にも書いた通り、今後はAI作曲のクオリティをどのように上げていけるかを探求してみようと思います。 ただ、このツールは、まだまだ機能追加をしたいと思っているので、開発は今後も続けていこうと思います。 もし、お手伝いしていただける人などいましたら、お気軽にお声がけくださいませ。 また、このツールを使って作曲をしてみたいという、クリエーターなどがいましたら、是非とも出来上がりを聞かせてくださいませ。 とにかく、AIを使って、世界が広がった今回の機能追加開発でした。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ