#include "midi.h" #include "notes.h" #include void midi_decode(uint32_t msg, synth_t * synth) { // printf("MIDI message: 0x%X\n", msg); uint8_t status = msg; uint8_t data1 = (msg >> 8) & 0xFF; uint8_t data2 = (msg >> 16) & 0xFF; uint8_t channel = (status & 0x0F) + 1; // convert to human uint8_t message = status >> 4; switch (message) { case 0x08: printf("Note Off: channel=%d, note=%d, velocity=%d\n", channel, data1, data2); if (synth->n.key == data1) { synth->n.noteOff = Pa_GetStreamTime(synth->stream); } synth->midi_note[data1].noteOff = Pa_GetStreamTime(synth->stream); break; case 0x09: printf("Note On: channel=%d, note=%d, velocity=%d\n", channel, data1, data2); synth->n.key = data1; synth->n.freq = notes[data1 % 12][(data1 / 12) % 8]; synth->n.noteOn = Pa_GetStreamTime(synth->stream); synth->n.noteOff = 0; synth->n.elapsed = 0; synth->adsr.elapsed = 0; synth->active = 1; //synth->gain = data2 / 127.0; //synth->midi_note[i].n = -1; synth->midi_note[data1].freq = notes[data1 % 12][(data1 / 12) % 8]; synth->midi_note[data1].channel = channel; synth->midi_note[data1].noteOn = Pa_GetStreamTime(synth->stream); synth->midi_note[data1].noteOff = 0; synth->midi_note[data1].velocity = (float)data2 / 127.0; synth->midi_note[data1].elapsed = 0; synth->midi_note[data1].active = 1; break; case 0x0A: printf("Aftertouch: channel=%d, note=%d, pressure=%d\n", channel, data1, data2); break; case 0x0B: printf("Control Change: channel=%d, controller=%d, value=%d\n", channel, data1, data2); int x = data2 < 64 ? 1 : -1; switch (data1) { case 0: synth->adsr.a = synth->adsr.a + (x * 0.01); break; case 1: synth->adsr.d = synth->adsr.d + (x * 0.01); break; case 2: synth->adsr.s = synth->adsr.s + (x * 0.01); break; case 3: synth->adsr.r = synth->adsr.r + (x * 0.01); break; case 4: synth->cutoff = synth->cutoff + (x * (10 * log10(synth->cutoff))); break; case 5: synth->resonance = synth->resonance + (x * 0.02); break; case 6: synth->lfo.freq = synth->lfo.freq + (x * 0.1); break; case 7: synth->lfo.amp = synth->lfo.amp + (x * 0.002); break; break; case 28: synth->filter = x - 1; break; case 29: synth->multi = x - 1; break; default: } break; case 0x0C: printf("Program Change: channel=%d, program=%d\n", channel, data1); break; case 0x0D: printf("Channel Pressure: channel=%d, pressure=%d\n", channel, data1); break; case 0x0E: printf("Pitch Bend: channel=%d, value=%d\n", channel, ((data2 << 7) | data1) - 8192); synth->n.freq = (((data2 << 7) | data1) - 8192); break; default: printf("Unknown MIDI message\n"); break; } } void midiCallback(PtTimestamp timestamp, void *userData) { midi_t * m = (midi_t *)userData; if (!m->stream) return; // if (!Pm_Poll(m->stream)) return; PmEvent buf; int e = Pm_Read(m->stream, &buf, 1); if (e == 0) return; // nothing to do if (e < 0) { printf("Pm_Read error %d\n", e); return; } //printf("%d\n", buf.message); midi_decode(buf.message, m->synth); } void init_midi(midi_t *m, synth_t *synth) { m->stream = NULL; m->synth = synth; Pm_Initialize(); printf("midi devs: %d\n", Pm_CountDevices()); const PmDeviceInfo *info; int i; for (i = 0; i < Pm_CountDevices(); i++) { info = Pm_GetDeviceInfo(i); printf("%d: %s [input: %d output: %d opened: %d is_virt:%d] (interf: %s) -- %d\n", i, info->name, info->input, info->output, info->opened, info->is_virtual, info->interf, Pm_GetDefaultInputDeviceID()); //if (!strcmp("MPK225 MIDI", info->name) && !info->input) break; if (!strcmp("MPK225 Port A", info->name) && info->input == 1) break; } Pt_Start(1, midiCallback, m); Pm_OpenInput(&(m->stream), i, //Pm_GetDefaultInputDeviceID(), NULL, 128, NULL, NULL); } void terminate_midi(midi_t *m) { Pm_Close(m->stream); Pt_Stop(); Pm_Terminate(); }