MIDI event handling rewritten: now using the system of the MIDI library to

send events to the right destinations.
Added software MIDI-THRU.
Added driver for TGA-PRO audio board.
master
Holger Wirtz 6 years ago
parent 64998dfdcd
commit 115da6d2a0
  1. 299
      MicroMDAEPiano.ino
  2. 1
      config.h
  3. 73
      mdaEPiano.cpp
  4. 6
      mdaEPiano.h

@ -67,12 +67,16 @@ AudioConnection patchCord6(queue_r, 0, mixer_r, 0);
AudioConnection patchCord7(queue_l, 0, mixer_l, 0);
AudioConnection patchCord8(freeverb_r, 0, mixer_r, 1);
AudioConnection patchCord9(freeverb_l, 0, mixer_l, 1);
#ifdef TEENSY_AUDIO_BOARD
#if defined(TEENSY_AUDIO_BOARD) || defined(TGA_AUDIO_BOARD)
AudioOutputI2S i2s1;
AudioConnection patchCord110(mixer_r, 0, i2s1, 0);
AudioConnection patchCord111(mixer_l, 0, i2s1, 1);
#ifdef TEENSY_AUDIO_BOARD
AudioControlSGTL5000 sgtl5000_1;
#else
AudioControlWM8731master wm8731m1;
#endif
#else
AudioOutputPT8211 pt8211_1;
AudioAmplifier volume_r;
AudioAmplifier volume_l;
@ -127,26 +131,26 @@ void setup()
Serial.begin(SERIAL_SPEED);
delay(220);
/*
// LCD display setup
lcd.init();
lcd.blink_off();
lcd.cursor_off();
lcd.backlight();
lcd.noAutoscroll();
lcd.clear();
lcd.display();
lcd.show(0, 0, 20, " MicroMDAEPiano");
lcd.show(1, 0, 16, "(c)parasiTstudio");
// Encoder setup
enc[0].write(INITIAL_ENC_L_VALUE);
enc_val[0] = enc[0].read();
enc[1].write(INITIAL_ENC_R_VALUE);
enc_val[1] = enc[1].read();
but[0].update();
but[1].update();
*/
/*
// LCD display setup
lcd.init();
lcd.blink_off();
lcd.cursor_off();
lcd.backlight();
lcd.noAutoscroll();
lcd.clear();
lcd.display();
lcd.show(0, 0, 20, " MicroMDAEPiano");
lcd.show(1, 0, 16, "(c)parasiTstudio");
// Encoder setup
enc[0].write(INITIAL_ENC_L_VALUE);
enc_val[0] = enc[0].read();
enc[1].write(INITIAL_ENC_R_VALUE);
enc_val[1] = enc[1].read();
but[0].update();
but[1].update();
*/
// Debug output
Serial.println(F("MicroMDAEPiano based on https://sourceforge.net/projects/mda-vst"));
@ -164,25 +168,35 @@ void setup()
// read initial EEPROM variables
initial_values_from_eeprom();
#ifdef MIDI_DEVICE_DIN
// Start serial MIDI
midi_serial.begin(DEFAULT_MIDI_CHANNEL);
midi_serial.setHandleNoteOn(handleNoteOn_MIDI_DEVICE_DIN);
midi_serial.setHandleNoteOff(handleNoteOff_MIDI_DEVICE_DIN);
midi_serial.setHandleControlChange(handleControlChange_MIDI_DEVICE_DIN);
Serial.println(F("MIDI_DEVICE_DIN enabled"));
#endif
// start up USB host
#ifdef MIDI_DEVICE_USB_HOST
usb_host.begin();
midi_usb.setHandleNoteOn(handleNoteOn_MIDI_DEVICE_USB_HOST);
midi_usb.setHandleNoteOff(handleNoteOff_MIDI_DEVICE_USB_HOST);
midi_usb.setHandleControlChange(handleControlChange_MIDI_DEVICE_USB_HOST);
Serial.println(F("MIDI_DEVICE_USB_HOST enabled."));
#endif
// check for onboard USB-MIDI
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.begin();
midi_onboard_usb.setHandleNoteOn(handleNoteOn_MIDI_DEVICE_USB);
midi_onboard_usb.setHandleNoteOff(handleNoteOff_MIDI_DEVICE_USB);
midi_onboard_usb.setHandleControlChange(handleControlChange_MIDI_DEVICE_USB);
Serial.println(F("MIDI_DEVICE_USB enabled."));
#endif
#ifdef MIDI_DEVICE_DIN
// Start serial MIDI
midi_serial.begin(DEFAULT_MIDI_CHANNEL);
Serial.println(F("MIDI_DEVICE_DIN enabled"));
#endif
// start audio card
AudioNoInterrupts();
AudioMemory(AUDIO_MEM);
#ifdef TEENSY_AUDIO_BOARD
@ -195,6 +209,11 @@ void setup()
sgtl5000_1.volume(1.0, 1.0);
#endif
#ifdef TGA_AUDIO_BOARD
wm8731m1.enable();
wm8731m1.volume(1.0);
#endif
//set_volume(vol, vol_left, vol_right);
set_volume(1.0, 1.0, 1.0);
@ -228,6 +247,7 @@ void setup()
mixer_r.gain(1, 0.3);
mixer_l.gain(1, 0.3);
AudioNoInterrupts();
Serial.println(F("<setup end>"));
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
@ -236,7 +256,6 @@ void setup()
#endif
}
//*************************************************************************************************
//* MAIN LOOP
//*************************************************************************************************
@ -300,78 +319,186 @@ void loop()
queue_r.playBuffer();
queue_l.playBuffer();
}
handle_input();
#ifdef MIDI_DEVICE_DIN
midi_serial.read();
#endif
#ifdef MIDI_DEVICE_USB_HOST
midi_usb.read();
#endif
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.read();
#endif
}
//*************************************************************************************************
//* PROGRAM FUNCTIONS
//*************************************************************************************************
#ifdef MIDI_DEVICE_DIN
void handleNoteOn_MIDI_DEVICE_DIN(byte inChannel, byte inNumber, byte inVelocity)
{
handleNoteOn(byte inChannel, byte inNumber, byte inVelocity);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_USB_HOST
midi_usb.send(midi::NoteOn, inNumber, inVelocity, inChannel);
#endif
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.send(midi::NoteOn, inNumber, inVelocity, inChannel);
#endif
#endif
}
void handle_input(void)
void handleNoteOff_MIDI_DEVICE_DIN(byte inChannel, byte inNumber, byte inVelocity)
{
#ifdef MIDI_DEVICE_DIN
while (midi_serial.read())
{
#ifdef DEBUG
Serial.println(F("[MIDI-Serial]"));
handleNoteOff(byte inChannel, byte inNumber, byte inVelocity)
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_USB_HOST
midi_usb.send(midi::NoteOff, inNumber, inVelocity, inChannel);
#endif
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.send(midi::NoteOff, inNumber, inVelocity, inChannel);
#endif
queue_midi_event(midi_serial.getType(), midi_serial.getData1(), midi_serial.getData2());
}
#endif
}
void handleControlChange_MIDI_DEVICE_DIN(byte inChannel, byte inData1, byte inData2)
{
handleControlChange(byte inChannel, byte inData1, byte inData2)
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_USB_HOST
usb_host.Task();
while (midi_usb.read())
{
#ifdef DEBUG
Serial.println(F("[MIDI-USB-HOST]"));
midi_usb.send(midi::ControlChange, inData1, inData2, inChannel);
#endif
queue_midi_event(midi_usb.getType(), midi_usb.getData1(), midi_usb.getData2());
}
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.send(midi::ControlChange, inData1, inData2, inChannel);
#endif
#endif
}
#endif
#ifdef MIDI_DEVICE_USB_HOST
void handleNoteOn_MIDI_DEVICE_USB_HOST(byte inChannel, byte inNumber, byte inVelocity)
{
handleNoteOn(inChannel, inNumber, inVelocity);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_DIN
midi_serial.send(midi::NoteOn, inNumber, inVelocity, inChannel);
#endif
#ifdef MIDI_DEVICE_USB
while (midi_onboard_usb.read())
{
#ifdef DEBUG
Serial.println(F("[MIDI-USB]"));
midi_onboard_usb.send(midi::NoteOn, inNumber, inVelocity, inChannel);
#endif
queue_midi_event(midi_onboard_usb.getType(), midi_onboard_usb.getData1(), midi_onboard_usb.getData2());
}
#endif
}
bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
void handleNoteOff_MIDI_DEVICE_USB_HOST(byte inChannel, byte inNumber, byte inVelocity)
{
handleNoteOff(inChannel, inNumber, inVelocity);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_DIN
midi_serial.send(midi::NoteOff, inNumber, inVelocity, inChannel);
#endif
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.send(midi::NoteOff, inNumber, inVelocity, inChannel);
#endif
#endif
}
void handleControlChange_MIDI_DEVICE_USB_HOST(byte inChannel, byte inData1, byte inData2)
{
bool ret = false;
handleControlChange(inChannel, inData1, inData2);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_DIN
midi_serial.send(midi::ControlChange, inData1, inData2, inChannel);
#endif
#ifdef MIDI_DEVICE_USB
midi_onboard_usb.send(midi::ControlChange, inData1, inData2, inChannel);
#endif
#endif
}
#endif
#if defined(DEBUG) && defined(SHOW_MIDI_EVENT)
print_midi_event(type, data1, data2);
#ifdef MIDI_DEVICE_USB
void handleNoteOn_MIDI_DEVICE_USB(byte inChannel, byte inNumber, byte inVelocity)
{
handleNoteOn(inChannel, inNumber, inVelocity);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_DIN
midi_serial.send(midi::NoteOn, inNumber, inVelocity, inChannel);
#endif
#ifdef MIDI_DEVICE_USB_HOST
midi_usb.send(midi::NoteOn, inNumber, inVelocity, inChannel);
#endif
#endif
}
// check for MIDI channel
if (midi_channel != MIDI_CHANNEL_OMNI)
{
uint8_t c = type & 0x0f;
if (c != midi_channel)
{
#ifdef DEBUG
Serial.print(F("Ignoring MIDI data on channel "));
Serial.print(c);
Serial.print(F("(listening on "));
Serial.print(midi_channel);
Serial.println(F(")"));
void handleNoteOff_MIDI_DEVICE_USB(byte inChannel, byte inNumber, byte inVelocity)
{
handleNoteOff(inChannel, inNumber, inVelocity);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_DIN
midi_serial.send(midi::NoteOff, inNumber, inVelocity, inChannel);
#endif
return (false);
}
#ifdef MIDI_DEVICE_USB_HOST
midi_usb.send(midi::NoteOff, inNumber, inVelocity, inChannel);
#endif
#endif
}
void handleControlChange_MIDI_DEVICE_USB(byte inChannel, byte inData1, byte inData2)
{
handleControlChange(inChannel, inData1, inData2);
#ifdef MIDI_MERGE_THRU
#ifdef MIDI_DEVICE_DIN
midi_serial.send(midi::ControlChange, inData1, inData2, inChannel);
#endif
#ifdef MIDI_DEVICE_USB_HOST
midi_usb.send(midi::ControlChange, inData1, inData2, inChannel);
#endif
#endif
}
#endif
void handleNoteOn(byte inChannel, byte inNumber, byte inVelocity)
{
if (checkMidiChannel(inChannel))
{
ep->noteOn(inNumber, inVelocity);
}
}
// now throw away the MIDI channel information
type &= 0xf0;
void handleNoteOff(byte inChannel, byte inNumber, byte inVelocity)
{
if (checkMidiChannel(inChannel))
{
ep->noteOn(inNumber, 0);
}
}
ret = ep->processMidiMessage(type, data1, data2);
void handleControlChange(byte inChannel, byte inData1, byte inData2)
{
if (checkMidiChannel(inChannel))
{
ep->processMidiController(inData1, inData2);
}
}
return (ret);
bool checkMidiChannel(byte inChannel)
{
// check for MIDI channel
if (inChannel == MIDI_CHANNEL_OMNI)
{
return (true);
}
else if (inChannel != midi_channel)
{
#ifdef DEBUG
Serial.print(F("Ignoring MIDI data on channel "));
Serial.print(inChannel);
Serial.print(F("(listening on "));
Serial.print(midi_channel);
Serial.println(F(")"));
#endif
return (false);
}
return (true);
}
void set_volume(float v, float vr, float vl)
@ -413,13 +540,14 @@ void set_volume(float v, float vr, float vl)
#ifdef TEENSY_AUDIO_BOARD
sgtl5000_1.dacVolume(vol * vol_left, vol * vol_right);
#elif TGA_AUDIO_BOARD
wm8731m1.volume(vol);
#else
volume_r.gain(vr);
volume_l.gain(vl);
#endif
}
//*************************************************************************************************
//* EEPROM FUNCTIONS
//*************************************************************************************************
@ -503,27 +631,6 @@ uint32_t eeprom_crc32(uint16_t calc_start, uint16_t calc_bytes) // base code fro
//* DEBUG FUNCTIONS
//*************************************************************************************************
#ifdef DEBUG
#ifdef SHOW_MIDI_EVENT
void print_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
{
Serial.print(F("MIDI-Channel: "));
if (midi_channel == MIDI_CHANNEL_OMNI)
Serial.print(F("OMNI"));
else
Serial.print(midi_channel, DEC);
Serial.print(F(", MIDI event type: 0x"));
if (type < 16)
Serial.print(F("0"));
Serial.print(type, HEX);
Serial.print(F(", data1: "));
Serial.print(data1, DEC);
Serial.print(F(", data2: "));
Serial.println(data2, DEC);
}
#endif
#endif
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
void show_cpu_and_mem_usage(void)
{

@ -40,6 +40,7 @@
// AUDIO
//#define TEENSY_AUDIO_BOARD 1
#define TGA_AUDIO_BOARD 1
//*************************************************************************************************
//* MIDI SETTINGS

@ -228,9 +228,9 @@ void mdaEPiano::process(int16_t* outputs_r, int16_t* outputs_l)
l += l * lmod * lfo1;
r += r * rmod * lfo1; //worth making all these local variables?
r*=0.5;
l*=0.5;
r *= 0.5;
l *= 0.5;
if (r > 1.0)
r = 1.0;
else if (r < -1.0)
@ -328,63 +328,42 @@ void mdaEPiano::noteOn(int32_t note, int32_t velocity)
}
}
bool mdaEPiano::processMidiMessage(uint8_t type, uint8_t data1, uint8_t data2)
bool mdaEPiano::processMidiController(uint8_t data1, uint8_t data2)
{
float* param = programs[curProgram].param;
switch (type)
switch (data1)
{
case 0x80: //note off
noteOn(data1 & 0x7F, 0);
case 0x01: //mod wheel
modwhl = 0.0078f * (float)(data2);
if (modwhl > 0.05f) //over-ride pan/trem depth
{
rmod = lmod = modwhl; //lfo depth
if (param[4] < 0.5f) rmod = -rmod;
}
break;
case 0x90: //note on
noteOn(data1 & 0x7F, data2 & 0x7F);
case 0x07: //volume
volume = 0.00002f * (float)(data2 * data2);
break;
case 0xB0: //controller
switch (data1)
case 0x40: //sustain pedal
case 0x42: //sustenuto pedal
sustain = data2 & 0x40;
if (sustain == 0)
{
case 0x01: //mod wheel
modwhl = 0.0078f * (float)(data2);
if (modwhl > 0.05f) //over-ride pan/trem depth
{
rmod = lmod = modwhl; //lfo depth
if (param[4] < 0.5f) rmod = -rmod;
}
break;
case 0x07: //volume
volume = 0.00002f * (float)(data2 * data2);
break;
case 0x40: //sustain pedal
case 0x42: //sustenuto pedal
sustain = data2 & 0x40;
if (sustain == 0)
{
noteOn(SUSTAIN, 0); //end all sustained notes
}
break;
default: //all notes off
if (data1 > 0x7A)
{
for (int32_t v = 0; v < NVOICES; v++) voice[v].dec = 0.99f;
sustain = 0;
muff = 160.0f;
}
break;
noteOn(SUSTAIN, 0); //end all sustained notes
}
break;
case 0xC0: //program change
if (data1 < NPROGS) setProgram(data1);
default: //all notes off
if (data1 > 0x7A)
{
for (int32_t v = 0; v < NVOICES; v++) voice[v].dec = 0.99f;
sustain = 0;
muff = 160.0f;
}
break;
default: break;
}
return (true);
}

@ -79,7 +79,8 @@ class mdaEPiano
~mdaEPiano();
virtual void process(int16_t *outputs_r, int16_t *outputs_l);
virtual bool processMidiMessage(uint8_t type, uint8_t data1, uint8_t data2);
void noteOn(int32_t note, int32_t velocity);
virtual bool processMidiController(uint8_t data1, uint8_t data2);
virtual void setProgram(int32_t program);
virtual void setParameter(int32_t index, float value);
virtual float getParameter(int32_t index);
@ -90,10 +91,9 @@ class mdaEPiano
private:
void update(); //my parameter update
void noteOn(int32_t note, int32_t velocity);
void fillpatch(int32_t p, char *name, float p0, float p1, float p2, float p3, float p4,
float p5, float p6, float p7, float p8, float p9, float p10, float p11);
mdaEPianoProgram* programs;
float Fs, iFs;

Loading…
Cancel
Save