ArduinoとTC4051BP(アナログマルチプレクサIC)で簡単なMIDIシーケンサーをつくる

音楽理論とかぜんぜんわからないんですが、この動画で和音の話してて、うちにある唯一のポリフォニックシンセ・MIDI野郎用に和音を鳴らせるMIDIシーケンサーをつくってみるか、と思い立ってつくったやつのメモ。

完成(?)品

謎の配置になってるんですが、それぞれこういう役割です。3ステップシーケンサーで、音の高さ(tone)・長さ(length)・音数(chord)が各ステップごとに指定できます。音数のツマミが小さいと単音、多いと和音になります。lengthが3ステップ目にないのはなぜかは後述。

f:id:yutannihilation:20201010225418p:plain
各ノブの役割

回路図的なもの(雰囲気)

(慣れてないので、記号とか変だったらすみません...)

https://raw.githubusercontent.com/yutannihilation/arduino_midi_3step_sequencer/baa3338f03e3ac095ebdf540672a4a5608a9432b/%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C.png

TC4051BP

8つの入力(上の図のA0A7)の中から1つを選択して出力(COM)に流すIC。どれを選ぶかはS0S2のhigh/lowで切り替えられます。 要は0〜7までの整数を3bitで表現すればよく、上の図のようにつながっている状態だと以下のコードになります(D2からなので2桁シフトする)。PORTDport registerというやつです。

PORTD = i << 2;

ただ、今回のはTX(D1にあたるもの)をMIDIの送信に使っていて、そこの状態は保ちたいのでPORTD & B00000010とのORを取ることになります。

PORTD = (PORTD & B00000010) | (i << 2);

こんな感じで、一定間隔ごとに読み取るチャンネルを切り替えていくとシーケンサーができあがります。

MIDI Library

MIDI関連の操作は、Arduino MIDI Libraryを使います。あんまりドキュメントちゃんと読んでませんが、MIDI送信側で使うときは何も考えずに使える感じでした(受信側はちょっとややこしそうかも)。

メジャーコード、マイナーコード

↑の動画いわく、メジャーコードは4 tone上の音とそこからさらに3 tone上の音を足せばいける、ということで、

MIDI.sendNoteOn(baseTone, 127, 1);
MIDI.sendNoteOn(baseTone + 4, 127, 1);
MIDI.sendNoteOn(baseTone + 7, 127, 1);

とかやるとメジャーコードになるみたいです。マイナーコードは、3 note上→4 note上、なので

MIDI.sendNoteOn(baseTone, 127, 1);
MIDI.sendNoteOn(baseTone + 3, 127, 1);
MIDI.sendNoteOn(baseTone + 7, 127, 1);

です。どっちも鳴らせるようにしたいので、デフォルトはマイナーの方にしておいてメジャーなら偶数のときは1 tone足す、という感じにしました。

int chord[5] = {
    0,
    3,
    7,
    10,
};

// toneは0〜127の128段階だが、下位1bitをメジャー・マイナーの区別に使いたいので256段階の値を読み取る
sensorValue = map(analogRead(pin), 0, 1023, 0, 255);
major = sensorValue & 1; // major or minor
baseTone = sensorValue >> 1;

for (int n = 0; n < notes; n++)
{
  MIDI.sendNoteOn(baseTone + chord[n] + n % 2 * major, velocity, 1);
}

3ステップ目のlength

TC4051BPは8チャンネルしかないので、3ステップに3つのパラメーターを指定しようと思うと3x3=9で1チャンネル足りません。なんですが、1シーケンスのステップ数が一定だとすると、

3ステップ目の長さ = (シーケンス全体の長さ) - (1ステップ目の長さ) - (2ステップ目の長さ)

で計算できるので、まあ別になくてもいいかということでこうなっています。

その他

あと、音に変化を付けるため、

  • 1/10くらいは別の音色で鳴らす
  • 音数は毎回同じではなく、ランダムに飛ばしたりする
  • toneOnだけでなくtoneOffもランダムに飛ばして、たまに長く鳴る音が出るようにする

みたいなこともしています。気になる方はコードを見てください(注:音の長さの計算あたりはたぶん間違えてます。直す気力がない...)

感想

シーケンサー、こんなに可変抵抗ついてて尊い...という気持ちになりました。

あとMIDI野郎は便利。一家に一台ぜひ。