Androidのメモとか

ポキオの日記です。今日も遅延してない。

【DJへの道】ArduinoでMIDIデバイスを作ってRaspberry Pi上のMixxxと連携させる

まずはボタンから。

ポキオ Arduino MIDI Raspberry Pi Mixxx

前回はMixxxをRaspberry Piにインストールしました

非力なRaspberry Pi 2Bでディスプレイも小さいですが、動作自体は問題なさそうです。

relativelayout.hatenablog.com

今回は、Mixxxを操作するハードウェアを作っていきます。

以前作ったデバイスを再利用

ハードウェアを作ると言っても、モノ自体は以前作ったデバイスを再利用していきます。

ポキオ Arduino MIDI Raspberry Pi Mixxx

こんな感じで、5つのボタンをGNDとデジタルIOピンにつないだものです。

ポキオ Arduino MIDI Raspberry Pi Mixxx

マイコン部分はArduino Leonardo互換機のSeeeduino Liteです。Atmega32U4が搭載されているのでUSBネイティブサポートも使えて、USBデバイスとしてエミュレーションも可能です。よって以て、USB接続できるMIDIバイスとしてもエミュレーション可能なはず…。

いざプログラミング

ハードウェアは再利用するので、それを制御するロジックを書き換えていきます。コーディングはArduino IDEで。 久しぶりのダウンロード・起動だったので、UIがガラッと変わっていたのでびっくりしました。

www.arduino.cc

さて、プログラミング自体は下記のArduinoのドキュメントを参考にコーディングしていきます。

docs.arduino.cc

ポイントは…

  • Native USB Port対応をしているボードを使う
  • MIDIを扱うためにMIDIUSBライブラリを使う

こんな感じ。MIDI系のライブラリは複数あってカオスですが、今回はArduinoドキュメントに従っていきます。

コードは最後の方に貼っておきますが、MIDIのやり取りとしてはノートオン・ノートオフを使っていきます。

void noteOn(byte channel, byte pitch, byte velocity) {
  Serial.println("noteOn");
  midiEventPacket_t noteOn = { 0x09, 0x90 | channel, pitch, velocity };
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  Serial.println("noteOff");
  midiEventPacket_t noteOff = { 0x08, 0x80 | channel, pitch, velocity };
  MidiUSB.sendMIDI(noteOff);
}

こんな感じで、ノート(鍵盤)を押す・離すという情報をプログラム的に送信します。鍵盤なので、どの音階をどのくらいの速さ(強さ)で押すか、などの情報も送ります。今回は中央のド(C3)からソ(G3)までを5つのボタンに割り当てて、ノートオン・ノートオフで送信します。チャネルと速度は固定のものを使いました。

ドレミファソをMixxxのコントロールに割り当てる

今回ド〜ソまでの5つの音階が表現できるMIDIバイスが出来たので、それぞれDeck1/2のPlay・Cueに割り当てていきます。(5つのボタンのうち4つだけアサインしてみます)

ポキオ Arduino MIDI Raspberry Pi Mixxx

理想としてはこんな割り当て。実際にMixxxでマッピングしていきます。

ポキオ Arduino MIDI Raspberry Pi Mixxx

自作MIDIバイスRaspberry Piに接続してからMixxxを起動して、設定画面を開くとコントローラーというタブでデバイスが認識されているようです。

一応、プリセットという項目を覗いてみると、主要なDJコントローラーのマッピングには対応してそうですが、今回はプリセットは使わず、ラーニングウィザードを使って自力でマッピングしていきます。

ポキオ Arduino MIDI Raspberry Pi Mixxx

ラーニングウィザードを開くと、Mixxx上の要素が一覧で並んでいて、それぞれに信号のアサインが出来ます。

ポキオ Arduino MIDI Raspberry Pi Mixxx

とりあえず、Deck1/2のPlayとCueを探しては、実際にデバイスのボタンを押して、ボタンと制御の紐付けを行いました。

ポキオ Arduino MIDI Raspberry Pi Mixxx

こんな感じ。

いざDJ

4ボタンだけなので、凝ったことは出来ませんが、ちゃんとボタンと演奏がリンクしていました。

ポキオ Arduino MIDI Raspberry Pi Mixxx

雑感として

  • 理論的にはボタンやスライダーを追加していけばDJコントローラーは自作できる
  • ボタンがチャタるので、何かしらの制御が必要そう
  • ハードウェアボタンを同時に押したり操作したりすると、処理が追いつくか(他の処理をブロッキングしないか)が心配
  • ボタンが増えるとマッピングが面倒

こんな感じですねぇ。自作あるあるですが、やっぱり製品ってすげぇ…ってなりますね(笑)

とりあえず、横フェーダー・縦フェーダー、イコライザ、できればジョグあたりも追加してみたいところ・・・。

コードはこちら

#include <MIDIUSB.h>
#include <MIDIUSB_Defs.h>
#include <frequencyToNote.h>
#include <pitchToFrequency.h>
#include <pitchToNote.h>

#define BUTTON1 3
#define BUTTON2 5
#define BUTTON3 7
#define BUTTON4 8
#define BUTTON5 10

#define C3 48
#define D3 50
#define E3 52
#define F3 53
#define G3 55

#define DELAY 100

void setup() {
  pinMode(BUTTON1, INPUT_PULLUP);
  pinMode(BUTTON2, INPUT_PULLUP);
  pinMode(BUTTON3, INPUT_PULLUP);
  pinMode(BUTTON4, INPUT_PULLUP);
  pinMode(BUTTON5, INPUT_PULLUP);

  Serial.begin(9600);
}

void loop() {
  if (digitalRead(BUTTON1) == 0) {
    Serial.println("BUTTON1");
    noteOn(5, C3, 64);
    MidiUSB.flush();
    delay(DELAY);
    noteOff(5, C3, 64);
    MidiUSB.flush();
  }

  if (digitalRead(BUTTON2) == 0) {
    Serial.println("BUTTON2");
    noteOn(5, D3, 64);
    MidiUSB.flush();
    delay(DELAY);
    noteOff(5, D3, 64);
    MidiUSB.flush();
  }

  if (digitalRead(BUTTON3) == 0) {
    Serial.println("BUTTON3");
    noteOn(5, E3, 64);
    MidiUSB.flush();
    delay(DELAY);
    noteOff(5, E3, 64);
    MidiUSB.flush();
  }

  if (digitalRead(BUTTON4) == 0) {
    Serial.println("BUTTON4");
    noteOn(5, F3, 64);
    MidiUSB.flush();
    delay(DELAY);
    noteOff(5, F3, 64);
    MidiUSB.flush();
  }

  if (digitalRead(BUTTON5) == 0) {
    Serial.println("BUTTON5");
    noteOn(5, G3, 64);
    MidiUSB.flush();
    delay(DELAY);
    noteOff(5, G3, 64);
    MidiUSB.flush();
  }
}

void noteOn(byte channel, byte pitch, byte velocity) {
  Serial.println("noteOn");
  midiEventPacket_t noteOn = { 0x09, 0x90 | channel, pitch, velocity };
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  Serial.println("noteOff");
  midiEventPacket_t noteOff = { 0x08, 0x80 | channel, pitch, velocity };
  MidiUSB.sendMIDI(noteOff);
}

void controlChange(byte channel, byte control, byte value) {
  Serial.println("controlChange");
  midiEventPacket_t event = { 0x0B, 0xB0 | channel, control, value };
  MidiUSB.sendMIDI(event);
}

最後に…

誰かPCDJを私に恵んでください…。

www.amazon.jp

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。