aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/midi/base.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2013-12-18 22:51:53 -0800
committerChris Robinson <[email protected]>2013-12-18 22:51:53 -0800
commit8083fb5be7943e6c5ade6c062ae78559c0826472 (patch)
tree5e39ff595fcead4d272ad8896aef43b94c8adcec /Alc/midi/base.c
parentb9468dc9176861f6ab6f6e358fda71c0d6fecc90 (diff)
Add a new ALsoundfont object type
Includes a basic hierarchy for presets, instruments, samples, zones, generators, and modulators.
Diffstat (limited to 'Alc/midi/base.c')
-rw-r--r--Alc/midi/base.c344
1 files changed, 278 insertions, 66 deletions
diff --git a/Alc/midi/base.c b/Alc/midi/base.c
index 46c9b3d2..20d7a27c 100644
--- a/Alc/midi/base.c
+++ b/Alc/midi/base.c
@@ -8,6 +8,7 @@
#include "midi/base.h"
+#include "alMidi.h"
#include "alMain.h"
#include "alError.h"
#include "evtqueue.h"
@@ -22,6 +23,100 @@
#define SYSEX_EVENT (0xF0)
+void InitEvtQueue(EvtQueue *queue)
+{
+ queue->events = NULL;
+ queue->maxsize = 0;
+ queue->size = 0;
+ queue->pos = 0;
+}
+
+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;
+ queue->size = 0;
+ queue->pos = 0;
+}
+
+ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt)
+{
+ ALsizei pos;
+
+ if(queue->maxsize == queue->size)
+ {
+ if(queue->pos > 0)
+ {
+ /* 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;
+ queue->pos = 0;
+ }
+ else
+ {
+ /* Queue is full, double the allocated space. */
+ void *temp = NULL;
+ ALsizei newsize;
+
+ newsize = (queue->maxsize ? (queue->maxsize<<1) : 16);
+ if(newsize > queue->maxsize)
+ temp = realloc(queue->events, newsize * sizeof(queue->events[0]));
+ if(!temp)
+ return AL_OUT_OF_MEMORY;
+
+ queue->events = temp;
+ queue->maxsize = newsize;
+ }
+ }
+
+ pos = queue->pos;
+ if(queue->size > 0)
+ {
+ ALsizei high = queue->size - 1;
+ while(pos < high)
+ {
+ ALsizei mid = pos + (high-pos)/2;
+ if(queue->events[mid].time < evt->time)
+ pos = mid + 1;
+ else
+ high = mid;
+ }
+ while(pos < queue->size && queue->events[pos].time <= evt->time)
+ pos++;
+
+ if(pos < queue->size)
+ memmove(&queue->events[pos+1], &queue->events[pos],
+ (queue->size-pos)*sizeof(queue->events[0]));
+ }
+
+ queue->events[pos] = *evt;
+ queue->size++;
+
+ return AL_NO_ERROR;
+}
+
+
void MidiSynth_Construct(MidiSynth *self, ALCdevice *device)
{
InitEvtQueue(&self->EventQueue);
@@ -147,95 +242,212 @@ ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *
}
-void InitEvtQueue(EvtQueue *queue)
+void ALsfzone_Construct(ALsfzone *self)
{
- queue->events = NULL;
- queue->maxsize = 0;
- queue->size = 0;
- queue->pos = 0;
+ self->Generators = NULL;
+ self->NumGenerators = 0;
+ self->GeneratorsMax = 0;
+
+ self->Modulators = NULL;
+ self->NumModulators = 0;
+ self->ModulatorsMax = 0;
+
+ self->Object = NULL;
}
-void ResetEvtQueue(EvtQueue *queue)
+void ALsfzone_Destruct(ALsfzone *self)
+{
+ self->Object = NULL;
+
+ free(self->Modulators);
+ self->Modulators = NULL;
+ self->NumModulators = 0;
+ self->ModulatorsMax = 0;
+
+ free(self->Generators);
+ self->Generators = NULL;
+ self->NumGenerators = 0;
+ self->GeneratorsMax = 0;
+}
+
+ALenum ALsfzone_addGenerator(ALsfzone *self, ALenum generator, ALint value)
{
ALsizei i;
- for(i = 0;i < queue->size;i++)
+ for(i = 0;i < self->NumGenerators;i++)
{
- if(queue->events[i].event == SYSEX_EVENT)
+ if(self->Generators[i].Generator == generator)
{
- free(queue->events[i].param.sysex.data);
- queue->events[i].param.sysex.data = NULL;
+ self->Generators[i].Value = value;
+ return AL_NO_ERROR;
}
}
- free(queue->events);
- queue->events = NULL;
- queue->maxsize = 0;
- queue->size = 0;
- queue->pos = 0;
+ if(self->NumGenerators == self->GeneratorsMax)
+ {
+ ALsizei newmax = 0;
+ ALvoid *temp = NULL;
+
+ newmax = (self->GeneratorsMax ? self->GeneratorsMax<<1 : 1);
+ if(newmax > self->GeneratorsMax)
+ temp = realloc(self->Generators, newmax * sizeof(ALsfgenerator));
+ if(!temp) return AL_OUT_OF_MEMORY;
+
+ self->Generators = temp;
+ self->GeneratorsMax = newmax;
+ }
+
+ self->Generators[self->NumGenerators].Generator = generator;
+ self->Generators[self->NumGenerators].Value = value;
+ self->NumGenerators++;
+
+ return AL_NO_ERROR;
}
-ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt)
+ALenum ALsfzone_addModulator(ALsfzone *self, ALenum sourceop, ALenum destop, ALint amount, ALenum amtsourceop, ALenum transop)
{
- ALsizei pos;
-
- if(queue->maxsize == queue->size)
+ ALsizei i;
+ for(i = 0;i < self->NumModulators;i++)
{
- if(queue->pos > 0)
+ if(self->Modulators[i].SourceOp == sourceop && self->Modulators[i].DestOp == destop &&
+ self->Modulators[i].AmountSourceOp == amtsourceop &&
+ self->Modulators[i].TransformOp == transop)
{
- /* 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;
- queue->pos = 0;
+ self->Modulators[i].Amount = amount;
+ return AL_NO_ERROR;
}
- else
- {
- /* Queue is full, double the allocated space. */
- void *temp = NULL;
- ALsizei newsize;
+ }
- newsize = (queue->maxsize ? (queue->maxsize<<1) : 16);
- if(newsize > queue->maxsize)
- temp = realloc(queue->events, newsize * sizeof(queue->events[0]));
- if(!temp)
- return AL_OUT_OF_MEMORY;
+ if(self->NumModulators == self->ModulatorsMax)
+ {
+ ALsizei newmax = 0;
+ ALvoid *temp = NULL;
- queue->events = temp;
- queue->maxsize = newsize;
- }
+ newmax = (self->ModulatorsMax ? self->ModulatorsMax<<1 : 1);
+ if(newmax > self->ModulatorsMax)
+ temp = realloc(self->Modulators, newmax * sizeof(ALsfmodulator));
+ if(!temp) return AL_OUT_OF_MEMORY;
+
+ self->Modulators = temp;
+ self->ModulatorsMax = newmax;
}
- pos = queue->pos;
- if(queue->size > 0)
+ self->Modulators[self->NumModulators].SourceOp = sourceop;
+ self->Modulators[self->NumModulators].DestOp = destop;
+ self->Modulators[self->NumModulators].Amount = amount;
+ self->Modulators[self->NumModulators].AmountSourceOp = amtsourceop;
+ self->Modulators[self->NumModulators].TransformOp = transop;
+ self->NumModulators++;
+
+ return AL_NO_ERROR;
+}
+
+/* Stores a new object pointer in the zone. Returns the old object pointer. */
+ALvoid *ALsfzone_setRefObject(ALsfzone *self, ALvoid *object)
+{
+ ALvoid *oldobj = self->Object;
+ self->Object = object;
+ return oldobj;
+}
+
+
+void ALsfsample_Construct(ALsfsample *self)
+{
+ self->ref = 0;
+
+ self->id = 0;
+}
+
+void ALsfsample_Destruct(ALsfsample *self)
+{
+ self->id = 0;
+}
+
+
+void ALsfinstrument_Construct(ALsfinstrument *self)
+{
+ self->ref = 0;
+
+ self->Zones = NULL;
+ self->NumZones = 0;
+
+ self->id = 0;
+}
+
+void ALsfinstrument_Destruct(ALsfinstrument *self)
+{
+ ALsizei i;
+
+ self->id = 0;
+
+ for(i = 0;i < self->NumZones;i++)
{
- ALsizei high = queue->size - 1;
- while(pos < high)
- {
- ALsizei mid = pos + (high-pos)/2;
- if(queue->events[mid].time < evt->time)
- pos = mid + 1;
- else
- high = mid;
- }
- while(pos < queue->size && queue->events[pos].time <= evt->time)
- pos++;
+ if(self->Zones[i].Object)
+ DecrementRef(&((ALsfsample*)self->Zones[i].Object)->ref);
+ ALsfzone_Destruct(&self->Zones[i]);
+ }
+ free(self->Zones);
+ self->Zones = NULL;
+ self->NumZones = 0;
+}
- if(pos < queue->size)
- memmove(&queue->events[pos+1], &queue->events[pos],
- (queue->size-pos)*sizeof(queue->events[0]));
+
+void ALsfpreset_Construct(ALsfpreset *self)
+{
+ self->ref = 0;
+
+ self->Zones = NULL;
+ self->NumZones = 0;
+
+ self->id = 0;
+}
+
+void ALsfpreset_Destruct(ALsfpreset *self)
+{
+ ALsizei i;
+
+ self->id = 0;
+
+ for(i = 0;i < self->NumZones;i++)
+ {
+ if(self->Zones[i].Object)
+ DecrementRef(&((ALsfinstrument*)self->Zones[i].Object)->ref);
+ ALsfzone_Destruct(&self->Zones[i]);
}
+ free(self->Zones);
+ self->Zones = NULL;
+ self->NumZones = 0;
+}
- queue->events[pos] = *evt;
- queue->size++;
- return AL_NO_ERROR;
+void ALsoundfont_Construct(ALsoundfont *self)
+{
+ self->ref = 0;
+
+ self->Presets = NULL;
+ self->NumPresets = 0;
+
+ self->SampleData = NULL;
+ self->SampleDataLen = 0;
+
+ self->id = 0;
+}
+
+void ALsoundfont_Destruct(ALsoundfont *self)
+{
+ ALsizei i;
+
+ self->id = 0;
+
+ for(i = 0;i < self->NumPresets;i++)
+ {
+ DecrementRef(&self->Presets[i]->ref);
+ self->Presets[i] = NULL;
+ }
+ free(self->Presets);
+ self->Presets = NULL;
+ self->NumPresets = 0;
+
+ free(self->SampleData);
+ self->SampleData = NULL;
+ self->SampleDataLen = 0;
}