FortySevenEffects/arduino_midi_library

Passthrough everything but NoteOn and NoteOff

gitkps opened this issue · 6 comments

I am using 5.0.2
I would like to intercept and modify only the NoteOn and NoteOff Midi commands. The rest I want to passthrough. I successfuly used the Callback functions of NoteOn and NoteOff to do that. But now I find that except those two commands no other messages are getting through.
For example, in order to allow the pitchbend information to go through, I had to use the callback for pitchbend and send it again.

How do I allow all commands to get through without writing individual callback functions for each of them?

Finally, a big thank you for this wonderful library. I could realize a long term dream of mine.

The upcoming filter/map API would be perfect for that, see #40 (comment).

Unfortunately it's not publicly available, but you can use it by downloading the library code from the master branch here on GitHub.

Thank you very much. I am glad there is a solution for my problem.
But unfortunately, I really have no idea how to go about using your suggestion. I am a complete newbie. I have been working on my project by copy pasting and modifying existing arduino code examples.

I know it is asking for too much but if someone can provide me the sample code for both map and filter methods, I would really appreciate that.

Thanks in advance.

If understand your use-case correctly, you'd like to:

  • Have everything but NoteOn and NoteOff pass thru unmodified
  • Modify note events somehow before they are forwarded to Thru

Based on these assumptions, it means that:

  • filter would be configured to allow all types of messages to pass through
  • map would be configured to transform note events in some way

The code would look like this:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

bool thruFilter(const midi::Message& incoming)
{
  return true;
}

midi::Message thruMap(const midi::Message& incoming)
{
  if (incoming.type != midi::NoteOn && incoming.type != midi::NoteOff)
  {
    // Forward everything else as-is
    return incoming;
  }
  midi::Message transformed = incoming;
  // Example: set velocity to maximum
  transformed.data2 = 127;
  return transformed;
}

void setup()
{
  MIDI.setThuFilter(thruFilter);
  MIDI.setThruMap(thruMap);
  MIDI.begin();
}

void loop()
{
  MIDI.read();
}

That was very kind of you.
I copy pasted the code in Arduino IDE. I am using Arduino Uno with the USB Host Shield to connect the USB Midi cable. So, I added the code for Host shield.

The only goal of my project is to intercept the incoming NoteOn or NoteOff command, modify the pitch and send them out.

Before I come to the main issue, I have another doubt. Refer to this part
// Example: set velocity to maximum
transformed.data2 = 127;
Since I want to change the pitch, do I use transformed.data1 = ##, say?
Where do I get this info on what is data2 and data1, etc?
I feel so guilty to ask all these "silly" questions. Please pardon me.

This is the code I tried to compile.
`
#include <MIDI.h> // This line was not required in my working program with callbacks.

// copied these lines from my working program
#include <UHS2-MIDI.h>
USB Usb;
UHS2MIDI_CREATE_DEFAULT_INSTANCE(&Usb);

//MIDI_CREATE_DEFAULT_INSTANCE(); // commented this assuming the line above takes care of this.

bool thruFilter(const midi::Message& incoming)
{
return true;
}

midi::Message thruMap(const midi::Message& incoming)
{
if (incoming.type != midi::NoteOn && incoming.type != midi::NoteOff)
{
// Forward everything else as-is
return incoming;
}
midi::Message transformed = incoming;
// Example: set velocity to maximum
// transformed.data2 = 127;

// change pitch
transformed.data1 = 60;
return transformed;
}

void setup()
{
MIDI.setThuFilter(thruFilter);
MIDI.setThruMap(thruMap);
MIDI.begin();
}

void loop()
{
Usb.Task(); // host shield
MIDI.read();
}
`
=================== I get these errors ============
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:9:23: error: invalid use of template-name 'midi::Message' without an argument list
bool thruFilter(const midi::Message& incoming)
^~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:9:23: note: class template argument deduction is only available with -std=c++1z or -std=gnu++1z
In file included from C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/MIDI.h:33:0,
from C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:1:
C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/midi_Message.h:42:8: note: 'template struct midi::Message' declared here
struct Message
^~~~~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:14:1: error: invalid use of template-name 'midi::Message' without an argument list
midi::Message thruMap(const midi::Message& incoming)
^~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:14:1: note: class template argument deduction is only available with -std=c++1z or -std=gnu++1z
In file included from C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/MIDI.h:33:0,
from C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:1:
C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/midi_Message.h:42:8: note: 'template struct midi::Message' declared here
struct Message
^~~~~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:9:23: error: invalid use of template-name 'midi::Message' without an argument list
bool thruFilter(const midi::Message& incoming)
^~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:9:23: note: class template argument deduction is only available with -std=c++1z or -std=gnu++1z
In file included from C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/MIDI.h:33:0,
from C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:1:
C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/midi_Message.h:42:8: note: 'template struct midi::Message' declared here
struct Message
^~~~~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:14:1: error: invalid use of template-name 'midi::Message' without an argument list
midi::Message thruMap(const midi::Message& incoming)
^~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:14:1: note: class template argument deduction is only available with -std=c++1z or -std=gnu++1z
In file included from C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/MIDI.h:33:0,
from C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:1:
C:\Users\kpsba\OneDrive\Documents\Arduino\libraries\arduino_midi_library-master\src/midi_Message.h:42:8: note: 'template struct midi::Message' declared here
struct Message
^~~~~~~
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino: In function 'void setup()':
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:32:8: error: 'class midi::MidiInterfaceuhs2Midi::uhs2MidiTransport' has no member named 'setThuFilter'; did you mean 'thruFilter'?
MIDI.setThuFilter(thruFilter);
^~~~~~~~~~~~
thruFilter
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:33:8: error: 'class midi::MidiInterfaceuhs2Midi::uhs2MidiTransport' has no member named 'setThruMap'; did you mean 'getThruState'?
MIDI.setThruMap(thruMap);
^~~~~~~~~~
getThruState
C:\Users\kpsba\AppData\Local\Temp.arduinoIDE-unsaved20221130-15996-jrq6f.wvjces\sketch_dec30a\sketch_dec30a.ino:33:19: error: 'thruMap' was not declared in this scope
MIDI.setThruMap(thruMap);
^~~~~~~

exit status 1

Compilation error: invalid use of template-name 'midi::Message' without an argument list

I have no clue how to sort this out.
For some reason, I am having problem with <> code formatting also.
I am sorry.

Regards

Ok, so it's going to be much more complicated.

My proposition involved using an unreleased feature, using MIDI library code from GitHub, rather than the Arduino Library Manager.

It's not going to work here since you're using an additional layer (a midi host library) that internally seems to use this MIDI library (at a version where the map/filter feature doesn't exist).

Your hunch was correct, it would be data1 that represents pitch in the case of note events. This encoding is found online in the MIDI specification, usually with callbacks it's not necessary to know what goes where, since the callback arguments are named after what they mean, but a generic MIDI message object has only those two generically-named bytes.

That being said, if you're using the Arduino as a MIDI USB host, I'm not sure I follow what you want to do with thru, as this concept only exists for hardware serial connections, where it's possible to place the Arduino in the middle of a DIN chain to process the MIDI stream.

Thank you for taking all that trouble.
A bit disappointed that your technique is not going to work in my case.
But that's fine. For the moment, I have managed with callbacks of NoteOn, NoteOff and Pitchbend.

I will close this issue with this.