Add infrastructure for handling SysEx MIDI events

This commit is contained in:
Chris Robinson 2013-11-29 04:56:33 -08:00
parent 82d4e69da1
commit ea1d7d56d3
2 changed files with 44 additions and 22 deletions

View File

@ -8,7 +8,13 @@
typedef struct MidiEvent {
ALuint64 time;
ALuint event;
ALuint param[2];
union {
ALuint val[2];
struct {
ALvoid *data;
ALsizei size;
} sysex;
} param;
} MidiEvent;
typedef struct EvtQueue {

View File

@ -16,6 +16,9 @@
/* Microsecond resolution */
#define TICKS_PER_SECOND (1000000)
#define SYSEX_EVENT (0xF0)
static void MidiSynth_Construct(MidiSynth *self, ALCdevice *device);
static void MidiSynth_Destruct(MidiSynth *self);
static inline void MidiSynth_setState(MidiSynth *self, ALenum state);
@ -92,9 +95,14 @@ static void MidiSynth_setSampleRate(MidiSynth *self, ALdouble srate)
static ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2)
{
MidiEvent entry = { time, event, { param1, param2 } };
MidiEvent entry;
ALenum err;
entry.time = time;
entry.event = event;
entry.param.val[0] = param1;
entry.param.val[1] = param2;
err = InsertEvtQueue(&self->EventQueue, &entry);
if(err != AL_NO_ERROR) return err;
@ -249,42 +257,38 @@ static void FSynth_processQueue(FSynth *self, ALuint64 time)
{
const MidiEvent *evt = &queue->events[queue->pos];
switch((evt->event&0xF0))
if(evt->event == SYSEX_EVENT)
fluid_synth_sysex(self->Synth, evt->param.sysex.data, evt->param.sysex.size, NULL, NULL, NULL, 0);
else switch((evt->event&0xF0))
{
case AL_NOTEOFF_SOFT:
fluid_synth_noteoff(self->Synth, (evt->event&0x0F), evt->param[0]);
fluid_synth_noteoff(self->Synth, (evt->event&0x0F), evt->param.val[0]);
break;
case AL_NOTEON_SOFT:
fluid_synth_noteon(self->Synth, (evt->event&0x0F), evt->param[0], evt->param[1]);
fluid_synth_noteon(self->Synth, (evt->event&0x0F), evt->param.val[0], evt->param.val[1]);
break;
case AL_AFTERTOUCH_SOFT:
break;
case AL_CONTROLLERCHANGE_SOFT:
fluid_synth_cc(self->Synth, (evt->event&0x0F), evt->param[0], evt->param[1]);
fluid_synth_cc(self->Synth, (evt->event&0x0F), evt->param.val[0], evt->param.val[1]);
break;
case AL_PROGRAMCHANGE_SOFT:
fluid_synth_program_change(self->Synth, (evt->event&0x0F), evt->param[0]);
fluid_synth_program_change(self->Synth, (evt->event&0x0F), evt->param.val[0]);
break;
case AL_CHANNELPRESSURE_SOFT:
fluid_synth_channel_pressure(self->Synth, (evt->event&0x0F), evt->param[0]);
fluid_synth_channel_pressure(self->Synth, (evt->event&0x0F), evt->param.val[0]);
break;
case AL_PITCHBEND_SOFT:
fluid_synth_pitch_bend(self->Synth, (evt->event&0x0F), (evt->param[0]&0x7F) |
((evt->param[1]&0x7F)<<7));
fluid_synth_pitch_bend(self->Synth, (evt->event&0x0F), (evt->param.val[0]&0x7F) |
((evt->param.val[1]&0x7F)<<7));
break;
}
queue->pos++;
}
if(queue->pos == queue->size)
{
queue->pos = 0;
queue->size = 0;
}
}
static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE])
@ -382,12 +386,6 @@ static void DSynth_processQueue(DSynth *self, ALuint64 time)
while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
queue->pos++;
if(queue->pos == queue->size)
{
queue->pos = 0;
queue->size = 0;
}
}
static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloatBUFFERSIZE*restrict UNUSED(DryBuffer))
@ -597,6 +595,16 @@ void InitEvtQueue(EvtQueue *queue)
void ResetEvtQueue(EvtQueue *queue)
{
ALsizei i;
for(i = 0;i < queue->size;i++)
{
if(queue->events[i].event == SYSEX_EVENT)
{
free(queue->events[i].param.sysex.data);
queue->events[i].param.sysex.data = NULL;
}
}
free(queue->events);
queue->events = NULL;
queue->maxsize = 0;
@ -614,6 +622,14 @@ ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt)
{
/* Queue has some stale entries, remove them to make space for more
* events. */
for(pos = 0;pos < queue->pos;pos++)
{
if(queue->events[pos].event == SYSEX_EVENT)
{
free(queue->events[pos].param.sysex.data);
queue->events[pos].param.sysex.data = NULL;
}
}
memmove(&queue->events[0], &queue->events[queue->pos],
(queue->size-queue->pos)*sizeof(queue->events[0]));
queue->size -= queue->pos;