時間×高さ — 三層を積む
横が時間(ステップ)、縦が高さ(音程)の格子で、「いつ」と「どの高さ」を一枚にする。マスをトグルすると、そのステップでその高さが鳴る。ステップシーケンサの形になる。
ピアノロールは、横軸を等分した時間、縦軸を音程に取った二次元の格子。横が時間でステップ、縦が音高で MIDI ノート番号に対応する。各セルのオン/オフが「その時刻にその音を鳴らすか」を表し、和音は同じ列に複数のセルを立てて作る。MIDI シーケンサや DAW のノート編集が同じ表現を使う。縦軸をスケール(音階)の音だけに絞ると、どのセルを立てても和声から外れにくくなる。
縦軸を 5 段、ペンタトニック(5 音)に絞ったメロの格子を置く。段は上が高音、下が低音。点いたマスは melody という行ごとの配列で持つ。ヘッドが点いたマスを踏んだ瞬間だけ濃くする。
// 5段 × 16ステップ。各行に「鳴るステップ」を入れておく const melody = [ [0, 6, 11], [3, 8, 13], [1, 9], [4, 12, 15], [2, 7, 14], ]
格子の背景を 4 マスごとに濃淡をつけて敷いてから、行を回して点いたマスを塗る。横が時間、縦が高さの、二次元の格子になる。
ヘッドが横切るたび、その列で点いているマスが光る。縦の位置がそのまま音の高さで、上に行くほど高い。格子の下にコードの土台が一段付く。コードのルートが 2 ステップごとに切り替わる動きを小さな関数で持つ。
// 2ステップごとにルートを返す。3段の高さで描く const chordRoot = (step) => [0, 0, 2, 2, 1, 1, 0, 0][Math.floor(step / 2)]
Math.floor(step / 2) で 16 ステップを 8 区間に潰して、その区間ごとのルートを引く。返ってきた 0〜2 を縦の高さに使って、点を上下に振り分ける。メロ格子の下に、この点の列が並ぶ。
下の点の列が、2 ステップごとに高さの段で切り替わる。コードのルートの動きが出る。残るのはドラム。キックとハットを別々のステップ配列で持って、四角と小さい丸で別レーンに置く。
// キックは四角、ハットは小さい丸で。別レーンに分ける const kick = [0, 4, 8, 12] const hat = [2, 6, 10, 14]
メロ格子、コードのルート、ドラムの 2 レーン。三つを同じ時間軸の上に積んで、再生ヘッドが上から下まで一本で横切る。
上段がメロディの格子で、点いたマスをヘッドが通るたび濃く光る。中段の点がコードのルートで、2 ステップごとに高さが切り替わる。下段がドラムで、四角がキック、小さい丸がハット。三つが同じ時間軸の上に積み重なって、横に流れていく。曲の最小単位の形で、本物のシーケンサはここに音色と音量が乗る。ペンタに絞ったメロは、どの組み合わせでも破綻しない。