Gemphet8 ; 8-polyphonic synthesizer control application
Dependencies: MIDI REnc button mbed
Diff: MIDI_Proc/midi_proc.c
- Revision:
- 5:7d7be4c72d21
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MIDI_Proc/midi_proc.c Mon Aug 11 07:46:03 2014 +0000 @@ -0,0 +1,143 @@ +#include "midi_proc.h" + +using namespace mbed; + +MN_t NoteEnd = { 255, 255, 15, 0 }; +MN_t NoteStart = { 0, 0, 0, &NoteEnd }; +MN_t MidiNotes[POLYPHONICE_NOTES]; +static uint16_t MidiNotesTag; +volatile static uint8_t NumOfNotes = POLYPHONICE_NOTES; + +MIDI midi(dp16, dp15); + +void midi_init(void) +{ + midi.setHandleNoteOff(&midi_noteoff); + midi.setHandleNoteOn(&midi_noteon); + midi.setHandleControlChange(&midi_cc); + midi.setHandleProgramChange(&midi_pc); + midi.setHandlePitchBend(&midi_pbend); + midi.setHandleSystemReset(&midi_sysreset); +} + +/// @brief Reset all MIDI controller +static void midi_allnoteoff(void) +{ + int i; + uint16_t msk; + + for (i = 0, msk = 0x01; i < NumOfNotes; i++, msk<<=1) { + if (MidiNotesTag & msk) { + midi.sendNoteOff(MidiNotes[i].Note, MidiNotes[i].Velocity, MidiNotes[i].Channel); + MidiNotesTag &= ~msk; + } + } + + MidiNotesTag = 0x0000; + NoteEnd.next = NULL; + NoteStart.next = &NoteEnd; +} + +/// @brief Reset MIDI controller +static void midi_resetcontrol(void) +{ +} + +/// @brief Reset all MIDI controller +void midi_sysreset(void) +{ + midi_allnoteoff(); + midi_resetcontrol(); +} + +/// @brief MIDI note structure allocate function +static MN_p allocN(void) { + int i; + uint16_t msk; + + for (i = 0, msk = 0x01; i < NumOfNotes; i++, msk<<=1) { + if (!(MidiNotesTag & msk)) { + MidiNotesTag |= msk; + MidiNotes[i].Channel = i; + return (&MidiNotes[i]); + } + } + return NULL; +} + +/// @brief MIDI note structure free function +static void freeN(MN_p addr) +{ + int i; + uint16_t msk; + + for (i = 0, msk = 0x01; i < NumOfNotes; i++, msk<<=1) { + if (addr == &MidiNotes[i]) + MidiNotesTag &= ~msk; + } +} + +/// @brief MIDI Control Change callback funcion +void midi_cc(byte channel, byte number, byte value) +{ + if (number == MIDI_ALL_NOTE_OFF) { + midi_allnoteoff(); + } + if (number == MIDI_RESET_ALL_CONTROLLERS) { + midi_resetcontrol(); + } + midi.sendControlChange(number, value, channel); +} + +/// @brief MIDI Program Change callback funcion +void midi_pc(byte channel, byte number) +{ + midi.sendProgramChange(number, channel); +} + +/// @brief MIDI Pitch Bend callback funcion +void midi_pbend(byte channel, int bend) +{ + midi.sendPitchBend(bend, channel); +} + +/// @brief MIDI Note On callback funcion +void midi_noteon(byte channel, byte note, byte velocity) +{ + MN_p ptr, newnote; + + if ((newnote = allocN()) == NULL) { // if table full, release oldest note + ptr = NoteStart.next; + midi.sendNoteOff(ptr->Note, ptr->Velocity, ptr->Channel); + NoteStart.next = ptr->next; + freeN(ptr); + newnote = allocN(); + } + newnote->Note = note; + newnote->Velocity = velocity; + // newnote->Channel // do not set channel + midi.sendNoteOn(note, velocity, newnote->Channel); + for (ptr = &NoteStart; ptr->next; ptr = ptr->next) { // put newnote on the tail + if (ptr->next == &NoteEnd) { + newnote->next = ptr->next; + ptr->next = newnote; + break; + } + } +} + +/// @brief MIDI Note Off callback funcion +void midi_noteoff(byte channel, byte note, byte velocity) +{ + MN_p ptr, lastptr; + + for (ptr = &NoteStart; ptr->next; ptr = ptr->next) { + if (note == ptr->next->Note) { + lastptr = ptr->next; + midi.sendNoteOff(lastptr->Note, lastptr->Velocity, lastptr->Channel); + ptr->next = lastptr->next; + freeN(lastptr); + break; + } + } +}