打ち込みドラムのパラアウト:Reaper

ドラムの打ち込みでちゃんと音を作ろうとすると、「キックだけにコンプをかけたい」とか「スネアとハイハットのEQ設定を別にしたい」とか、楽器ごとにパラアウトしたいことはよくある。

音源側がパラアウトに対応していない場合、キック用、スネア用というように各楽器専用のトラックを作り、各トラックに音源を読み込む方法で一応可能だが、MIDIファイルを別々に作らねばならず、作業効率が悪い。(同じ音源を複数読み込むことによるメモリの圧迫も問題だが、こちらは解決しにくい…)

少し工夫して、音源を読み込むトラックとMIDIを打ち込むトラックを分け、MIDIの方でチャンネルごとに「チャンネル2はキックのトラックに送る」「チャンネル3はスネアのトラックに」とトラックI/Oで設定すると、MIDIファイルは一つですむ。しかしMIDI打ち込みの際、楽器ごとにチャンネルを切り替えねばならず、効率的にもう一歩である。

上は一例。トラック5でMIDIを打ち込み、MIDIチャンネル2をトラック7「kick」に、チャンネル3をトラック8「snare」に、チャンネル4をトラック9「toms」に、チャンネル1はトラック6「cymbal(other)」に送っている。

JSプラグイン

ReaperにはJSプラグインがある。独自の言語でスクリプトを記述すると、MIDIやWAVEに対して簡単な処理を施せる機能である。

ノート番号によってMIDIチャンネルをいじる事もできる。「ノート番号36(C3)~40(E3)は強制的にチャンネル2に送る」などとしてやることで、チャンネル1に打ち込むだけで自動的に適切なトラックにノートが割り振られ、作業効率を保ったままパラアウトを実現できる。

Reaperをインストールする際にプラグインも入れていると、最初から「MIDI note to channel」というJSプラグインが入っている。しかしこれは指定チャンネルに送るノートを1つしか指定できない。タムやシンバルなど複数のノートに割り振られているものをこれで一つ一つ指定するのは相当手間なので、少しだけいじって、上限と下限を指定することで一定範囲のノートをまとめて送れるようにした。

以下のJSスクリプトを、<Reaperインストールフォルダ\Effects\MIDI\midi_notes2channel>に配置すると、FXを追加する画面の「JS」に「JS:MIDI/midi_notes2channel」が追加されている。

midi_notes2channel
/* 
 * MIDI notes to channel
 * 特定の範囲のMIDIノートを、強制的に指定したチャンネルにする。
 * 初期から入っているMIDI note to channelを範囲指定可能にしたもの。
 * max noteをmin note以下にすると、min noteのノートのみが指定チャンネルになる。
 */
desc:MIDI notes to channel

slider1:0<0,127,1{0: C0,1: C#0,2: D0,3: Eb0,4: E0,5: F0,6: F#0,7: G0,8: G#0,9: A0,10: Bb0,11: B0,12: C1,13: C#1,14: D1,15: Eb1,16: E1,17: F1,18: F#1,19: G1,20: G#1,21: A1,22: Bb1,23: B1,24: C2,25: C#2,26: D2,27: Eb2,28: E2,29: F2,30: F#2,31: G2,32: G#2,33: A2,34: Bb2,35: B2,36: C3,37: C#3,38: D3,39: Eb3,40: E3,41: F3,42: F#3,43: G3,44: G#3,45: A3,46: Bb3,47: B3,48: C4,49: C#4,50: D4,51: Eb4,52: E4,53: F4,54: F#4,55: G4,56: G#4,57: A4,58: Bb4,59: B4,60: C5,61: C#5,62: D5,63: Eb5,64: E5,65: F5,66: F#5,67: G5,68: G#5,69: A5,70: Bb5,71: B5,72: C6,73: C#6,74: D6,75: Eb6,76: E6,77: F6,78: F#6,79: G6,80: G#6,81: A6,82: Bb6,83: B6,84: C7,85: C#7,86: D7,87: Eb7,88: E7,89: F7,90: F#7,91: G7,92: G#7,93: A7,94: Bb7,95: B7,96: C8,97: C#8,98: D8,99: Eb8,100: E8,101: F8,102: F#8,103: G8,104: G#8,105: A8,106: Bb8,107: B8,108: C9,109: C#9,110: D9,111: Eb9,112: E9,113: F9,114: F#9,115: G9,116: G#9,117: A9,118: Bb9,119: B9,120: C10,121: C#10,122: D10,123: Eb10,124: E10,125: F10,126: F#10,127: G10}>min note

slider2:0<0,127,1{0: C0,1: C#0,2: D0,3: Eb0,4: E0,5: F0,6: F#0,7: G0,8: G#0,9: A0,10: Bb0,11: B0,12: C1,13: C#1,14: D1,15: Eb1,16: E1,17: F1,18: F#1,19: G1,20: G#1,21: A1,22: Bb1,23: B1,24: C2,25: C#2,26: D2,27: Eb2,28: E2,29: F2,30: F#2,31: G2,32: G#2,33: A2,34: Bb2,35: B2,36: C3,37: C#3,38: D3,39: Eb3,40: E3,41: F3,42: F#3,43: G3,44: G#3,45: A3,46: Bb3,47: B3,48: C4,49: C#4,50: D4,51: Eb4,52: E4,53: F4,54: F#4,55: G4,56: G#4,57: A4,58: Bb4,59: B4,60: C5,61: C#5,62: D5,63: Eb5,64: E5,65: F5,66: F#5,67: G5,68: G#5,69: A5,70: Bb5,71: B5,72: C6,73: C#6,74: D6,75: Eb6,76: E6,77: F6,78: F#6,79: G6,80: G#6,81: A6,82: Bb6,83: B6,84: C7,85: C#7,86: D7,87: Eb7,88: E7,89: F7,90: F#7,91: G7,92: G#7,93: A7,94: Bb7,95: B7,96: C8,97: C#8,98: D8,99: Eb8,100: E8,101: F8,102: F#8,103: G8,104: G#8,105: A8,106: Bb8,107: B8,108: C9,109: C#9,110: D9,111: Eb9,112: E9,113: F9,114: F#9,115: G9,116: G#9,117: A9,118: Bb9,119: B9,120: C10,121: C#10,122: D10,123: Eb10,124: E10,125: F10,126: F#10,127: G10}>max note

slider3:0<0,15,1{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16>channel

@init

NOTE_ON = 8;
NOTE_OFF = 9;

@slider

minnote = slider1;
maxnote = (minnote < slider2) ? slider2 : minnote;
channel = slider3;

@block

while (
  midirecv(ts, msg1, msg23) ? (
    m = msg1&240;
    n = msg23&127;
    ((m == NOTE_ON*16 || m == NOTE_OFF*16) && n >= minnote && n <= maxnote) ? (
      msg1 = m+channel;
    );
    midisend(ts, msg1, msg23);
  );
);