Friday, November 2, 2018

Filtering MIDI volume and expression with an Arduino

I need a MIDI filter that simply filters volume and expression CC messages. I use a Hammond XK3c for organ and as a controller for a Yamaha Motif-Rack ES. The organ has two manuals, so in many cases I am playing organ on one and synth on the other. In such cases, I need to be able to change the organ's volume, but I don't want the synth to change volume (at least not the same as the organ). Thanks to Arduino community,  the awesome SparkFunMIDI tutorial, and other places on the Web, I came up with the working code below. This controls an Arduino and the MIDI Shield very well. I'm happy with the functionality.

#include
/*
* MIDI_FilterExp.ino 
* David Summers
* 2018.01.03

* Reads MIDI IN, passes every message except
* CC mnessages for Expression (CC11) and Volume (CC04).
* Useful for controllers that send such data, 
* but you wish for the controlled tone module to ignore it. 
* I use this to control a Yamaha Motif-Rack ES from 
* a Hammond XK3c; I want my expression pedal to
* effect the organ, but not anything on the Motif.
*/
MIDI_CREATE_DEFAULT_INSTANCE();
static const unsigned ledPinG = 6;      // LED pin on Arduino Uno
static const unsigned ledPinR = 7;      // LED pin on Arduino Uno

void setup() 
{
  pinMode(ledPinG, OUTPUT);
  pinMode(ledPinR, OUTPUT);
  MIDI.begin(MIDI_CHANNEL_OMNI);
  digitalWrite(ledPinG, LOW);
  digitalWrite(ledPinR, HIGH);
  MIDI.turnThruOff();
}

void loop()
{
  //digitalWrite(ledPinR, LOW);
  if (MIDI.read())
  {
    
    switch(MIDI.getType()) // Get the type of the message we caught
    {
      //Capture Control Change messages     
      case midi::ControlChange :
        
        //Capture Expression OR Volume CC messages
        if (MIDI.getData1() == 11 || MIDI.getData1() == 4)
        {
          //Don't pass data
          digitalWrite(ledPinR, LOW);
        }
        //All other CC messages
        else
        {
          MIDI.sendControlChange(MIDI.getData1(), MIDI.getData2(), MIDI.getChannel());
        }
        delay(0);
        digitalWrite(ledPinR, HIGH);
      break;
      
      default:
        //digitalWrite(ledPinR, LOW);
        MIDI.send(MIDI.getType(),
                   MIDI.getData1(),
                   MIDI.getData2(),
                   MIDI.getChannel());
        delay(0);
        //digitalWrite(ledPinR, HIGH);
      break;  
      
    }
  }
}