Remapping MIDI channels using MIDI Library on an Arduino Nano

I'm trying to remap channels 3 and 6 to channels 1 and 2, respectively...while filtering out channels 3-16. I can't have channel 3 as it acts as a duo-phonic channel on my eurorack

The midi -> serial and serial -> midi circuits work as I've used this exact set-up with this code:

/*
// Simple DIY Electronic Music Projects
//    diyelectromusic.wordpress.com
//
//  Arduino MIDI Filter
//  https://diyelectromusic.wordpress.com/2020/09/12/arduino-midi-filter/
//
      MIT License
      
      Copyright (c) 2020 diyelectromusic (Kevin)
      
      Permission is hereby granted, free of charge, to any person obtaining a copy of
      this software and associated documentation files (the "Software"), to deal in
      the Software without restriction, including without limitation the rights to
      use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
      the Software, and to permit persons to whom the Software is furnished to do so,
      subject to the following conditions:
      
      The above copyright notice and this permission notice shall be included in all
      copies or substantial portions of the Software.
      
      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
      COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHERIN
      AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
      WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
  Using principles from the following Arduino tutorials:
    Arduino MIDI Library  - https://github.com/FortySevenEffects/arduino_midi_library
*/
#include <MIDI.h>

// Use binary to say which MIDI channels this should respond to.
// Every "1" here enables that channel. Set all bits for all channels.
//
//                               16  12  8   4  1
//                               |   |   |   |  |
uint16_t MIDI_CHANNEL_FILTER = 0b0000000000000011;

// This is required to set up the MIDI library.
// The default MIDI setup uses the built-in serial port.
MIDI_CREATE_DEFAULT_INSTANCE();

#define MIDI_LED LED_BUILTIN

void setup() {
  pinMode (MIDI_LED, OUTPUT);
  digitalWrite (MIDI_LED, LOW);
  
  // This listens to all MIDI channels
  // They will be filtered out later...
  MIDI.begin(MIDI_CHANNEL_OMNI);
  MIDI.turnThruOff();  // Disable automatic MIDI Thru function
}

void loop() {
  // put your main code here, to run repeatedly:
  // If we have MIDI data then forward it on.
  // Based on the DualMerger.ino example from the MIDI library.
  //
  if (MIDI.read()) {
    // Extract the channel and type to build the command to pass on
    // Recall MIDI channels are in the range 1 to 16, but will be
    // encoded as 0 to 15.
    //
    // All commands in the range 0x80 to 0xE0 support a channel.
    // Any command 0xF0 or above do not (they are system messages).
    // 
    byte ch = MIDI.getChannel();
    uint16_t ch_filter = 1<<(ch-1);  // bit numbers are 0 to 15; channels are 1 to 16
    if (ch == 0) ch_filter = 0xffff; // special case - always pass system messages where ch==0
    if (MIDI_CHANNEL_FILTER & ch_filter) {
      // Now we've filtered on channel, filter on command
      byte cmd = MIDI.getType();
      switch (cmd) {
        case midi::NoteOn:
        case midi::NoteOff:
          digitalWrite (MIDI_LED, HIGH);
          MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), MIDI.getChannel());
          digitalWrite (MIDI_LED, LOW);
          break;
      }
    }
  }
}

I've tried using the "MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), MIDI.getChannel());" to force a remap but it has only made a mess of the MIDI track I've been using. I've attached a readout of the midi messages that are coming out of the Arduino and my code below:
Attempted Midi Remap Messages.pdf (419.1 KB)

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

#define MIDI_LED LED_BUILTIN


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

void loop() {
  
  if (MIDI.read(MIDI.getChannel() == 0))
    ;
  {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 0);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 3))
    ;
  {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 1);
    digitalWrite(MIDI_LED, LOW);
  }
    if (MIDI.read(MIDI.getChannel() == 6))
    ;
  {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 2);
    digitalWrite(MIDI_LED, LOW);
  }
}

Any Idea where I've gone wrong?

1 Like

Well for a start the ; ends the if statement therefore the code in the braces { to } will be run irrespective of the channel number.

You repeat this mistake all the way through your code.

Thank you! That explains why it was auto-formatting so oddly.

I've updated the code to remove those semicolons and remapped the original channels 1-3 to 12-14 to keep it out of the eurorack's scope.

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

#define MIDI_LED LED_BUILTIN


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

