
QWRT-002 MIDI Controller
概要(QWRT 2作目)
私の1作目の『QWRT-001 MIDI Thru USB HUB』への接続を想定したMIDIデバイスの一つとしてUSB MIDI Controllerを作成しました。
なお、このMIDI コントローラーは特殊なコントローラではないので、普通にPCへUSB接続してAbleton LiveなどのDAWで使えます。(デバイス名は"Seeeduino xiao")
ただ、私はDAW レス環境を想定しているので、上記『QWRT-001 MIDI Thru USB HUB』に差し込んで『MIDI音源』や『MIDI to CV』などの別モジュラーをダイレクトにコントロールする使い方をします。
※参考:関連モジュール、デバイス
・『QWRT-001 MIDI Thru USB HUB』:MIDI スルーHUB ※各デバイスのHUB
・『QWRT-003 MIDI NSX-1 Panel for eVY1』:MIDI音源
・『QWRT-004 MIDI Chord Generator』:MIDIコードジェネレーター





構成
1.Seeeduino xiao(SAMD)
BOM
※近いうちにアップします。
配線
※大した配線ではありませんが、いつかアップします。
基本、ハギヲさんのサイトのノブ(可変抵抗)に関する回路図を参照いただければ同じです。それを6個同じように配置しました。
プログラム
利用ライブラリ
MIDIUSB Library for Arduino
私は今回MIDIチャネルはフル活用してみたかったので、複数のMIDIチャンネルに同時送信できるようにしています。通常はチャンネルは1つだけでいいです。
また、”midiEventPacket_t”を使えばいろいろできそうでしたので、以下がコントロールできるようにしました。コード内の一番下の関数群をご確認ください。
controlChange(MIDI CCイベント)
programChange(音色変更)
PitchBend(音程変更)
noteOn(キーボードオン) ※通常使わないとは思います。
noteOff(キーボードオフ) ※通常使わないとは思います。
参考:CC(Control Change)一覧
参考:Program Change events一覧
ライブラリに関する細かい説明は、多数サイトがあるので割愛しますが、例えば、下記の方のような応用例があります。
”midiEventPacket_t”を利用して上記イベントをコントロールできるように応用して実装するには下記のサイトを参考にしています。基本的なMIDIメッセージの仕様を理解されている方は簡単な内容かとは思います。(MidiType項参照)
仕様
各ノブに割り当てられたMIDI CCナンバーなどに対するパラメータをノブを回すことで0~127の範囲で可変可能(MIDIの規格通り)
ただし、各ノブのMIDI CCナンバーなどはプログラムの変更により変更可能
本プログラムの各ノブのデフォルト設定内容は下記の通り。
KnobA 音量 VOLUME(CC No.7) CH=No.1-8同時送信
KnobB リリースタイム Release Time(CC No.72) CH=No.1
KnobC リリースタイム Release Time(CC No.72) CH=No.2-8同時送信
KnobD リバーブ Reverb(CC No.91) CH=No.1-8同時送信
KnobF ピッチ(音程) PITCHBEND(CC No.16) CH=No.1-8同時送信
KnobG 音色 ProgramChange CH=No.1-8同時送信
作成したコード
#include <Arduino.h>
#include "MIDIUSB.h"
byte CH=1; //Midi Channel No.
byte VOLUME_DATA;
byte VOLUME_DATA_TMP;
byte RELEASE_1_DATA;
byte RELEASE_1_DATA_TMP;
byte RELEASE_DATA;
byte RELEASE_DATA_TMP;
byte REVVERB_DATA;
byte REVVERB_DATA_TMP;
byte PITCHBEND_DATA;
byte PITCHBEND_DATA_TMP;
byte PROGRAM_DATA;
byte PROGRAM_DATA_TMP;
void setup()
{
Serial1.begin(115200);
delay(2000);
}
void loop()
{
//KnobA:Volume:CH1-8
VOLUME_DATA = analogRead( 10 )/8;
if ( VOLUME_DATA_TMP != VOLUME_DATA)
{
controlChange(1, 7, VOLUME_DATA);
controlChange(2, 7, VOLUME_DATA);
controlChange(3, 7, VOLUME_DATA);
controlChange(4, 7, VOLUME_DATA);
controlChange(5, 7, VOLUME_DATA);
controlChange(6, 7, VOLUME_DATA);
controlChange(7, 7, VOLUME_DATA);
controlChange(8, 7, VOLUME_DATA);
MidiUSB.flush();
VOLUME_DATA_TMP = VOLUME_DATA;
Serial.print( "VOLUME_DATA:" );
Serial.print( VOLUME_DATA );
Serial.print( "\n" );
}
//KnobB:Release Time:CH1
RELEASE_1_DATA = analogRead( 9 )/8;
if ( RELEASE_1_DATA_TMP != RELEASE_1_DATA)
{
controlChange(CH, 72, RELEASE_1_DATA);
MidiUSB.flush();
RELEASE_1_DATA_TMP = RELEASE_1_DATA;
Serial.print( "RELEASE_1_DATA:" );
Serial.print( RELEASE_1_DATA );
Serial.print( "\n" );
}
//KnobC:Release Time:CH2-8
RELEASE_DATA = analogRead( 8 )/8;
if ( RELEASE_DATA_TMP != RELEASE_DATA)
{
// controlChange(CH, 72, RELEASE_DATA);
controlChange(2, 72, RELEASE_DATA);
controlChange(3, 72, RELEASE_DATA);
controlChange(4, 72, RELEASE_DATA);
controlChange(5, 72, RELEASE_DATA);
controlChange(6, 72, RELEASE_DATA);
controlChange(7, 72, RELEASE_DATA);
controlChange(8, 72, RELEASE_DATA);
MidiUSB.flush();
RELEASE_DATA_TMP = RELEASE_DATA;
Serial.print( "RELEASE_DATA:" );
Serial.print( RELEASE_DATA );
Serial.print( "\n" );
}
//KnobD:Reverb:CH1-8
REVVERB_DATA = analogRead( 1 )/8;
if ( REVVERB_DATA_TMP != REVVERB_DATA)
{
controlChange(CH, 91, REVVERB_DATA);
controlChange(2, 91, REVVERB_DATA);
controlChange(3, 91, REVVERB_DATA);
controlChange(4, 91, REVVERB_DATA);
controlChange(5, 91, REVVERB_DATA);
controlChange(6, 91, REVVERB_DATA);
controlChange(7, 91, REVVERB_DATA);
controlChange(8, 91, REVVERB_DATA);
MidiUSB.flush();
REVVERB_DATA_TMP = REVVERB_DATA;
Serial.print( "REVVERB_DATA:" );
Serial.print( REVVERB_DATA );
Serial.print( "\n" );
}
//KnobF:PITCHBEND:CH1-8
PITCHBEND_DATA = analogRead( 2 )/8;
if ( PITCHBEND_DATA_TMP != PITCHBEND_DATA)
{
controlChange_PitchBend(1, 16, PITCHBEND_DATA);
controlChange_PitchBend(2, 16, PITCHBEND_DATA);
controlChange_PitchBend(3, 16, PITCHBEND_DATA);
controlChange_PitchBend(4, 16, PITCHBEND_DATA);
controlChange_PitchBend(5, 16, PITCHBEND_DATA);
controlChange_PitchBend(6, 16, PITCHBEND_DATA);
controlChange_PitchBend(7, 16, PITCHBEND_DATA);
controlChange_PitchBend(8, 16, PITCHBEND_DATA);
MidiUSB.flush();
PITCHBEND_DATA_TMP = PITCHBEND_DATA;
Serial.print( "PITCHBEND_DATA:" );
Serial.print( PITCHBEND_DATA );
Serial.print( "\n" );
}
//KnobG:Program:CH1-8
PROGRAM_DATA = analogRead( 3)/8;
if ( PROGRAM_DATA_TMP != PROGRAM_DATA)
{
programChange(CH,PROGRAM_DATA);
programChange(2,PROGRAM_DATA);
programChange(3,PROGRAM_DATA);
programChange(4,PROGRAM_DATA);
programChange(5,PROGRAM_DATA);
programChange(6,PROGRAM_DATA);
programChange(7,PROGRAM_DATA);
programChange(8,PROGRAM_DATA);
MidiUSB.flush();
PROGRAM_DATA_TMP = PROGRAM_DATA;
Serial.print( "PROGRAM_DATA:" );
Serial.print( PROGRAM_DATA );
Serial.print( "\n" );
}
delay(200);
}
void controlChange_PitchBend(byte channel, byte control, byte value)
{
midiEventPacket_t event = {0x0E, 0xE0 | channel, control, value};
MidiUSB.sendMIDI(event);
}
void programChange(byte channel, byte patch)
{
midiEventPacket_t event = {0x0C, 0xC0 | channel, patch};
MidiUSB.sendMIDI(event);
}
void controlChange(byte channel, byte control, byte value)
{
midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
MidiUSB.sendMIDI(event);
}
void noteOn(byte channel, byte pitch, byte velocity)
{
midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOn);
}
void noteOff(byte channel, byte pitch, byte velocity)
{
midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
MidiUSB.sendMIDI(noteOff);
}