コンテンツにスキップ

ヘルパー:音楽理論

スケールとコードを MIDI ピッチの配列として返すヘルパー群です。返り値はただの数値配列なので、JS の配列メソッド(map / filter / forEach / slice 等)と自由に組み合わせられます。

スケール定数表からルートを起点に MIDI ピッチ配列を返します。配列は 1 オクターブ分のみ(例:scale("major", 60)[60, 62, 64, 65, 67, 69, 71])。

いつ使うか: 「全部のノートを C メジャーに揃える」「C ドリアンで 8 音アルペジオ」など、一定の調に縛りたい時。

最小例

const sc = scale("minor", 60); // [60, 62, 63, 65, 67, 68, 70]
onInit(() => sc.forEach((p, i) => setNote({ pitch: p, startBeat: i * 0.5 })));

実用例:元ノートをスケールにスナップ

const sc = scale("dorian", 60);
const allowed = new Set(sc.map((p) => p % 12)); // 許可された音名(class)
onNote((n) => {
if (allowed.has(n.pitch % 12)) {
setNote({ ...n }); // 既にスケール内 — 通す
} else {
setNote({ ...n, pitch: n.pitch - 1 }); // 半音下げてスケールへ
}
});
name音程(半音)雰囲気・用例
major0, 2, 4, 5, 7, 9, 11ポップ・ロックの定番
minor0, 2, 3, 5, 7, 8, 10エモーショナル・ダーク
harmonicMinor0, 2, 3, 5, 7, 8, 11ジプシー・東欧的
melodicMinor0, 2, 3, 5, 7, 9, 11ジャズ系
dorian0, 2, 3, 5, 7, 9, 10ファンク・ジャズ
phrygian0, 1, 3, 5, 7, 8, 10スパニッシュ・メタル
lydian0, 2, 4, 6, 7, 9, 11浮遊感・映画音楽
mixolydian0, 2, 4, 5, 7, 9, 10ブルース・ロック
locrian0, 1, 3, 5, 6, 8, 10ダーク・テンション系
pentaMajor0, 2, 4, 7, 9カントリー・ポップ
pentaMinor0, 3, 5, 7, 10ロック・ペンタトニックソロ
blues0, 3, 5, 6, 7, 10ブルース(♭5 入り)
chromatic0..11全 12 音(クロマチックパターン用)

[!CAUTION] 未定義の名前を渡すと scale: unknown name 'foo' の例外が投げられます(コードの type-o 防止)。

コード定数表から MIDI ピッチ配列を返します。

最小例

chord("maj", 60); // [60, 64, 67] C メジャートライアド
chord("min7", 60); // [60, 63, 67, 70] Cm7
chord("add9", 60); // [60, 64, 67, 74] C add9 (9th はオクターブ上)

実用例:分散和音(アルペジオ)

const ch = chord("maj7", 60);
onInit(() => {
ch.forEach((p, i) => {
setNote({ pitch: p, startBeat: i * 0.25, lengthBeats: 1 });
});
});

実用例:和音をスタックして鳴らす

const ch = chord("min7", 57); // Am7
onInit(() => {
ch.forEach((p) => setNote({ pitch: p, startBeat: 0, lengthBeats: 4 }));
});
name構成(半音)例(C ルート)
maj0, 4, 7C E G
min0, 3, 7C E♭ G
dim0, 3, 6C E♭ G♭
aug0, 4, 8C E G♯
sus20, 2, 7C D G
sus40, 5, 7C F G
maj70, 4, 7, 11C E G B
min70, 3, 7, 10C E♭ G B♭
dom70, 4, 7, 10C E G B♭
m7b50, 3, 6, 10C E♭ G♭ B♭
dim70, 3, 6, 9C E♭ G♭ A
add90, 4, 7, 14C E G D(オクターブ上)

スケール配列を オクターブ巻き戻し付き で添字アクセスします。scale の戻り値(1 オクターブ分)を 無限スケール として扱える便利関数。

いつ使うか: 1 オクターブ内に収まらないアルペジオやライン生成。「マイナースケールで 2 オクターブ上昇」のような使い方が短く書ける。

最小例

const sc = scale("minor", 60); // [60, 62, 63, 65, 67, 68, 70]
degree(sc, 0); // 60 1 度
degree(sc, 7); // 72 1 オクターブ上の 1 度(60 + 12)
degree(sc, -1); // 58 1 オクターブ下の最終度(70 - 12)
degree(sc, 14); // 84 2 オクターブ上の 1 度

実用例:8 ステップで 2 オクターブ上昇

const sc = scale("dorian", 60);
onInit(() => {
for (let i = 0; i < 8; i++) {
setNote({ pitch: degree(sc, i * 2), startBeat: i * 0.25 });
}
});

[!TIP] ループの添字 idegree(sc, i % sc.length) で渡すと 1 オクターブ内、degree(sc, i) で渡すとオクターブ展開。スケール長で剰余を取るかどうか がポイント。

配列内の全要素に semis(半音数)を加算した 新しい配列 を返します。元配列は変更しません。

最小例

const ch = chord("maj", 60); // [60, 64, 67]
transpose(ch, 5); // [65, 69, 72] F メジャー
transpose(ch, -2); // [58, 62, 65] B♭ メジャー

実用例:I → IV → V → I のコード進行

const I = chord("maj", 60);
const IV = transpose(I, 5);
const V = transpose(I, 7);
const prog = [I, I, IV, V]; // 各 1 拍
onInit(() => {
prog.forEach((ch, bar) => {
ch.forEach((p) => setNote({ pitch: p, startBeat: bar, lengthBeats: 1 }));
});
});