void loop() {

  if (MIDI.read(MIDI.getChannel() == 0))

  {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 0);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 1)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 12);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 2)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 13);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 3)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 1);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 6)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 2);
    digitalWrite(MIDI_LED, LOW);
  }
}

The barrage of messages has calmed down, but it's still not right, musically.
Attempted Midi Remap Messages 2.pdf (356.6 KB)

Are you forgetting that MIDI channel one is written in code as zero, so

Is passing through everything on channel zero ( or 1 for musicians)

I think you are mixing up your displayed MIDI channel and the ones you have to use in a program.

That's what I thought the first time I put the code together because everything I was able to find was based on Serial and 0-F instead of the MIDI library (albeit, before the semicolon oversight was fixed)

But when I tried this just now it deleted all the channel 2 activity on my midi monitor:

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

#define MIDI_LED LED_BUILTIN


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

void loop() {
/*
  if (MIDI.read(MIDI.getChannel() == 0))

  {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 0);
    digitalWrite(MIDI_LED, LOW);
  }
*/
  if (MIDI.read(MIDI.getChannel() == 0)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 12);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 1)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 13);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 2)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 0);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 5)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 1);
    digitalWrite(MIDI_LED, LOW);
  }
}

Attempted Midi Remap Messages 3.pdf (318.4 KB)

To clarify what I want out of this program.

-----------------------------
|MIDI INPUT| NEW MIDI OUTPUT|
|1         |x               |
|2         |x               |
|3         |1               |
|4         |x               |
|5         |x               |
|6         |2               |
|7         |x               |
|8         |x               |
|9         |x               |
|10        |x               |
|11        |x               |
|12        |x               |
|13        |x               |
|14        |x               |
|15        |x               |
|16        |x               |
-----------------------------

I've just moved the original channel 1 and 2 as an attempt to move the data out of the scope of my eurorack (it responds to channels:1, 2, 3, and 10)

I've been able to manipulate the midi in my DAW to simulate the midi outputs I'm looking for:
Desired Midi Outputs.pdf (507.0 KB)

I updated that code to ignore the original channel 1 and 2 as my code is specifically reading channels 3 and 6:

#include <MIDI.h>
MIDI_CREATE_DEFAULT_INSTANCE();

#define MIDI_LED LED_BUILTIN


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

void loop() {
/*
  if (MIDI.read(MIDI.getChannel() == 0))

  {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), MIDI.getChannel());
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 1)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 12);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 2)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 13);
    digitalWrite(MIDI_LED, LOW);
  }
*/
  if (MIDI.read(MIDI.getChannel() == 3)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 1);
    digitalWrite(MIDI_LED, LOW);
  }

  if (MIDI.read(MIDI.getChannel() == 6)) {
    digitalWrite(MIDI_LED, HIGH);
    MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 2);
    digitalWrite(MIDI_LED, LOW);
  }
}

This is what came out:
Attempted Midi Remap Messages 4.pdf (712.5 KB)

Because this is derived from a spread sheet then I can't highlight any line. But what is quite wrong is that you are getting four byte out for a three byte message. The first byte you get out is printed in decimal and the other three are in HEX?
What are you using to get this printout?

Sorry about the delated message but the forum mangled up the table I was trying to write.

I ran into that issue myself, no worries!

I'm using Midiview which exports to CSV so I can't upload that directly. I re-exported the desired and 4th attempt in tab-separated txt instead of pdf
Attempted Midi Remap Messages 4.txt (51.9 KB)
Desired Midi Outputs.txt (47.6 KB)
EDIT
-Reuploaded poorly formatted txt's

I think you are over using MIDI.read()
Just use it once at the start of the loop like this:-

void loop()
{
    if (MIDI.read())                // Is there a MIDI message incoming ?
    {
        if (MIDI.getChannel() == 3)) {
               digitalWrite(MIDI_LED, HIGH);
               MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 1);
              digitalWrite(MIDI_LED, LOW);
         }

              if MIDI.getChannel() == 6)) {
              digitalWrite(MIDI_LED, HIGH);
              MIDI.send(MIDI.getType(), MIDI.getData1(), MIDI.getData2(), 2);
              digitalWrite(MIDI_LED, LOW);
         }
}

So in this code Things on MIDI channel 4 will come out on MIDI channel 2, and stuff on MIDI channel 7 will come out on MIDI channel 3,

1 Like

EVERYTHING WORKS!

You, good sir, are a legend. Now I just need to tune my synthesizer to not be horribly off-key LOL.

Thank you so much.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.