#include "midi.h"
#include "notes.h"
#include <string.h>
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);
}
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;
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);
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);
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;
Pm_Read(m->stream, &buf, 1);
//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();
}