Skip to content

Commit 1f209aa

Browse files
committed
Add MIDI_Pipes-Filter example
1 parent 049b929 commit 1f209aa

File tree

3 files changed

+118
-10
lines changed

3 files changed

+118
-10
lines changed

doxygen/pages/MIDI.md

+9
Original file line numberDiff line numberDiff line change
@@ -868,8 +868,17 @@ void loop() {
868868
}
869869
```
870870

871+
### Filtering or modifying messages passing through a pipe {#midi_md-pipes-filtering}
872+
873+
It is possible to create custom MIDI pipes that can filter out certain MIDI
874+
messages, or even modify the MIDI messages that pass through them (for instance,
875+
to change the channel of certain messages). This is done by inheriting from
876+
the @ref MIDI_Pipe class and overriding the @ref MIDI_Pipe::mapForwardMIDI
877+
functions. See @ref MIDI_Pipes-Filter.ino for more details.
878+
871879
### More examples {#midi_md-routing-more-examples}
872880

873881
- @ref MIDI_Pipes-Routing.ino
874882
- @ref Dual-MIDI-Interface.ino
875883
- @ref MIDI-Monitor.ino
884+
- @ref MIDI_Pipes-Filter.ino
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/**
2+
* @brief Filtering and modifying MIDI messages that travel through a MIDI_Pipe.
3+
*
4+
* This example demonstrates how to create custom MIDI pipes that can filter out
5+
* and modify the messages that travel through it. It uses a debug MIDI
6+
* interface for demonstration purposes, and loops back only MIDI note and
7+
* real-time messages, messages of any other type are dropped. Additionally, all
8+
* MIDI note messages are transposed down an octave, and their channel is set
9+
* to 5.
10+
*
11+
* To try it out, open the Serial monitor (at 115200 baud) and type `98 3C 7F`
12+
* (Note On, channel 9, C4, full velocity). When you press enter, you'll get
13+
* back the following message (note how the channel and pitch changed):
14+
*
15+
* ```
16+
* Note On Channel: 5 Data 1: 0x30 Data 2: 0x7F
17+
* ```
18+
*
19+
* If you try to send a Pitch Bend message (for example, `E0 12 34`), you'll get
20+
* no response, because the code filtered it out.
21+
*
22+
* @boards AVR, AVR USB, Nano Every, Due, Nano 33 IoT, Nano 33 BLE, UNO R4, Pi Pico, ESP32, Teensy 3.x
23+
*/
24+
25+
#include <Control_Surface.h>
26+
27+
USBDebugMIDI_Interface midi;
28+
29+
// A unidirectional pipe that connects a MIDI source to a MIDI sink.
30+
// Messages coming from the source are handled by the `mapForwardMIDI()`
31+
// function, where they can be modified or filtered out, and then sent
32+
// to the MIDI sink by calling the `sourceMIDItoSink()` function.
33+
struct MyMIDIFilter : MIDI_Pipe {
34+
// Pass on only Note On/Off messages, changing the channel to 5 and
35+
// transposing all notes an octave down.
36+
void mapForwardMIDI(ChannelMessage msg) override {
37+
switch (msg.getMessageType()) {
38+
case MIDIMessageType::NoteOff: // fallthrough
39+
case MIDIMessageType::NoteOn:
40+
msg.setChannel(Channel_5);
41+
if (msg.data1 >= 12)
42+
msg.data1 -= 12;
43+
sourceMIDItoSink(msg);
44+
break;
45+
default: break;
46+
}
47+
}
48+
// Do not pass on System Exclusive messages.
49+
void mapForwardMIDI(SysExMessage) override {}
50+
// Do not pass on System Common messages.
51+
void mapForwardMIDI(SysCommonMessage) override {}
52+
// Pass on Real-Time messages without changes.
53+
void mapForwardMIDI(RealTimeMessage msg) override {
54+
sourceMIDItoSink(msg);
55+
}
56+
};
57+
58+
MyMIDIFilter filter;
59+
60+
void setup() {
61+
// Loop back the MIDI input to the MIDI output, through the filter:
62+
// (MIDI input) -> (MIDI filter) -> (MIDI output)
63+
// (source) -> (pipe) -> (sink)
64+
midi >> filter >> midi;
65+
midi.begin();
66+
}
67+
68+
void loop() {
69+
midi.update();
70+
}

examples/examples.dox

+39-10
Original file line numberDiff line numberDiff line change
@@ -1498,20 +1498,20 @@
14981498
* Program Change Channel: 9 Data 1: 0x06
14991499
* Channel Pressure Channel: 3 Data 1: 0x40
15001500
* Pitch Bend Channel: 3 Data 1: 0x7f Data 2: 0x7f (16383)
1501-
* System Common MTC_QUARTER_FRAME Data 1: 0x2f
1502-
* System Common SONG_POSITION_POINTER Data 1: 0x10 Data 2: 0x4e (10000)
1503-
* System Common SONG_SELECT Data 1: 0x46
1504-
* System Common TUNE_REQUEST
1501+
* System Common MTCQuarterFrame Data 1: 0x2f
1502+
* System Common SongPositionPointer Data 1: 0x10 Data 2: 0x4e (10000)
1503+
* System Common SongSelect Data 1: 0x46
1504+
* System Common TuneRequest
15051505
* System Exclusive [10] F0 00 01 02 03 04 05 06 07 F7
15061506
* System Exclusive [6+] F0 10 11 12 13 14
15071507
* System Exclusive [6+] 15 16 17 18 19 1A
15081508
* System Exclusive [6] 1B 1C 1D 1E 1F F7
1509-
* Real-Time TIMING_CLOCK
1510-
* Real-Time START
1511-
* Real-Time CONTINUE
1512-
* Real-Time STOP
1513-
* Real-Time ACTIVE_SENSING
1514-
* Real-Time SYSTEM_RESET
1509+
* Real-Time TimingClock
1510+
* Real-Time Start
1511+
* Real-Time Continue
1512+
* Real-Time Stop
1513+
* Real-Time ActiveSensing
1514+
* Real-Time SystemReset
15151515
* ~~~
15161516
*
15171517
* @see @ref midi_md-sending "MIDI Tutorial: Sending MIDI messages"
@@ -1555,6 +1555,35 @@
15551555
* https://github.com/tttapa/Control-Surface
15561556
*/
15571557

1558+
/**
1559+
* @example "MIDI_Pipes-Filter.ino"
1560+
*
1561+
* MIDI_Pipes-Filter
1562+
* =================
1563+
*
1564+
* @brief Filtering and modifying MIDI messages that travel through a MIDI_Pipe.
1565+
*
1566+
* This example demonstrates how to create custom MIDI pipes that can filter out
1567+
* and modify the messages that travel through it. It uses a debug MIDI
1568+
* interface for demonstration purposes, and loops back only MIDI note and
1569+
* real-time messages, messages of any other type are dropped. Additionally, all
1570+
* MIDI note messages are transposed down an octave, and their channel is set
1571+
* to 5.
1572+
*
1573+
* To try it out, open the Serial monitor (at 115200 baud) and type `98 3C 7F`
1574+
* (Note On, channel 9, C4, full velocity). When you press enter, you'll get
1575+
* back the following message (note how the channel and pitch changed):
1576+
*
1577+
* ```
1578+
* Note On Channel: 5 Data 1: 0x30 Data 2: 0x7F
1579+
* ```
1580+
*
1581+
* If you try to send a Pitch Bend message (for example, `E0 12 34`), you'll get
1582+
* no response, because the code filtered it out.
1583+
*
1584+
* @boards AVR, AVR USB, Nano Every, Due, Nano 33 IoT, Nano 33 BLE, UNO R4, Pi Pico, ESP32, Teensy 3.x
1585+
*/
1586+
15581587
/**
15591588
* @example "Bank.ino"
15601589
*

0 commit comments

Comments
 (0)