Go Down

Topic: Change MIDI channel (Read 8725 times) previous topic - next topic

eptheca

I have a simple MIDI keyboard that only sends messages on channel 1
I want to use it with a EHX V256 vocoder that only receives messages on channel 16

I have built a circuit with an arduino + MIDI I/O
I would like to read the incoming MIDI message, and pass it on to MIDI out, just changing the channel number.

Any suggestions to how to do this fast enough?

I have tried with this code:
Code: [Select]

byte incomingByte;


void setup(){
   Serial.begin(31250);
}
 
void loop () {
  if (Serial.available() > 0) {   // read the incoming byte:
    incomingByte = Serial.read();
    Serial.print(incomingByte, BYTE); //debugging over midi out
   
  }
}


it reads the MIDI message, and sends it to MIDI out
so the circuit works

then I tried to change the channel with:
Code: [Select]


byte statusByte, dataByte1, dataByte2;

void setup(){
    Serial.begin(31250);
  }
 
void loop(){
  if(Serial.available() > 0) {
    statusByte = Serial.read();
    if (statusByte == 0x90){
      while(Serial.available() < 1){  //wait for dataByte1 to arrive on Serial;
   }
      dataByte1 = Serial.read();
      while(Serial.available() < 1){  //wait for dataByte2 to arrive;
   }
      dataByte2 = Serial.read();
   }
   if (statusByte == 0x90){
    playNote(0x9F, dataByte1, dataByte2);
  }
}
}
 

  void playNote(byte cmd , byte pitch, byte velocity){
  Serial.write(cmd);
  Serial.write(pitch);
  Serial.write(velocity);
  }


With this code it reads the MIDI message and changes the channel by sending 159 (note on ch.16) as the first byte
but it can not read multiple notes (polyphony) and if the key is released too fast, it will not register it to send the note off

I would really appreciate if anybody has any suggestions on how to do this
Would the MIDI.h library handle polyphony and be faster to read/write the message? 

Grumpy_Mike

#1
Aug 20, 2012, 04:26 pm Last Edit: Aug 20, 2012, 04:29 pm by Grumpy_Mike Reason: 1
Well you could do this with the loop:-
Code: [Select]
void loop(){
 if(Serial.available() > 2) {
   statusByte = Serial.read();
   if (statusByte == 0x90){
     dataByte1 = Serial.read();
     dataByte2 = Serial.read();
     playNote(0x9F, dataByte1, dataByte2);
 }
}
}

However I think your problem is the
Code: [Select]
if (statusByte == 0x90){
line. If your input is using running status then you will get out of sync with the messages. Your code also ignores the note off messages, you need to convert them into note off for the new channel as well.

I think you can handle the note off situation something like this:-
Code: [Select]
void loop(){
  if(Serial.available() > 2) {
    statusByte = Serial.read();
    if (statusByte == 0x90 || statusByte == 0x80 ){
      dataByte1 = Serial.read();
      dataByte2 = Serial.read();
      playNote(statusByte | 0xf, dataByte1, dataByte2);
  }
}
}

el_supremo

A MIDI command byte is easy to detect because it is the only one which has the high order bit set. Try this:
Code: [Select]

byte incomingByte;

void setup(){
   Serial.begin(31250);
}
 
void loop () {
  if (Serial.available() > 0) {   // read the incoming byte:
    incomingByte = Serial.read();
    if(incomingByte & 0x80) {
      // Command byte. Change channel to 0xf if this is NOT a system message
      if((incomingByte & 0xf0) != 0xf0)incomingByte |= 0x0f;
    }
    Serial.print(incomingByte, BYTE); //debugging over midi out
  }
}


Pete
Don't send me technical questions via Private Message.

eptheca

thanks guys :)

Pete, that was exactly the type of "bit-wizardry" I was hoping for
It worked perfect.
I have spent a while now to go through the math to understand it, so it's been a learning experience as well.

schiller

hi there!

what if i would change the second byte of the note on / note off messages?

I'm trying to compile a code for a transposition box..

thanks

Andrea

Grumpy_Mike


hi there!

what if i would change the second byte of the note on / note off messages?

I'm trying to compile a code for a transposition box..

thanks

Andrea


Yes that would work, add 12 to shift up an octave.

N871

#6
Dec 17, 2013, 03:46 pm Last Edit: Dec 17, 2013, 03:50 pm by N871 Reason: 1
Hello,

I have an important question:

Was this code used for a midi keyboard connected  to the arduino with a MIDI cable, or using a USB cable (USB host shield)??
I also would like to change the MIDI channel of my keyboard, but it has to work with a USB cable. The USB port is only
available on the arduino ADK rev3, which would therefor be  my choice.

the idea is to change the channel and send the data to my computer.

thank you for your time.

Grumpy_Mike

Quote
Was this code used for a midi keyboard connected  to the arduino with a MIDI cable,

Yes.

Quote
he USB port is only available on the arduino ADK rev3, which would therefor be  my choice.

Be aware that this is unlikely to work with a USB MIDI HID right out of the box, you will have a lot of complex code to write or find.

crlMidi

This thread may be cold by now - I havn't been lurking for a while.

You can do what you want using my midTemperament tuning aid application on http://www.music.chrblee.net/tuningaid/. Just ignore the features you don't need. If you want, you can set each octave of your keyboard to a different channel!

It uses a Sparkfun midi shield, though you can make your own, and the MIDI library with callbacks. My only Arduino is a Mega 2560, but a smaller one should be OK.

For the benefit of search engines, I mention that the application uses Roland JV / XP system exclusive messages (which are well handled by the library)  and allows you to microtune these synthesisers.

thistof

This is great, it effectively changes notes coming from any channel to channel 16.
How would I go about changing them to a different channel?
I tried changing one line from

if((incomingByte & 0xf0) != 0xf0)incomingByte |= 0x0f;

to

if((incomingByte & 0xf0) != 0xf0)incomingByte |= 0x0e;

thinking that it would send them all to channel 15. It kinda worked, but now any notes coming from odd numbered channels go to channel 15, while those from even numbered channels are still output to channel 16.

What am I missing?

Grumpy_Mike

#10
Jun 22, 2017, 07:50 am Last Edit: Jun 22, 2017, 07:51 am by Grumpy_Mike
Quote
What am I missing
You are missing reading the how to use this forum sticky thread.

It will tell you how to ask questions and also tell you to not hijack the threads or resurrect old threads without very good reason.

Now start your own thread and include more detail, and post all your code.

thistof

#11
Jun 23, 2017, 08:06 am Last Edit: Jun 23, 2017, 08:35 am by thistof
Sorry, I've seen so many forums where everybody groans if you start a thread that's related to a topic already being discussed. I was simply trying to help keep the place tidy and organized with like information in one place. Will do.

Grumpy_Mike

Quote
Sorry, I've seen so many forums where everybody groans if you start a thread that's related to a topic already being discussed.
But here we go by these rules, cunningly hidden at the start of each section How to use this forum

Go Up