aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/midi
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/midi')
-rw-r--r--Alc/midi/base.c244
-rw-r--r--Alc/midi/base.h133
-rw-r--r--Alc/midi/dummy.c76
-rw-r--r--Alc/midi/fluidsynth.c934
-rw-r--r--Alc/midi/sf2load.c1373
-rw-r--r--Alc/midi/soft.c139
6 files changed, 0 insertions, 2899 deletions
diff --git a/Alc/midi/base.c b/Alc/midi/base.c
deleted file mode 100644
index cab85c1a..00000000
--- a/Alc/midi/base.c
+++ /dev/null
@@ -1,244 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "midi/base.h"
-
-#include "alMidi.h"
-#include "alMain.h"
-#include "alError.h"
-#include "alThunk.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-#include "alu.h"
-
-
-extern inline ALboolean IsValidCtrlInput(int cc);
-
-extern inline size_t Reader_read(Reader *self, void *buf, size_t len);
-
-
-/* MIDI events */
-#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);
-
- RWLockInit(&self->Lock);
-
- self->Soundfonts = NULL;
- self->NumSoundfonts = 0;
-
- self->Gain = 1.0f;
- self->State = AL_INITIAL;
-
- self->ClockBase = 0;
- self->SamplesDone = 0;
- self->SampleRate = device->Frequency;
-}
-
-void MidiSynth_Destruct(MidiSynth *self)
-{
- ALsizei i;
-
- for(i = 0;i < self->NumSoundfonts;i++)
- DecrementRef(&self->Soundfonts[i]->ref);
- free(self->Soundfonts);
- self->Soundfonts = NULL;
- self->NumSoundfonts = 0;
-
- ResetEvtQueue(&self->EventQueue);
-}
-
-
-ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
-{
- ALCdevice *device = context->Device;
- ALsoundfont **sfonts;
- ALsizei i;
-
- if(self->State != AL_INITIAL && self->State != AL_STOPPED)
- return AL_INVALID_OPERATION;
-
- sfonts = calloc(1, count * sizeof(sfonts[0]));
- if(!sfonts) return AL_OUT_OF_MEMORY;
-
- for(i = 0;i < count;i++)
- {
- if(ids[i] == 0)
- sfonts[i] = ALsoundfont_getDefSoundfont(context);
- else if(!(sfonts[i]=LookupSfont(device, ids[i])))
- {
- free(sfonts);
- return AL_INVALID_VALUE;
- }
- }
-
- for(i = 0;i < count;i++)
- IncrementRef(&sfonts[i]->ref);
- sfonts = ExchangePtr((XchgPtr*)&self->Soundfonts, sfonts);
- count = ExchangeInt(&self->NumSoundfonts, count);
-
- for(i = 0;i < count;i++)
- DecrementRef(&sfonts[i]->ref);
- free(sfonts);
-
- return AL_NO_ERROR;
-}
-
-extern inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain);
-extern inline ALfloat MidiSynth_getGain(const MidiSynth *self);
-extern inline void MidiSynth_setState(MidiSynth *self, ALenum state);
-extern inline ALenum MidiSynth_getState(const MidiSynth *self);
-
-void MidiSynth_stop(MidiSynth *self)
-{
- ResetEvtQueue(&self->EventQueue);
-
- self->ClockBase = 0;
- self->SamplesDone = 0;
-}
-
-extern inline void MidiSynth_reset(MidiSynth *self);
-extern inline ALuint64 MidiSynth_getTime(const MidiSynth *self);
-extern inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self);
-
-void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate)
-{
- if(self->SampleRate != srate)
- {
- self->ClockBase += self->SamplesDone * MIDI_CLOCK_RES / self->SampleRate;
- self->SamplesDone = 0;
- self->SampleRate = srate;
- }
-}
-
-extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device);
-
-ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2)
-{
- MidiEvent entry;
- entry.time = time;
- entry.event = event;
- entry.param.val[0] = param1;
- entry.param.val[1] = param2;
- return InsertEvtQueue(&self->EventQueue, &entry);
-}
-
-ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size)
-{
- MidiEvent entry;
- ALenum err;
-
- entry.time = time;
- entry.event = SYSEX_EVENT;
- entry.param.sysex.size = size;
- entry.param.sysex.data = malloc(size);
- if(!entry.param.sysex.data)
- return AL_OUT_OF_MEMORY;
- memcpy(entry.param.sysex.data, data, size);
-
- err = InsertEvtQueue(&self->EventQueue, &entry);
- if(err != AL_NO_ERROR)
- free(entry.param.sysex.data);
- return err;
-}
diff --git a/Alc/midi/base.h b/Alc/midi/base.h
deleted file mode 100644
index 823e3802..00000000
--- a/Alc/midi/base.h
+++ /dev/null
@@ -1,133 +0,0 @@
-#ifndef AL_MIDI_BASE_H
-#define AL_MIDI_BASE_H
-
-#include "alMain.h"
-#include "atomic.h"
-#include "evtqueue.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ALsoundfont;
-
-typedef size_t (*ReaderCb)(void *ptr, size_t size, void *stream);
-typedef struct Reader {
- ReaderCb cb;
- void *ptr;
- int error;
-} Reader;
-inline size_t Reader_read(Reader *self, void *buf, size_t len)
-{
- size_t got = (!self->error) ? self->cb(buf, len, self->ptr) : 0;
- if(got < len) self->error = 1;
- return got;
-}
-#define READERR(x_) ((x_)->error)
-
-ALboolean loadSf2(Reader *stream, struct ALsoundfont *sfont, ALCcontext *context);
-
-
-#define MIDI_CLOCK_RES U64(1000000000)
-
-
-struct MidiSynthVtable;
-
-typedef struct MidiSynth {
- EvtQueue EventQueue;
-
- ALuint64 ClockBase;
- ALuint SamplesDone;
- ALuint SampleRate;
-
- /* NOTE: This rwlock is for the state and soundfont. The EventQueue and
- * related must instead use the device lock as they're used in the mixer
- * thread.
- */
- RWLock Lock;
-
- struct ALsoundfont **Soundfonts;
- ALsizei NumSoundfonts;
-
- volatile ALfloat Gain;
- volatile ALenum State;
-
- const struct MidiSynthVtable *vtbl;
-} MidiSynth;
-
-void MidiSynth_Construct(MidiSynth *self, ALCdevice *device);
-void MidiSynth_Destruct(MidiSynth *self);
-ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
-inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain) { self->Gain = gain; }
-inline ALfloat MidiSynth_getGain(const MidiSynth *self) { return self->Gain; }
-inline void MidiSynth_setState(MidiSynth *self, ALenum state) { self->State = state; }
-inline ALenum MidiSynth_getState(const MidiSynth *self) { return self->State; }
-void MidiSynth_stop(MidiSynth *self);
-inline void MidiSynth_reset(MidiSynth *self) { MidiSynth_stop(self); }
-inline ALuint64 MidiSynth_getTime(const MidiSynth *self)
-{ return self->ClockBase + (self->SamplesDone*MIDI_CLOCK_RES/self->SampleRate); }
-inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self)
-{
- if(self->EventQueue.pos == self->EventQueue.size)
- return UINT64_MAX;
- return self->EventQueue.events[self->EventQueue.pos].time;
-}
-void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate);
-inline void MidiSynth_update(MidiSynth *self, ALCdevice *device)
-{ MidiSynth_setSampleRate(self, device->Frequency); }
-ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2);
-ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size);
-
-
-struct MidiSynthVtable {
- void (*const Destruct)(MidiSynth *self);
-
- ALenum (*const selectSoundfonts)(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
-
- void (*const setGain)(MidiSynth *self, ALfloat gain);
-
- void (*const stop)(MidiSynth *self);
- void (*const reset)(MidiSynth *self);
-
- void (*const update)(MidiSynth *self, ALCdevice *device);
- void (*const process)(MidiSynth *self, ALuint samples, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels);
-
- void (*const Delete)(void *ptr);
-};
-
-#define DEFINE_MIDISYNTH_VTABLE(T) \
-DECLARE_THUNK(T, MidiSynth, void, Destruct) \
-DECLARE_THUNK3(T, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*) \
-DECLARE_THUNK1(T, MidiSynth, void, setGain, ALfloat) \
-DECLARE_THUNK(T, MidiSynth, void, stop) \
-DECLARE_THUNK(T, MidiSynth, void, reset) \
-DECLARE_THUNK1(T, MidiSynth, void, update, ALCdevice*) \
-DECLARE_THUNK3(T, MidiSynth, void, process, ALuint, ALfloatBUFFERSIZE*restrict, ALuint) \
-static void T##_MidiSynth_Delete(void *ptr) \
-{ T##_Delete(STATIC_UPCAST(T, MidiSynth, (MidiSynth*)ptr)); } \
- \
-static const struct MidiSynthVtable T##_MidiSynth_vtable = { \
- T##_MidiSynth_Destruct, \
- \
- T##_MidiSynth_selectSoundfonts, \
- T##_MidiSynth_setGain, \
- T##_MidiSynth_stop, \
- T##_MidiSynth_reset, \
- T##_MidiSynth_update, \
- T##_MidiSynth_process, \
- \
- T##_MidiSynth_Delete, \
-}
-
-
-MidiSynth *SSynth_create(ALCdevice *device);
-MidiSynth *FSynth_create(ALCdevice *device);
-MidiSynth *DSynth_create(ALCdevice *device);
-
-MidiSynth *SynthCreate(ALCdevice *device);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AL_MIDI_BASE_H */
diff --git a/Alc/midi/dummy.c b/Alc/midi/dummy.c
deleted file mode 100644
index 23c0d2cb..00000000
--- a/Alc/midi/dummy.c
+++ /dev/null
@@ -1,76 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "alMain.h"
-#include "alError.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-#include "alu.h"
-
-#include "midi/base.h"
-
-typedef struct DSynth {
- DERIVE_FROM_TYPE(MidiSynth);
-} DSynth;
-
-static void DSynth_Construct(DSynth *self, ALCdevice *device);
-static DECLARE_FORWARD(DSynth, MidiSynth, void, Destruct)
-static DECLARE_FORWARD3(DSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*)
-static DECLARE_FORWARD1(DSynth, MidiSynth, void, setGain, ALfloat)
-static DECLARE_FORWARD(DSynth, MidiSynth, void, stop)
-static DECLARE_FORWARD(DSynth, MidiSynth, void, reset)
-static DECLARE_FORWARD1(DSynth, MidiSynth, void, update, ALCdevice*)
-static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels);
-DECLARE_DEFAULT_ALLOCATORS(DSynth)
-DEFINE_MIDISYNTH_VTABLE(DSynth);
-
-
-static void DSynth_Construct(DSynth *self, ALCdevice *device)
-{
- MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
- SET_VTABLE2(DSynth, MidiSynth, self);
-}
-
-
-static void DSynth_processQueue(DSynth *self, ALuint64 time)
-{
- EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
-
- while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
- queue->pos++;
-}
-
-static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloatBUFFERSIZE*restrict UNUSED(DryBuffer), ALuint UNUSED(NumChannels))
-{
- MidiSynth *synth = STATIC_CAST(MidiSynth, self);
- ALuint64 curtime;
-
- if(synth->State != AL_PLAYING)
- return;
-
- synth->SamplesDone += SamplesToDo;
- synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
- synth->SamplesDone %= synth->SampleRate;
-
- curtime = MidiSynth_getTime(synth);
- DSynth_processQueue(self, maxi64(curtime-1, 0));
-}
-
-
-MidiSynth *DSynth_create(ALCdevice *device)
-{
- DSynth *synth;
-
- NEW_OBJ(synth, DSynth)(device);
- if(!synth)
- {
- ERR("Failed to allocate DSynth\n");
- return NULL;
- }
- return STATIC_CAST(MidiSynth, synth);
-}
diff --git a/Alc/midi/fluidsynth.c b/Alc/midi/fluidsynth.c
deleted file mode 100644
index 2236c812..00000000
--- a/Alc/midi/fluidsynth.c
+++ /dev/null
@@ -1,934 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "midi/base.h"
-
-#include "alMain.h"
-#include "alError.h"
-#include "alMidi.h"
-#include "alu.h"
-#include "compat.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-
-#ifdef HAVE_FLUIDSYNTH
-
-#include <fluidsynth.h>
-
-
-#ifdef HAVE_DYNLOAD
-#define FLUID_FUNCS(MAGIC) \
- MAGIC(new_fluid_synth); \
- MAGIC(delete_fluid_synth); \
- MAGIC(new_fluid_settings); \
- MAGIC(delete_fluid_settings); \
- MAGIC(fluid_settings_setint); \
- MAGIC(fluid_settings_setnum); \
- MAGIC(fluid_synth_noteon); \
- MAGIC(fluid_synth_noteoff); \
- MAGIC(fluid_synth_program_change); \
- MAGIC(fluid_synth_pitch_bend); \
- MAGIC(fluid_synth_channel_pressure); \
- MAGIC(fluid_synth_cc); \
- MAGIC(fluid_synth_sysex); \
- MAGIC(fluid_synth_bank_select); \
- MAGIC(fluid_synth_set_channel_type); \
- MAGIC(fluid_synth_all_sounds_off); \
- MAGIC(fluid_synth_system_reset); \
- MAGIC(fluid_synth_set_gain); \
- MAGIC(fluid_synth_set_sample_rate); \
- MAGIC(fluid_synth_write_float); \
- MAGIC(fluid_synth_add_sfloader); \
- MAGIC(fluid_synth_sfload); \
- MAGIC(fluid_synth_sfunload); \
- MAGIC(fluid_synth_alloc_voice); \
- MAGIC(fluid_synth_start_voice); \
- MAGIC(fluid_voice_gen_set); \
- MAGIC(fluid_voice_add_mod); \
- MAGIC(fluid_mod_set_source1); \
- MAGIC(fluid_mod_set_source2); \
- MAGIC(fluid_mod_set_amount); \
- MAGIC(fluid_mod_set_dest);
-
-void *fsynth_handle = NULL;
-#define DECL_FUNC(x) __typeof(x) *p##x
-FLUID_FUNCS(DECL_FUNC)
-#undef DECL_FUNC
-
-#define new_fluid_synth pnew_fluid_synth
-#define delete_fluid_synth pdelete_fluid_synth
-#define new_fluid_settings pnew_fluid_settings
-#define delete_fluid_settings pdelete_fluid_settings
-#define fluid_settings_setint pfluid_settings_setint
-#define fluid_settings_setnum pfluid_settings_setnum
-#define fluid_synth_noteon pfluid_synth_noteon
-#define fluid_synth_noteoff pfluid_synth_noteoff
-#define fluid_synth_program_change pfluid_synth_program_change
-#define fluid_synth_pitch_bend pfluid_synth_pitch_bend
-#define fluid_synth_channel_pressure pfluid_synth_channel_pressure
-#define fluid_synth_cc pfluid_synth_cc
-#define fluid_synth_sysex pfluid_synth_sysex
-#define fluid_synth_bank_select pfluid_synth_bank_select
-#define fluid_synth_set_channel_type pfluid_synth_set_channel_type
-#define fluid_synth_all_sounds_off pfluid_synth_all_sounds_off
-#define fluid_synth_system_reset pfluid_synth_system_reset
-#define fluid_synth_set_gain pfluid_synth_set_gain
-#define fluid_synth_set_sample_rate pfluid_synth_set_sample_rate
-#define fluid_synth_write_float pfluid_synth_write_float
-#define fluid_synth_add_sfloader pfluid_synth_add_sfloader
-#define fluid_synth_sfload pfluid_synth_sfload
-#define fluid_synth_sfunload pfluid_synth_sfunload
-#define fluid_synth_alloc_voice pfluid_synth_alloc_voice
-#define fluid_synth_start_voice pfluid_synth_start_voice
-#define fluid_voice_gen_set pfluid_voice_gen_set
-#define fluid_voice_add_mod pfluid_voice_add_mod
-#define fluid_mod_set_source1 pfluid_mod_set_source1
-#define fluid_mod_set_source2 pfluid_mod_set_source2
-#define fluid_mod_set_amount pfluid_mod_set_amount
-#define fluid_mod_set_dest pfluid_mod_set_dest
-
-static ALboolean LoadFSynth(void)
-{
- ALboolean ret = AL_TRUE;
- if(!fsynth_handle)
- {
- fsynth_handle = LoadLib("libfluidsynth.so.1");
- if(!fsynth_handle) return AL_FALSE;
-
-#define LOAD_FUNC(x) do { \
- p##x = GetSymbol(fsynth_handle, #x); \
- if(!p##x) ret = AL_FALSE; \
-} while(0)
- FLUID_FUNCS(LOAD_FUNC)
-#undef LOAD_FUNC
-
- if(ret == AL_FALSE)
- {
- CloseLib(fsynth_handle);
- fsynth_handle = NULL;
- }
- }
- return ret;
-}
-#else
-static inline ALboolean LoadFSynth(void) { return AL_TRUE; }
-#endif
-
-
-/* MIDI events */
-#define SYSEX_EVENT (0xF0)
-
-/* MIDI controllers */
-#define CTRL_BANKSELECT_MSB (0)
-#define CTRL_BANKSELECT_LSB (32)
-#define CTRL_ALLNOTESOFF (123)
-
-
-static int getModInput(ALenum input)
-{
- switch(input)
- {
- case AL_ONE_SOFT: return FLUID_MOD_NONE;
- case AL_NOTEON_VELOCITY_SOFT: return FLUID_MOD_VELOCITY;
- case AL_NOTEON_KEY_SOFT: return FLUID_MOD_KEY;
- case AL_KEYPRESSURE_SOFT: return FLUID_MOD_KEYPRESSURE;
- case AL_CHANNELPRESSURE_SOFT: return FLUID_MOD_CHANNELPRESSURE;
- case AL_PITCHBEND_SOFT: return FLUID_MOD_PITCHWHEEL;
- case AL_PITCHBEND_SENSITIVITY_SOFT: return FLUID_MOD_PITCHWHEELSENS;
- }
- return input&0x7F;
-}
-
-static int getModFlags(ALenum input, ALenum type, ALenum form)
-{
- int ret = 0;
-
- switch(type)
- {
- case AL_UNORM_SOFT: ret |= FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE; break;
- case AL_UNORM_REV_SOFT: ret |= FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE; break;
- case AL_SNORM_SOFT: ret |= FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE; break;
- case AL_SNORM_REV_SOFT: ret |= FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE; break;
- }
- switch(form)
- {
- case AL_LINEAR_SOFT: ret |= FLUID_MOD_LINEAR; break;
- case AL_CONCAVE_SOFT: ret |= FLUID_MOD_CONCAVE; break;
- case AL_CONVEX_SOFT: ret |= FLUID_MOD_CONVEX; break;
- case AL_SWITCH_SOFT: ret |= FLUID_MOD_SWITCH; break;
- }
- /* Source input values less than 128 correspond to a MIDI continuous
- * controller. Otherwise, it's a general controller. */
- if(input < 128) ret |= FLUID_MOD_CC;
- else ret |= FLUID_MOD_GC;
-
- return ret;
-}
-
-static enum fluid_gen_type getModDest(ALenum gen)
-{
- switch(gen)
- {
- case AL_MOD_LFO_TO_PITCH_SOFT: return GEN_MODLFOTOPITCH;
- case AL_VIBRATO_LFO_TO_PITCH_SOFT: return GEN_VIBLFOTOPITCH;
- case AL_MOD_ENV_TO_PITCH_SOFT: return GEN_MODENVTOPITCH;
- case AL_FILTER_CUTOFF_SOFT: return GEN_FILTERFC;
- case AL_FILTER_RESONANCE_SOFT: return GEN_FILTERQ;
- case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT: return GEN_MODLFOTOFILTERFC;
- case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT: return GEN_MODENVTOFILTERFC;
- case AL_MOD_LFO_TO_VOLUME_SOFT: return GEN_MODLFOTOVOL;
- case AL_CHORUS_SEND_SOFT: return GEN_CHORUSSEND;
- case AL_REVERB_SEND_SOFT: return GEN_REVERBSEND;
- case AL_PAN_SOFT: return GEN_PAN;
- case AL_MOD_LFO_DELAY_SOFT: return GEN_MODLFODELAY;
- case AL_MOD_LFO_FREQUENCY_SOFT: return GEN_MODLFOFREQ;
- case AL_VIBRATO_LFO_DELAY_SOFT: return GEN_VIBLFODELAY;
- case AL_VIBRATO_LFO_FREQUENCY_SOFT: return GEN_VIBLFOFREQ;
- case AL_MOD_ENV_DELAYTIME_SOFT: return GEN_MODENVDELAY;
- case AL_MOD_ENV_ATTACKTIME_SOFT: return GEN_MODENVATTACK;
- case AL_MOD_ENV_HOLDTIME_SOFT: return GEN_MODENVHOLD;
- case AL_MOD_ENV_DECAYTIME_SOFT: return GEN_MODENVDECAY;
- case AL_MOD_ENV_SUSTAINVOLUME_SOFT: return GEN_MODENVSUSTAIN;
- case AL_MOD_ENV_RELEASETIME_SOFT: return GEN_MODENVRELEASE;
- case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT: return GEN_KEYTOMODENVHOLD;
- case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT: return GEN_KEYTOMODENVDECAY;
- case AL_VOLUME_ENV_DELAYTIME_SOFT: return GEN_VOLENVDELAY;
- case AL_VOLUME_ENV_ATTACKTIME_SOFT: return GEN_VOLENVATTACK;
- case AL_VOLUME_ENV_HOLDTIME_SOFT: return GEN_VOLENVHOLD;
- case AL_VOLUME_ENV_DECAYTIME_SOFT: return GEN_VOLENVDECAY;
- case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT: return GEN_VOLENVSUSTAIN;
- case AL_VOLUME_ENV_RELEASETIME_SOFT: return GEN_VOLENVRELEASE;
- case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT: return GEN_KEYTOVOLENVHOLD;
- case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT: return GEN_KEYTOVOLENVDECAY;
- case AL_ATTENUATION_SOFT: return GEN_ATTENUATION;
- case AL_TUNING_COARSE_SOFT: return GEN_COARSETUNE;
- case AL_TUNING_FINE_SOFT: return GEN_FINETUNE;
- case AL_TUNING_SCALE_SOFT: return GEN_SCALETUNE;
- }
- ERR("Unhandled generator: 0x%04x\n", gen);
- return 0;
-}
-
-static int getSf2LoopMode(ALenum mode)
-{
- switch(mode)
- {
- case AL_NONE: return 0;
- case AL_LOOP_CONTINUOUS_SOFT: return 1;
- case AL_LOOP_UNTIL_RELEASE_SOFT: return 3;
- }
- return 0;
-}
-
-static int getSampleType(ALenum type)
-{
- switch(type)
- {
- case AL_MONO_SOFT: return FLUID_SAMPLETYPE_MONO;
- case AL_RIGHT_SOFT: return FLUID_SAMPLETYPE_RIGHT;
- case AL_LEFT_SOFT: return FLUID_SAMPLETYPE_LEFT;
- }
- return FLUID_SAMPLETYPE_MONO;
-}
-
-typedef struct FSample {
- DERIVE_FROM_TYPE(fluid_sample_t);
-
- ALfontsound *Sound;
-
- fluid_mod_t *Mods;
- ALsizei NumMods;
-} FSample;
-
-static void FSample_Construct(FSample *self, ALfontsound *sound)
-{
- fluid_sample_t *sample = STATIC_CAST(fluid_sample_t, self);
- ALbuffer *buffer = ATOMIC_LOAD(&sound->Buffer);
-
- memset(sample->name, 0, sizeof(sample->name));
- sample->start = sound->Start;
- sample->end = sound->End;
- sample->loopstart = sound->LoopStart;
- sample->loopend = sound->LoopEnd;
- sample->samplerate = sound->SampleRate;
- sample->origpitch = sound->PitchKey;
- sample->pitchadj = sound->PitchCorrection;
- sample->sampletype = getSampleType(sound->SampleType);
- sample->valid = !!buffer;
- sample->data = buffer ? buffer->data : NULL;
-
- sample->amplitude_that_reaches_noise_floor_is_valid = 0;
- sample->amplitude_that_reaches_noise_floor = 0.0;
-
- sample->refcount = 0;
-
- sample->notify = NULL;
-
- sample->userdata = self;
-
- self->Sound = sound;
-
- self->NumMods = 0;
- self->Mods = calloc(sound->ModulatorMap.size*4, sizeof(fluid_mod_t[4]));
- if(self->Mods)
- {
- ALsizei i, j, k;
-
- for(i = j = 0;i < sound->ModulatorMap.size;i++)
- {
- ALsfmodulator *mod = sound->ModulatorMap.array[i].value;
- for(k = 0;k < 4;k++,mod++)
- {
- if(mod->Dest == AL_NONE)
- continue;
- fluid_mod_set_source1(&self->Mods[j], getModInput(mod->Source[0].Input),
- getModFlags(mod->Source[0].Input, mod->Source[0].Type,
- mod->Source[0].Form));
- fluid_mod_set_source2(&self->Mods[j], getModInput(mod->Source[1].Input),
- getModFlags(mod->Source[1].Input, mod->Source[1].Type,
- mod->Source[1].Form));
- fluid_mod_set_amount(&self->Mods[j], mod->Amount);
- fluid_mod_set_dest(&self->Mods[j], getModDest(mod->Dest));
- self->Mods[j++].next = NULL;
- }
- }
- self->NumMods = j;
- }
-}
-
-static void FSample_Destruct(FSample *self)
-{
- free(self->Mods);
- self->Mods = NULL;
- self->NumMods = 0;
-}
-
-
-typedef struct FPreset {
- DERIVE_FROM_TYPE(fluid_preset_t);
-
- char Name[16];
-
- int Preset;
- int Bank;
-
- FSample *Samples;
- ALsizei NumSamples;
-} FPreset;
-
-static char* FPreset_getName(fluid_preset_t *preset);
-static int FPreset_getPreset(fluid_preset_t *preset);
-static int FPreset_getBank(fluid_preset_t *preset);
-static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int channel, int key, int velocity);
-
-static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *parent)
-{
- STATIC_CAST(fluid_preset_t, self)->data = self;
- STATIC_CAST(fluid_preset_t, self)->sfont = parent;
- STATIC_CAST(fluid_preset_t, self)->free = NULL;
- STATIC_CAST(fluid_preset_t, self)->get_name = FPreset_getName;
- STATIC_CAST(fluid_preset_t, self)->get_banknum = FPreset_getBank;
- STATIC_CAST(fluid_preset_t, self)->get_num = FPreset_getPreset;
- STATIC_CAST(fluid_preset_t, self)->noteon = FPreset_noteOn;
- STATIC_CAST(fluid_preset_t, self)->notify = NULL;
-
- memset(self->Name, 0, sizeof(self->Name));
- self->Preset = preset->Preset;
- self->Bank = preset->Bank;
-
- self->NumSamples = 0;
- self->Samples = calloc(1, preset->NumSounds * sizeof(self->Samples[0]));
- if(self->Samples)
- {
- ALsizei i;
- self->NumSamples = preset->NumSounds;
- for(i = 0;i < self->NumSamples;i++)
- FSample_Construct(&self->Samples[i], preset->Sounds[i]);
- }
-}
-
-static void FPreset_Destruct(FPreset *self)
-{
- ALsizei i;
-
- for(i = 0;i < self->NumSamples;i++)
- FSample_Destruct(&self->Samples[i]);
- free(self->Samples);
- self->Samples = NULL;
- self->NumSamples = 0;
-}
-
-static ALboolean FPreset_canDelete(FPreset *self)
-{
- ALsizei i;
- for(i = 0;i < self->NumSamples;i++)
- {
- if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t, &self->Samples[i])) != 0)
- return AL_FALSE;
- }
- return AL_TRUE;
-}
-
-static char* FPreset_getName(fluid_preset_t *preset)
-{
- return ((FPreset*)preset->data)->Name;
-}
-
-static int FPreset_getPreset(fluid_preset_t *preset)
-{
- return ((FPreset*)preset->data)->Preset;
-}
-
-static int FPreset_getBank(fluid_preset_t *preset)
-{
- return ((FPreset*)preset->data)->Bank;
-}
-
-static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int channel, int key, int vel)
-{
- FPreset *self = ((FPreset*)preset->data);
- ALsizei i;
-
- for(i = 0;i < self->NumSamples;i++)
- {
- FSample *sample = &self->Samples[i];
- ALfontsound *sound = sample->Sound;
- fluid_voice_t *voice;
- ALsizei m;
-
- if(!(key >= sound->MinKey && key <= sound->MaxKey && vel >= sound->MinVelocity && vel <= sound->MaxVelocity))
- continue;
-
- voice = fluid_synth_alloc_voice(synth, STATIC_CAST(fluid_sample_t, sample), channel, key, vel);
- if(voice == NULL) return FLUID_FAILED;
-
- fluid_voice_gen_set(voice, GEN_MODLFOTOPITCH, sound->ModLfoToPitch);
- fluid_voice_gen_set(voice, GEN_VIBLFOTOPITCH, sound->VibratoLfoToPitch);
- fluid_voice_gen_set(voice, GEN_MODENVTOPITCH, sound->ModEnvToPitch);
- fluid_voice_gen_set(voice, GEN_FILTERFC, sound->FilterCutoff);
- fluid_voice_gen_set(voice, GEN_FILTERQ, sound->FilterQ);
- fluid_voice_gen_set(voice, GEN_MODLFOTOFILTERFC, sound->ModLfoToFilterCutoff);
- fluid_voice_gen_set(voice, GEN_MODENVTOFILTERFC, sound->ModEnvToFilterCutoff);
- fluid_voice_gen_set(voice, GEN_MODLFOTOVOL, sound->ModLfoToVolume);
- fluid_voice_gen_set(voice, GEN_CHORUSSEND, sound->ChorusSend);
- fluid_voice_gen_set(voice, GEN_REVERBSEND, sound->ReverbSend);
- fluid_voice_gen_set(voice, GEN_PAN, sound->Pan);
- fluid_voice_gen_set(voice, GEN_MODLFODELAY, sound->ModLfo.Delay);
- fluid_voice_gen_set(voice, GEN_MODLFOFREQ, sound->ModLfo.Frequency);
- fluid_voice_gen_set(voice, GEN_VIBLFODELAY, sound->VibratoLfo.Delay);
- fluid_voice_gen_set(voice, GEN_VIBLFOFREQ, sound->VibratoLfo.Frequency);
- fluid_voice_gen_set(voice, GEN_MODENVDELAY, sound->ModEnv.DelayTime);
- fluid_voice_gen_set(voice, GEN_MODENVATTACK, sound->ModEnv.AttackTime);
- fluid_voice_gen_set(voice, GEN_MODENVHOLD, sound->ModEnv.HoldTime);
- fluid_voice_gen_set(voice, GEN_MODENVDECAY, sound->ModEnv.DecayTime);
- fluid_voice_gen_set(voice, GEN_MODENVSUSTAIN, sound->ModEnv.SustainAttn);
- fluid_voice_gen_set(voice, GEN_MODENVRELEASE, sound->ModEnv.ReleaseTime);
- fluid_voice_gen_set(voice, GEN_KEYTOMODENVHOLD, sound->ModEnv.KeyToHoldTime);
- fluid_voice_gen_set(voice, GEN_KEYTOMODENVDECAY, sound->ModEnv.KeyToDecayTime);
- fluid_voice_gen_set(voice, GEN_VOLENVDELAY, sound->VolEnv.DelayTime);
- fluid_voice_gen_set(voice, GEN_VOLENVATTACK, sound->VolEnv.AttackTime);
- fluid_voice_gen_set(voice, GEN_VOLENVHOLD, sound->VolEnv.HoldTime);
- fluid_voice_gen_set(voice, GEN_VOLENVDECAY, sound->VolEnv.DecayTime);
- fluid_voice_gen_set(voice, GEN_VOLENVSUSTAIN, sound->VolEnv.SustainAttn);
- fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, sound->VolEnv.ReleaseTime);
- fluid_voice_gen_set(voice, GEN_KEYTOVOLENVHOLD, sound->VolEnv.KeyToHoldTime);
- fluid_voice_gen_set(voice, GEN_KEYTOVOLENVDECAY, sound->VolEnv.KeyToDecayTime);
- fluid_voice_gen_set(voice, GEN_ATTENUATION, sound->Attenuation);
- fluid_voice_gen_set(voice, GEN_COARSETUNE, sound->CoarseTuning);
- fluid_voice_gen_set(voice, GEN_FINETUNE, sound->FineTuning);
- fluid_voice_gen_set(voice, GEN_SAMPLEMODE, getSf2LoopMode(sound->LoopMode));
- fluid_voice_gen_set(voice, GEN_SCALETUNE, sound->TuningScale);
- fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, sound->ExclusiveClass);
- for(m = 0;m < sample->NumMods;m++)
- fluid_voice_add_mod(voice, &sample->Mods[m], FLUID_VOICE_OVERWRITE);
-
- fluid_synth_start_voice(synth, voice);
- }
-
- return FLUID_OK;
-}
-
-
-typedef struct FSfont {
- DERIVE_FROM_TYPE(fluid_sfont_t);
-
- char Name[16];
-
- FPreset *Presets;
- ALsizei NumPresets;
-
- ALsizei CurrentPos;
-} FSfont;
-
-static int FSfont_free(fluid_sfont_t *sfont);
-static char* FSfont_getName(fluid_sfont_t *sfont);
-static fluid_preset_t* FSfont_getPreset(fluid_sfont_t *sfont, unsigned int bank, unsigned int prenum);
-static void FSfont_iterStart(fluid_sfont_t *sfont);
-static int FSfont_iterNext(fluid_sfont_t *sfont, fluid_preset_t *preset);
-
-static void FSfont_Construct(FSfont *self, ALsoundfont *sfont)
-{
- STATIC_CAST(fluid_sfont_t, self)->data = self;
- STATIC_CAST(fluid_sfont_t, self)->id = FLUID_FAILED;
- STATIC_CAST(fluid_sfont_t, self)->free = FSfont_free;
- STATIC_CAST(fluid_sfont_t, self)->get_name = FSfont_getName;
- STATIC_CAST(fluid_sfont_t, self)->get_preset = FSfont_getPreset;
- STATIC_CAST(fluid_sfont_t, self)->iteration_start = FSfont_iterStart;
- STATIC_CAST(fluid_sfont_t, self)->iteration_next = FSfont_iterNext;
-
- memset(self->Name, 0, sizeof(self->Name));
- self->CurrentPos = 0;
- self->NumPresets = 0;
- self->Presets = calloc(1, sfont->NumPresets * sizeof(self->Presets[0]));
- if(self->Presets)
- {
- ALsizei i;
- self->NumPresets = sfont->NumPresets;
- for(i = 0;i < self->NumPresets;i++)
- FPreset_Construct(&self->Presets[i], sfont->Presets[i], STATIC_CAST(fluid_sfont_t, self));
- }
-}
-
-static void FSfont_Destruct(FSfont *self)
-{
- ALsizei i;
-
- for(i = 0;i < self->NumPresets;i++)
- FPreset_Destruct(&self->Presets[i]);
- free(self->Presets);
- self->Presets = NULL;
- self->NumPresets = 0;
- self->CurrentPos = 0;
-}
-
-static int FSfont_free(fluid_sfont_t *sfont)
-{
- FSfont *self = STATIC_UPCAST(FSfont, fluid_sfont_t, sfont);
- ALsizei i;
-
- for(i = 0;i < self->NumPresets;i++)
- {
- if(!FPreset_canDelete(&self->Presets[i]))
- return 1;
- }
-
- FSfont_Destruct(self);
- free(self);
- return 0;
-}
-
-static char* FSfont_getName(fluid_sfont_t *sfont)
-{
- return STATIC_UPCAST(FSfont, fluid_sfont_t, sfont)->Name;
-}
-
-static fluid_preset_t *FSfont_getPreset(fluid_sfont_t *sfont, unsigned int bank, unsigned int prenum)
-{
- FSfont *self = STATIC_UPCAST(FSfont, fluid_sfont_t, sfont);
- ALsizei i;
-
- for(i = 0;i < self->NumPresets;i++)
- {
- FPreset *preset = &self->Presets[i];
- if(preset->Bank == (int)bank && preset->Preset == (int)prenum)
- return STATIC_CAST(fluid_preset_t, preset);
- }
-
- return NULL;
-}
-
-static void FSfont_iterStart(fluid_sfont_t *sfont)
-{
- STATIC_UPCAST(FSfont, fluid_sfont_t, sfont)->CurrentPos = 0;
-}
-
-static int FSfont_iterNext(fluid_sfont_t *sfont, fluid_preset_t *preset)
-{
- FSfont *self = STATIC_UPCAST(FSfont, fluid_sfont_t, sfont);
- if(self->CurrentPos >= self->NumPresets)
- return 0;
- *preset = *STATIC_CAST(fluid_preset_t, &self->Presets[self->CurrentPos++]);
- preset->free = NULL;
- return 1;
-}
-
-
-typedef struct FSynth {
- DERIVE_FROM_TYPE(MidiSynth);
- DERIVE_FROM_TYPE(fluid_sfloader_t);
-
- fluid_settings_t *Settings;
- fluid_synth_t *Synth;
- int *FontIDs;
- ALsizei NumFontIDs;
-
- ALboolean ForceGM2BankSelect;
- ALfloat GainScale;
-} FSynth;
-
-static void FSynth_Construct(FSynth *self, ALCdevice *device);
-static void FSynth_Destruct(FSynth *self);
-static ALboolean FSynth_init(FSynth *self, ALCdevice *device);
-static ALenum FSynth_selectSoundfonts(FSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
-static void FSynth_setGain(FSynth *self, ALfloat gain);
-static void FSynth_stop(FSynth *self);
-static void FSynth_reset(FSynth *self);
-static void FSynth_update(FSynth *self, ALCdevice *device);
-static void FSynth_processQueue(FSynth *self, ALuint64 time);
-static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels);
-DECLARE_DEFAULT_ALLOCATORS(FSynth)
-DEFINE_MIDISYNTH_VTABLE(FSynth);
-
-static fluid_sfont_t *FSynth_loadSfont(fluid_sfloader_t *loader, const char *filename);
-
-
-static void FSynth_Construct(FSynth *self, ALCdevice *device)
-{
- MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
- SET_VTABLE2(FSynth, MidiSynth, self);
-
- STATIC_CAST(fluid_sfloader_t, self)->data = self;
- STATIC_CAST(fluid_sfloader_t, self)->free = NULL;
- STATIC_CAST(fluid_sfloader_t, self)->load = FSynth_loadSfont;
-
- self->Settings = NULL;
- self->Synth = NULL;
- self->FontIDs = NULL;
- self->NumFontIDs = 0;
- self->ForceGM2BankSelect = AL_FALSE;
- self->GainScale = 0.2f;
-}
-
-static void FSynth_Destruct(FSynth *self)
-{
- ALsizei i;
-
- for(i = 0;i < self->NumFontIDs;i++)
- fluid_synth_sfunload(self->Synth, self->FontIDs[i], 0);
- free(self->FontIDs);
- self->FontIDs = NULL;
- self->NumFontIDs = 0;
-
- if(self->Synth != NULL)
- delete_fluid_synth(self->Synth);
- self->Synth = NULL;
-
- if(self->Settings != NULL)
- delete_fluid_settings(self->Settings);
- self->Settings = NULL;
-
- MidiSynth_Destruct(STATIC_CAST(MidiSynth, self));
-}
-
-static ALboolean FSynth_init(FSynth *self, ALCdevice *device)
-{
- ALfloat vol;
-
- if(ConfigValueFloat(NULL, "midi", "volume", &vol))
- {
- if(!(vol <= 0.0f))
- {
- ERR("MIDI volume %f clamped to 0\n", vol);
- vol = 0.0f;
- }
- self->GainScale = powf(10.0f, vol / 20.0f);
- }
-
- self->Settings = new_fluid_settings();
- if(!self->Settings)
- {
- ERR("Failed to create FluidSettings\n");
- return AL_FALSE;
- }
-
- fluid_settings_setint(self->Settings, "synth.polyphony", 256);
- fluid_settings_setnum(self->Settings, "synth.gain", self->GainScale);
- fluid_settings_setnum(self->Settings, "synth.sample-rate", device->Frequency);
-
- self->Synth = new_fluid_synth(self->Settings);
- if(!self->Synth)
- {
- ERR("Failed to create FluidSynth\n");
- return AL_FALSE;
- }
-
- fluid_synth_add_sfloader(self->Synth, STATIC_CAST(fluid_sfloader_t, self));
-
- return AL_TRUE;
-}
-
-
-static fluid_sfont_t *FSynth_loadSfont(fluid_sfloader_t *loader, const char *filename)
-{
- FSynth *self = STATIC_UPCAST(FSynth, fluid_sfloader_t, loader);
- FSfont *sfont;
- int idx;
-
- if(!filename || sscanf(filename, "_al_internal %d", &idx) != 1)
- return NULL;
- if(idx < 0 || idx >= STATIC_CAST(MidiSynth, self)->NumSoundfonts)
- {
- ERR("Received invalid soundfont index %d (max: %d)\n", idx, STATIC_CAST(MidiSynth, self)->NumSoundfonts);
- return NULL;
- }
-
- sfont = calloc(1, sizeof(sfont[0]));
- if(!sfont) return NULL;
-
- FSfont_Construct(sfont, STATIC_CAST(MidiSynth, self)->Soundfonts[idx]);
- return STATIC_CAST(fluid_sfont_t, sfont);
-}
-
-static ALenum FSynth_selectSoundfonts(FSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
-{
- int *fontid;
- ALenum ret;
- ALsizei i;
-
- ret = MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth, self), context, count, ids);
- if(ret != AL_NO_ERROR) return ret;
-
- ALCdevice_Lock(context->Device);
- for(i = 0;i < 16;i++)
- fluid_synth_all_sounds_off(self->Synth, i);
- ALCdevice_Unlock(context->Device);
-
- fontid = malloc(count * sizeof(fontid[0]));
- if(fontid)
- {
- for(i = 0;i < STATIC_CAST(MidiSynth, self)->NumSoundfonts;i++)
- {
- char name[16];
- snprintf(name, sizeof(name), "_al_internal %d", i);
-
- fontid[i] = fluid_synth_sfload(self->Synth, name, 0);
- if(fontid[i] == FLUID_FAILED)
- ERR("Failed to load selected soundfont %d\n", i);
- }
-
- fontid = ExchangePtr((XchgPtr*)&self->FontIDs, fontid);
- count = ExchangeInt(&self->NumFontIDs, count);
- }
- else
- {
- ERR("Failed to allocate space for %d font IDs!\n", count);
- fontid = self->FontIDs;
- count = self->NumFontIDs;
- self->FontIDs = NULL;
- self->NumFontIDs = 0;
- }
-
- for(i = 0;i < count;i++)
- fluid_synth_sfunload(self->Synth, fontid[i], 0);
- free(fontid);
-
- return ret;
-}
-
-
-static void FSynth_setGain(FSynth *self, ALfloat gain)
-{
- fluid_settings_setnum(self->Settings, "synth.gain", self->GainScale * gain);
- fluid_synth_set_gain(self->Synth, self->GainScale * gain);
- MidiSynth_setGain(STATIC_CAST(MidiSynth, self), gain);
-}
-
-
-static void FSynth_stop(FSynth *self)
-{
- MidiSynth *synth = STATIC_CAST(MidiSynth, self);
- ALuint64 curtime;
- ALsizei chan;
-
- /* Make sure all pending events are processed. */
- curtime = MidiSynth_getTime(synth);
- FSynth_processQueue(self, curtime);
-
- /* All notes off */
- for(chan = 0;chan < 16;chan++)
- fluid_synth_cc(self->Synth, chan, CTRL_ALLNOTESOFF, 0);
-
- MidiSynth_stop(STATIC_CAST(MidiSynth, self));
-}
-
-static void FSynth_reset(FSynth *self)
-{
- /* Reset to power-up status. */
- fluid_synth_system_reset(self->Synth);
-
- MidiSynth_reset(STATIC_CAST(MidiSynth, self));
-}
-
-
-static void FSynth_update(FSynth *self, ALCdevice *device)
-{
- fluid_settings_setnum(self->Settings, "synth.sample-rate", device->Frequency);
- fluid_synth_set_sample_rate(self->Synth, device->Frequency);
- MidiSynth_update(STATIC_CAST(MidiSynth, self), device);
-}
-
-
-static void FSynth_processQueue(FSynth *self, ALuint64 time)
-{
- EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
-
- while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
- {
- const MidiEvent *evt = &queue->events[queue->pos];
-
- if(evt->event == SYSEX_EVENT)
- {
- static const ALbyte gm2_on[] = { 0x7E, 0x7F, 0x09, 0x03 };
- static const ALbyte gm2_off[] = { 0x7E, 0x7F, 0x09, 0x02 };
- int handled = 0;
-
- fluid_synth_sysex(self->Synth, evt->param.sysex.data, evt->param.sysex.size, NULL, NULL, &handled, 0);
- if(!handled && evt->param.sysex.size >= (ALsizei)sizeof(gm2_on))
- {
- if(memcmp(evt->param.sysex.data, gm2_on, sizeof(gm2_on)) == 0)
- self->ForceGM2BankSelect = AL_TRUE;
- else if(memcmp(evt->param.sysex.data, gm2_off, sizeof(gm2_off)) == 0)
- self->ForceGM2BankSelect = AL_FALSE;
- }
- }
- else switch((evt->event&0xF0))
- {
- case AL_NOTEOFF_SOFT:
- 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.val[0], evt->param.val[1]);
- break;
- case AL_KEYPRESSURE_SOFT:
- break;
-
- case AL_CONTROLLERCHANGE_SOFT:
- if(self->ForceGM2BankSelect)
- {
- int chan = (evt->event&0x0F);
- if(evt->param.val[0] == CTRL_BANKSELECT_MSB)
- {
- if(evt->param.val[1] == 120 && (chan == 9 || chan == 10))
- fluid_synth_set_channel_type(self->Synth, chan, CHANNEL_TYPE_DRUM);
- else if(evt->param.val[1] == 121)
- fluid_synth_set_channel_type(self->Synth, chan, CHANNEL_TYPE_MELODIC);
- break;
- }
- if(evt->param.val[0] == CTRL_BANKSELECT_LSB)
- {
- fluid_synth_bank_select(self->Synth, chan, evt->param.val[1]);
- break;
- }
- }
- 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.val[0]);
- break;
-
- case AL_CHANNELPRESSURE_SOFT:
- 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.val[0]&0x7F) |
- ((evt->param.val[1]&0x7F)<<7));
- break;
- }
-
- queue->pos++;
- }
-}
-
-static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels)
-{
- MidiSynth *synth = STATIC_CAST(MidiSynth, self);
- ALfloat *LeftBuffer = DryBuffer[0];
- ALfloat *RightBuffer = DryBuffer[(NumChannels > 1) ? 1 : 0];
- ALenum state = synth->State;
- ALuint64 curtime;
- ALuint total = 0;
-
- if(state == AL_INITIAL)
- return;
- if(state != AL_PLAYING)
- {
- fluid_synth_write_float(self->Synth, SamplesToDo, LeftBuffer, 0, 1,
- RightBuffer, 0, 1);
- return;
- }
-
- curtime = MidiSynth_getTime(synth);
- while(total < SamplesToDo)
- {
- ALuint64 time, diff;
- ALint tonext;
-
- time = MidiSynth_getNextEvtTime(synth);
- diff = maxu64(time, curtime) - curtime;
- if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX)
- {
- /* If there's no pending event, or if it's more than 1 second
- * away, do as many samples as we can. */
- tonext = INT_MAX;
- }
- else
- {
- /* Figure out how many samples until the next event. */
- tonext = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES);
- tonext -= total;
- }
-
- if(tonext > 0)
- {
- ALuint todo = minu(tonext, SamplesToDo-total);
- fluid_synth_write_float(self->Synth, todo, LeftBuffer, total, 1,
- RightBuffer, total, 1);
- total += todo;
- tonext -= todo;
- }
- if(total < SamplesToDo && tonext <= 0)
- FSynth_processQueue(self, time);
- }
-
- synth->SamplesDone += SamplesToDo;
- synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
- synth->SamplesDone %= synth->SampleRate;
-}
-
-
-MidiSynth *FSynth_create(ALCdevice *device)
-{
- FSynth *synth;
-
- if(!LoadFSynth())
- return NULL;
-
- NEW_OBJ(synth, FSynth)(device);
- if(!synth)
- {
- ERR("Failed to allocate FSynth\n");
- return NULL;
- }
-
- if(FSynth_init(synth, device) == AL_FALSE)
- {
- DELETE_OBJ(STATIC_CAST(MidiSynth, synth));
- return NULL;
- }
-
- return STATIC_CAST(MidiSynth, synth);
-}
-
-#else
-
-MidiSynth *FSynth_create(ALCdevice* UNUSED(device))
-{
- return NULL;
-}
-
-#endif
diff --git a/Alc/midi/sf2load.c b/Alc/midi/sf2load.c
deleted file mode 100644
index 31f6ee02..00000000
--- a/Alc/midi/sf2load.c
+++ /dev/null
@@ -1,1373 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "alMain.h"
-#include "alMidi.h"
-#include "alError.h"
-#include "alu.h"
-
-#include "midi/base.h"
-
-
-static ALuint read_le32(Reader *stream)
-{
- ALubyte buf[4];
- if(Reader_read(stream, buf, 4) != 4)
- return 0;
- return (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
-}
-static ALushort read_le16(Reader *stream)
-{
- ALubyte buf[2];
- if(Reader_read(stream, buf, 2) != 2)
- return 0;
- return (buf[1]<<8) | buf[0];
-}
-static ALubyte read_8(Reader *stream)
-{
- ALubyte buf[1];
- if(Reader_read(stream, buf, 1) != 1)
- return 0;
- return buf[0];
-}
-static void skip(Reader *stream, ALuint amt)
-{
- while(amt > 0 && !READERR(stream))
- {
- char buf[4096];
- amt -= Reader_read(stream, buf, minu(sizeof(buf), amt));
- }
-}
-
-typedef struct Generator {
- ALushort mGenerator;
- ALushort mAmount;
-} Generator;
-static void Generator_read(Generator *self, Reader *stream)
-{
- self->mGenerator = read_le16(stream);
- self->mAmount = read_le16(stream);
-}
-
-static const ALint DefaultGenValue[60] = {
- 0, /* 0 - startAddrOffset */
- 0, /* 1 - endAddrOffset */
- 0, /* 2 - startloopAddrOffset */
- 0, /* 3 - endloopAddrOffset */
- 0, /* 4 - startAddrCoarseOffset */
- 0, /* 5 - modLfoToPitch */
- 0, /* 6 - vibLfoToPitch */
- 0, /* 7 - modEnvToPitch */
- 13500, /* 8 - initialFilterFc */
- 0, /* 9 - initialFilterQ */
- 0, /* 10 - modLfoToFilterFc */
- 0, /* 11 - modEnvToFilterFc */
- 0, /* 12 - endAddrCoarseOffset */
- 0, /* 13 - modLfoToVolume */
- 0, /* 14 - */
- 0, /* 15 - chorusEffectsSend */
- 0, /* 16 - reverbEffectsSend */
- 0, /* 17 - pan */
- 0, /* 18 - */
- 0, /* 19 - */
- 0, /* 20 - */
- -12000, /* 21 - delayModLFO */
- 0, /* 22 - freqModLFO */
- -12000, /* 23 - delayVibLFO */
- 0, /* 24 - freqVibLFO */
- -12000, /* 25 - delayModEnv */
- -12000, /* 26 - attackModEnv */
- -12000, /* 27 - holdModEnv */
- -12000, /* 28 - decayModEnv */
- 0, /* 29 - sustainModEnv */
- -12000, /* 30 - releaseModEnv */
- 0, /* 31 - keynumToModEnvHold */
- 0, /* 32 - keynumToModEnvDecay */
- -12000, /* 33 - delayVolEnv */
- -12000, /* 34 - attackVolEnv */
- -12000, /* 35 - holdVolEnv */
- -12000, /* 36 - decayVolEnv */
- 0, /* 37 - sustainVolEnv */
- -12000, /* 38 - releaseVolEnv */
- 0, /* 39 - keynumToVolEnvHold */
- 0, /* 40 - keynumToVolEnvDecay */
- 0, /* 41 - */
- 0, /* 42 - */
- 0, /* 43 - keyRange */
- 0, /* 44 - velRange */
- 0, /* 45 - startloopAddrCoarseOffset */
- 0, /* 46 - keynum */
- 0, /* 47 - velocity */
- 0, /* 48 - initialAttenuation */
- 0, /* 49 - */
- 0, /* 50 - endloopAddrCoarseOffset */
- 0, /* 51 - corseTune */
- 0, /* 52 - fineTune */
- 0, /* 53 - */
- 0, /* 54 - sampleModes */
- 0, /* 55 - */
- 100, /* 56 - scaleTuning */
- 0, /* 57 - exclusiveClass */
- 0, /* 58 - overridingRootKey */
- 0, /* 59 - */
-};
-
-typedef struct Modulator {
- ALushort mSrcOp;
- ALushort mDstOp;
- ALshort mAmount;
- ALushort mAmtSrcOp;
- ALushort mTransOp;
-} Modulator;
-static void Modulator_read(Modulator *self, Reader *stream)
-{
- self->mSrcOp = read_le16(stream);
- self->mDstOp = read_le16(stream);
- self->mAmount = read_le16(stream);
- self->mAmtSrcOp = read_le16(stream);
- self->mTransOp = read_le16(stream);
-}
-
-typedef struct Zone {
- ALushort mGenIdx;
- ALushort mModIdx;
-} Zone;
-static void Zone_read(Zone *self, Reader *stream)
-{
- self->mGenIdx = read_le16(stream);
- self->mModIdx = read_le16(stream);
-}
-
-typedef struct PresetHeader {
- ALchar mName[20];
- ALushort mPreset; /* MIDI program number */
- ALushort mBank;
- ALushort mZoneIdx;
- ALuint mLibrary;
- ALuint mGenre;
- ALuint mMorphology;
-} PresetHeader;
-static void PresetHeader_read(PresetHeader *self, Reader *stream)
-{
- Reader_read(stream, self->mName, sizeof(self->mName));
- self->mPreset = read_le16(stream);
- self->mBank = read_le16(stream);
- self->mZoneIdx = read_le16(stream);
- self->mLibrary = read_le32(stream);
- self->mGenre = read_le32(stream);
- self->mMorphology = read_le32(stream);
-}
-
-typedef struct InstrumentHeader {
- ALchar mName[20];
- ALushort mZoneIdx;
-} InstrumentHeader;
-static void InstrumentHeader_read(InstrumentHeader *self, Reader *stream)
-{
- Reader_read(stream, self->mName, sizeof(self->mName));
- self->mZoneIdx = read_le16(stream);
-}
-
-typedef struct SampleHeader {
- ALchar mName[20];
- ALuint mStart;
- ALuint mEnd;
- ALuint mStartloop;
- ALuint mEndloop;
- ALuint mSampleRate;
- ALubyte mOriginalKey;
- ALbyte mCorrection;
- ALushort mSampleLink;
- ALushort mSampleType;
-} SampleHeader;
-static void SampleHeader_read(SampleHeader *self, Reader *stream)
-{
- Reader_read(stream, self->mName, sizeof(self->mName));
- self->mStart = read_le32(stream);
- self->mEnd = read_le32(stream);
- self->mStartloop = read_le32(stream);
- self->mEndloop = read_le32(stream);
- self->mSampleRate = read_le32(stream);
- self->mOriginalKey = read_8(stream);
- self->mCorrection = read_8(stream);
- self->mSampleLink = read_le16(stream);
- self->mSampleType = read_le16(stream);
-}
-
-
-typedef struct Soundfont {
- ALuint ifil;
- ALchar *irom;
-
- PresetHeader *phdr;
- ALsizei phdr_size;
-
- Zone *pbag;
- ALsizei pbag_size;
- Modulator *pmod;
- ALsizei pmod_size;
- Generator *pgen;
- ALsizei pgen_size;
-
- InstrumentHeader *inst;
- ALsizei inst_size;
-
- Zone *ibag;
- ALsizei ibag_size;
- Modulator *imod;
- ALsizei imod_size;
- Generator *igen;
- ALsizei igen_size;
-
- SampleHeader *shdr;
- ALsizei shdr_size;
-} Soundfont;
-
-static void Soundfont_Construct(Soundfont *self)
-{
- self->ifil = 0;
- self->irom = NULL;
-
- self->phdr = NULL;
- self->phdr_size = 0;
-
- self->pbag = NULL;
- self->pbag_size = 0;
- self->pmod = NULL;
- self->pmod_size = 0;
- self->pgen = NULL;
- self->pgen_size = 0;
-
- self->inst = NULL;
- self->inst_size = 0;
-
- self->ibag = NULL;
- self->ibag_size = 0;
- self->imod = NULL;
- self->imod_size = 0;
- self->igen = NULL;
- self->igen_size = 0;
-
- self->shdr = NULL;
- self->shdr_size = 0;
-}
-
-static void Soundfont_Destruct(Soundfont *self)
-{
- free(self->irom);
- self->irom = NULL;
-
- free(self->phdr);
- self->phdr = NULL;
- self->phdr_size = 0;
-
- free(self->pbag);
- self->pbag = NULL;
- self->pbag_size = 0;
- free(self->pmod);
- self->pmod = NULL;
- self->pmod_size = 0;
- free(self->pgen);
- self->pgen = NULL;
- self->pgen_size = 0;
-
- free(self->inst);
- self->inst = NULL;
- self->inst_size = 0;
-
- free(self->ibag);
- self->ibag = NULL;
- self->ibag_size = 0;
- free(self->imod);
- self->imod = NULL;
- self->imod_size = 0;
- free(self->igen);
- self->igen = NULL;
- self->igen_size = 0;
-
- free(self->shdr);
- self->shdr = NULL;
- self->shdr_size = 0;
-}
-
-
-#define FOURCC(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
-#define FOURCCFMT "%c%c%c%c"
-#define FOURCCARGS(x) (char)((x)&0xff), (char)(((x)>>8)&0xff), (char)(((x)>>16)&0xff), (char)(((x)>>24)&0xff)
-typedef struct RiffHdr {
- ALuint mCode;
- ALuint mSize;
-} RiffHdr;
-static void RiffHdr_read(RiffHdr *self, Reader *stream)
-{
- self->mCode = read_le32(stream);
- self->mSize = read_le32(stream);
-}
-
-
-typedef struct GenModList {
- VECTOR(Generator) gens;
- VECTOR(Modulator) mods;
-} GenModList;
-
-static void GenModList_Construct(GenModList *self)
-{
- VECTOR_INIT(self->gens);
- VECTOR_INIT(self->mods);
-}
-
-static void GenModList_Destruct(GenModList *self)
-{
- VECTOR_DEINIT(self->mods);
- VECTOR_DEINIT(self->gens);
-}
-
-static GenModList GenModList_clone(const GenModList *self)
-{
- GenModList ret;
-
- GenModList_Construct(&ret);
-
- VECTOR_INSERT(ret.gens, VECTOR_ITER_END(ret.gens),
- VECTOR_ITER_BEGIN(self->gens), VECTOR_ITER_END(self->gens)
- );
- VECTOR_INSERT(ret.mods, VECTOR_ITER_END(ret.mods),
- VECTOR_ITER_BEGIN(self->mods), VECTOR_ITER_END(self->mods)
- );
-
- return ret;
-}
-
-static void GenModList_insertGen(GenModList *self, const Generator *gen, ALboolean ispreset)
-{
- Generator *i;
-#define MATCH_GENERATOR(i) ((i)->mGenerator == gen->mGenerator)
- VECTOR_FIND_IF(i, Generator, self->gens, MATCH_GENERATOR);
- if(i != VECTOR_ITER_END(self->gens))
- {
- i->mAmount = gen->mAmount;
- return;
- }
-#undef MATCH_GENERATOR
-
- if(ispreset &&
- (gen->mGenerator == 0 || gen->mGenerator == 1 || gen->mGenerator == 2 ||
- gen->mGenerator == 3 || gen->mGenerator == 4 || gen->mGenerator == 12 ||
- gen->mGenerator == 45 || gen->mGenerator == 46 || gen->mGenerator == 47 ||
- gen->mGenerator == 50 || gen->mGenerator == 54 || gen->mGenerator == 57 ||
- gen->mGenerator == 58))
- return;
-
- if(VECTOR_PUSH_BACK(self->gens, *gen) == AL_FALSE)
- {
- ERR("Failed to insert generator (from "SZFMT" elements)\n", VECTOR_SIZE(self->gens));
- return;
- }
-}
-static void GenModList_accumGen(GenModList *self, const Generator *gen)
-{
- Generator *i;
-#define MATCH_GENERATOR(i) ((i)->mGenerator == gen->mGenerator)
- VECTOR_FIND_IF(i, Generator, self->gens, MATCH_GENERATOR);
- if(i != VECTOR_ITER_END(self->gens))
- {
- if(gen->mGenerator == 43 || gen->mGenerator == 44)
- {
- /* Range generators accumulate by taking the intersection of the
- * two ranges.
- */
- ALushort low = maxu(i->mAmount&0x00ff, gen->mAmount&0x00ff);
- ALushort high = minu(i->mAmount&0xff00, gen->mAmount&0xff00);
- i->mAmount = low | high;
- }
- else
- i->mAmount += gen->mAmount;
- return;
- }
-#undef MATCH_GENERATOR
-
- if(VECTOR_PUSH_BACK(self->gens, *gen) == AL_FALSE)
- {
- ERR("Failed to insert generator (from "SZFMT" elements)\n", VECTOR_SIZE(self->gens));
- return;
- }
- if(gen->mGenerator < 60)
- VECTOR_BACK(self->gens).mAmount += DefaultGenValue[gen->mGenerator];
-}
-
-static void GenModList_insertMod(GenModList *self, const Modulator *mod)
-{
- Modulator *i;
-#define MATCH_MODULATOR(i) ((i)->mDstOp == mod->mDstOp && (i)->mSrcOp == mod->mSrcOp && \
- (i)->mAmtSrcOp == mod->mAmtSrcOp && (i)->mTransOp == mod->mTransOp)
- VECTOR_FIND_IF(i, Modulator, self->mods, MATCH_MODULATOR);
- if(i != VECTOR_ITER_END(self->mods))
- {
- i->mAmount = mod->mAmount;
- return;
- }
-#undef MATCH_MODULATOR
-
- if(VECTOR_PUSH_BACK(self->mods, *mod) == AL_FALSE)
- {
- ERR("Failed to insert modulator (from "SZFMT" elements)\n", VECTOR_SIZE(self->mods));
- return;
- }
-}
-static void GenModList_accumMod(GenModList *self, const Modulator *mod)
-{
- Modulator *i;
-#define MATCH_MODULATOR(i) ((i)->mDstOp == mod->mDstOp && (i)->mSrcOp == mod->mSrcOp && \
- (i)->mAmtSrcOp == mod->mAmtSrcOp && (i)->mTransOp == mod->mTransOp)
- VECTOR_FIND_IF(i, Modulator, self->mods, MATCH_MODULATOR);
- if(i != VECTOR_ITER_END(self->mods))
- {
- i->mAmount += mod->mAmount;
- return;
- }
-#undef MATCH_MODULATOR
-
- if(VECTOR_PUSH_BACK(self->mods, *mod) == AL_FALSE)
- {
- ERR("Failed to insert modulator (from "SZFMT" elements)\n", VECTOR_SIZE(self->mods));
- return;
- }
-
- if(mod->mSrcOp == 0x0502 && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 960;
- else if(mod->mSrcOp == 0x0102 && mod->mDstOp == 8 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += -2400;
- else if(mod->mSrcOp == 0x000D && mod->mDstOp == 6 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 50;
- else if(mod->mSrcOp == 0x0081 && mod->mDstOp == 6 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 50;
- else if(mod->mSrcOp == 0x0582 && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 960;
- else if(mod->mSrcOp == 0x028A && mod->mDstOp == 17 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 1000;
- else if(mod->mSrcOp == 0x058B && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 960;
- else if(mod->mSrcOp == 0x00DB && mod->mDstOp == 16 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 200;
- else if(mod->mSrcOp == 0x00DD && mod->mDstOp == 15 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 200;
- /*else if(mod->mSrcOp == 0x020E && mod->mDstOp == ?initialpitch? && mod->mAmtSrcOp == 0x0010 && mod->mTransOp == 0)
- VECTOR_BACK(self->mods).mAmount += 12700;*/
-}
-
-
-#define ERROR_GOTO(lbl_, ...) do { \
- ERR(__VA_ARGS__); \
- goto lbl_; \
-} while(0)
-
-static ALboolean ensureFontSanity(const Soundfont *sfont)
-{
- ALsizei i;
-
- for(i = 0;i < sfont->phdr_size;i++)
- {
- if(sfont->phdr[i].mZoneIdx >= sfont->pbag_size)
- {
- WARN("Preset %d has invalid zone index %d (max: %d)\n", i,
- sfont->phdr[i].mZoneIdx, sfont->pbag_size);
- return AL_FALSE;
- }
- if(i+1 < sfont->phdr_size && sfont->phdr[i+1].mZoneIdx < sfont->phdr[i].mZoneIdx)
- {
- WARN("Preset %d has invalid zone index (%d does not follow %d)\n", i+1,
- sfont->phdr[i+1].mZoneIdx, sfont->phdr[i].mZoneIdx);
- return AL_FALSE;
- }
- }
-
- for(i = 0;i < sfont->pbag_size;i++)
- {
- if(sfont->pbag[i].mGenIdx >= sfont->pgen_size)
- {
- WARN("Preset zone %d has invalid generator index %d (max: %d)\n", i,
- sfont->pbag[i].mGenIdx, sfont->pgen_size);
- return AL_FALSE;
- }
- if(i+1 < sfont->pbag_size && sfont->pbag[i+1].mGenIdx < sfont->pbag[i].mGenIdx)
- {
- WARN("Preset zone %d has invalid generator index (%d does not follow %d)\n", i+1,
- sfont->pbag[i+1].mGenIdx, sfont->pbag[i].mGenIdx);
- return AL_FALSE;
- }
- if(sfont->pbag[i].mModIdx >= sfont->pmod_size)
- {
- WARN("Preset zone %d has invalid modulator index %d (max: %d)\n", i,
- sfont->pbag[i].mModIdx, sfont->pmod_size);
- return AL_FALSE;
- }
- if(i+1 < sfont->pbag_size && sfont->pbag[i+1].mModIdx < sfont->pbag[i].mModIdx)
- {
- WARN("Preset zone %d has invalid modulator index (%d does not follow %d)\n", i+1,
- sfont->pbag[i+1].mModIdx, sfont->pbag[i].mModIdx);
- return AL_FALSE;
- }
- }
-
-
- for(i = 0;i < sfont->inst_size;i++)
- {
- if(sfont->inst[i].mZoneIdx >= sfont->ibag_size)
- {
- WARN("Instrument %d has invalid zone index %d (max: %d)\n", i,
- sfont->inst[i].mZoneIdx, sfont->ibag_size);
- return AL_FALSE;
- }
- if(i+1 < sfont->inst_size && sfont->inst[i+1].mZoneIdx < sfont->inst[i].mZoneIdx)
- {
- WARN("Instrument %d has invalid zone index (%d does not follow %d)\n", i+1,
- sfont->inst[i+1].mZoneIdx, sfont->inst[i].mZoneIdx);
- return AL_FALSE;
- }
- }
-
- for(i = 0;i < sfont->ibag_size;i++)
- {
- if(sfont->ibag[i].mGenIdx >= sfont->igen_size)
- {
- WARN("Instrument zone %d has invalid generator index %d (max: %d)\n", i,
- sfont->ibag[i].mGenIdx, sfont->igen_size);
- return AL_FALSE;
- }
- if(i+1 < sfont->ibag_size && sfont->ibag[i+1].mGenIdx < sfont->ibag[i].mGenIdx)
- {
- WARN("Instrument zone %d has invalid generator index (%d does not follow %d)\n", i+1,
- sfont->ibag[i+1].mGenIdx, sfont->ibag[i].mGenIdx);
- return AL_FALSE;
- }
- if(sfont->ibag[i].mModIdx >= sfont->imod_size)
- {
- WARN("Instrument zone %d has invalid modulator index %d (max: %d)\n", i,
- sfont->ibag[i].mModIdx, sfont->imod_size);
- return AL_FALSE;
- }
- if(i+1 < sfont->ibag_size && sfont->ibag[i+1].mModIdx < sfont->ibag[i].mModIdx)
- {
- WARN("Instrument zone %d has invalid modulator index (%d does not follow %d)\n", i+1,
- sfont->ibag[i+1].mModIdx, sfont->ibag[i].mModIdx);
- return AL_FALSE;
- }
- }
-
-
- for(i = 0;i < sfont->shdr_size-1;i++)
- {
- if((sfont->shdr[i].mSampleType&0x8000) && sfont->irom == NULL)
- {
- WARN("Sample header %d has ROM sample type without an irom sub-chunk\n", i);
- return AL_FALSE;
- }
- }
-
-
- return AL_TRUE;
-}
-
-static ALboolean checkZone(const GenModList *zone, const PresetHeader *preset, const InstrumentHeader *inst, const SampleHeader *samp)
-{
- Generator *gen = VECTOR_ITER_BEGIN(zone->gens);
- Generator *gen_end = VECTOR_ITER_END(zone->gens);
- for(;gen != gen_end;gen++)
- {
- if(gen->mGenerator == 43 || gen->mGenerator == 44)
- {
- int high = gen->mAmount>>8;
- int low = gen->mAmount&0xff;
-
- if(!(low >= 0 && high <= 127 && high >= low))
- {
- TRACE("Preset \"%s\", inst \"%s\", sample \"%s\": invalid %s range %d...%d\n",
- preset->mName, inst->mName, samp->mName,
- (gen->mGenerator == 43) ? "key" :
- (gen->mGenerator == 44) ? "velocity" : "(unknown)",
- low, high);
- return AL_FALSE;
- }
- }
- }
-
- return AL_TRUE;
-}
-
-static ALenum getModSrcInput(int input)
-{
- if(input == 0) return AL_ONE_SOFT;
- if(input == 2) return AL_NOTEON_VELOCITY_SOFT;
- if(input == 3) return AL_NOTEON_KEY_SOFT;
- if(input == 10) return AL_KEYPRESSURE_SOFT;
- if(input == 13) return AL_CHANNELPRESSURE_SOFT;
- if(input == 14) return AL_PITCHBEND_SOFT;
- if(input == 16) return AL_PITCHBEND_SENSITIVITY_SOFT;
- if((input&0x80))
- {
- if(IsValidCtrlInput(input^0x80))
- return input^0x80;
- }
- ERR("Unhandled modulator source input: 0x%02x\n", input);
- return AL_INVALID;
-}
-
-static ALenum getModSrcType(int type)
-{
- if(type == 0x0000) return AL_UNORM_SOFT;
- if(type == 0x0100) return AL_UNORM_REV_SOFT;
- if(type == 0x0200) return AL_SNORM_SOFT;
- if(type == 0x0300) return AL_SNORM_REV_SOFT;
- ERR("Unhandled modulator source type: 0x%04x\n", type);
- return AL_INVALID;
-}
-
-static ALenum getModSrcForm(int form)
-{
- if(form == 0x0000) return AL_LINEAR_SOFT;
- if(form == 0x0400) return AL_CONCAVE_SOFT;
- if(form == 0x0800) return AL_CONVEX_SOFT;
- if(form == 0x0C00) return AL_SWITCH_SOFT;
- ERR("Unhandled modulator source form: 0x%04x\n", form);
- return AL_INVALID;
-}
-
-static ALenum getModTransOp(int op)
-{
- if(op == 0) return AL_LINEAR_SOFT;
- if(op == 2) return AL_ABSOLUTE_SOFT;
- ERR("Unhandled modulator transform op: 0x%04x\n", op);
- return AL_INVALID;
-}
-
-static ALenum getLoopMode(int mode)
-{
- if(mode == 0) return AL_NONE;
- if(mode == 1) return AL_LOOP_CONTINUOUS_SOFT;
- if(mode == 3) return AL_LOOP_UNTIL_RELEASE_SOFT;
- ERR("Unhandled loop mode: %d\n", mode);
- return AL_NONE;
-}
-
-static ALenum getSampleType(int type)
-{
- if(type == 1) return AL_MONO_SOFT;
- if(type == 2) return AL_RIGHT_SOFT;
- if(type == 4) return AL_LEFT_SOFT;
- if(type == 8)
- {
- WARN("Sample type \"linked\" ignored; pretending mono\n");
- return AL_MONO_SOFT;
- }
- ERR("Unhandled sample type: 0x%04x\n", type);
- return AL_MONO_SOFT;
-}
-
-static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList *zone)
-{
- static const ALenum Gen2Param[60] = {
- 0, /* 0 - startAddrOffset */
- 0, /* 1 - endAddrOffset */
- 0, /* 2 - startloopAddrOffset */
- 0, /* 3 - endloopAddrOffset */
- 0, /* 4 - startAddrCoarseOffset */
- AL_MOD_LFO_TO_PITCH_SOFT, /* 5 - modLfoToPitch */
- AL_VIBRATO_LFO_TO_PITCH_SOFT, /* 6 - vibLfoToPitch */
- AL_MOD_ENV_TO_PITCH_SOFT, /* 7 - modEnvToPitch */
- AL_FILTER_CUTOFF_SOFT, /* 8 - initialFilterFc */
- AL_FILTER_RESONANCE_SOFT, /* 9 - initialFilterQ */
- AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT, /* 10 - modLfoToFilterFc */
- AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT, /* 11 - modEnvToFilterFc */
- 0, /* 12 - endAddrCoarseOffset */
- AL_MOD_LFO_TO_VOLUME_SOFT, /* 13 - modLfoToVolume */
- 0, /* 14 - */
- AL_CHORUS_SEND_SOFT, /* 15 - chorusEffectsSend */
- AL_REVERB_SEND_SOFT, /* 16 - reverbEffectsSend */
- AL_PAN_SOFT, /* 17 - pan */
- 0, /* 18 - */
- 0, /* 19 - */
- 0, /* 20 - */
- AL_MOD_LFO_DELAY_SOFT, /* 21 - delayModLFO */
- AL_MOD_LFO_FREQUENCY_SOFT, /* 22 - freqModLFO */
- AL_VIBRATO_LFO_DELAY_SOFT, /* 23 - delayVibLFO */
- AL_VIBRATO_LFO_FREQUENCY_SOFT, /* 24 - freqVibLFO */
- AL_MOD_ENV_DELAYTIME_SOFT, /* 25 - delayModEnv */
- AL_MOD_ENV_ATTACKTIME_SOFT, /* 26 - attackModEnv */
- AL_MOD_ENV_HOLDTIME_SOFT, /* 27 - holdModEnv */
- AL_MOD_ENV_DECAYTIME_SOFT, /* 28 - decayModEnv */
- AL_MOD_ENV_SUSTAINVOLUME_SOFT, /* 29 - sustainModEnv */
- AL_MOD_ENV_RELEASETIME_SOFT, /* 30 - releaseModEnv */
- AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT, /* 31 - keynumToModEnvHold */
- AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT, /* 32 - keynumToModEnvDecay */
- AL_VOLUME_ENV_DELAYTIME_SOFT, /* 33 - delayVolEnv */
- AL_VOLUME_ENV_ATTACKTIME_SOFT, /* 34 - attackVolEnv */
- AL_VOLUME_ENV_HOLDTIME_SOFT, /* 35 - holdVolEnv */
- AL_VOLUME_ENV_DECAYTIME_SOFT, /* 36 - decayVolEnv */
- AL_VOLUME_ENV_SUSTAINVOLUME_SOFT, /* 37 - sustainVolEnv */
- AL_VOLUME_ENV_RELEASETIME_SOFT, /* 38 - releaseVolEnv */
- AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT, /* 39 - keynumToVolEnvHold */
- AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT, /* 40 - keynumToVolEnvDecay */
- 0, /* 41 - */
- 0, /* 42 - */
- AL_KEY_RANGE_SOFT, /* 43 - keyRange */
- AL_VELOCITY_RANGE_SOFT, /* 44 - velRange */
- 0, /* 45 - startloopAddrCoarseOffset */
- 0, /* 46 - keynum */
- 0, /* 47 - velocity */
- AL_ATTENUATION_SOFT, /* 48 - initialAttenuation */
- 0, /* 49 - */
- 0, /* 50 - endloopAddrCoarseOffset */
- AL_TUNING_COARSE_SOFT, /* 51 - corseTune */
- AL_TUNING_FINE_SOFT, /* 52 - fineTune */
- 0, /* 53 - */
- AL_LOOP_MODE_SOFT, /* 54 - sampleModes */
- 0, /* 55 - */
- AL_TUNING_SCALE_SOFT, /* 56 - scaleTuning */
- AL_EXCLUSIVE_CLASS_SOFT, /* 57 - exclusiveClass */
- AL_BASE_KEY_SOFT, /* 58 - overridingRootKey */
- 0, /* 59 - */
- };
- const Generator *gen, *gen_end;
- const Modulator *mod, *mod_end;
-
- mod = VECTOR_ITER_BEGIN(zone->mods);
- mod_end = VECTOR_ITER_END(zone->mods);
- for(;mod != mod_end;mod++)
- {
- ALenum src0in = getModSrcInput(mod->mSrcOp&0xFF);
- ALenum src0type = getModSrcType(mod->mSrcOp&0x0300);
- ALenum src0form = getModSrcForm(mod->mSrcOp&0xFC00);
- ALenum src1in = getModSrcInput(mod->mAmtSrcOp&0xFF);
- ALenum src1type = getModSrcType(mod->mAmtSrcOp&0x0300);
- ALenum src1form = getModSrcForm(mod->mAmtSrcOp&0xFC00);
- ALenum trans = getModTransOp(mod->mTransOp);
- ALenum dst = (mod->mDstOp < 60) ? Gen2Param[mod->mDstOp] : 0;
- if(!dst || dst == AL_KEY_RANGE_SOFT || dst == AL_VELOCITY_RANGE_SOFT ||
- dst == AL_LOOP_MODE_SOFT || dst == AL_EXCLUSIVE_CLASS_SOFT ||
- dst == AL_BASE_KEY_SOFT)
- ERR("Unhandled modulator destination: %d\n", mod->mDstOp);
- else if(src0in != AL_INVALID && src0form != AL_INVALID && src0type != AL_INVALID &&
- src1in != AL_INVALID && src1form != AL_INVALID && src1type != AL_INVALID &&
- trans != AL_INVALID)
- {
- ALsizei idx = (ALsizei)(mod - VECTOR_ITER_BEGIN(zone->mods));
- ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_INPUT_SOFT, src0in);
- ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_TYPE_SOFT, src0type);
- ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_FORM_SOFT, src0form);
- ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_INPUT_SOFT, src1in);
- ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_TYPE_SOFT, src1type);
- ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_FORM_SOFT, src1form);
- ALfontsound_setModStagei(sound, context, idx, AL_AMOUNT_SOFT, mod->mAmount);
- ALfontsound_setModStagei(sound, context, idx, AL_TRANSFORM_OP_SOFT, trans);
- ALfontsound_setModStagei(sound, context, idx, AL_DESTINATION_SOFT, dst);
- }
- }
-
- gen = VECTOR_ITER_BEGIN(zone->gens);
- gen_end = VECTOR_ITER_END(zone->gens);
- for(;gen != gen_end;gen++)
- {
- ALint value = (ALshort)gen->mAmount;
- if(gen->mGenerator == 0)
- sound->Start += value;
- else if(gen->mGenerator == 1)
- sound->End += value;
- else if(gen->mGenerator == 2)
- sound->LoopStart += value;
- else if(gen->mGenerator == 3)
- sound->LoopEnd += value;
- else if(gen->mGenerator == 4)
- sound->Start += value<<15;
- else if(gen->mGenerator == 12)
- sound->End += value<<15;
- else if(gen->mGenerator == 45)
- sound->LoopStart += value<<15;
- else if(gen->mGenerator == 50)
- sound->LoopEnd += value<<15;
- else if(gen->mGenerator == 43)
- {
- sound->MinKey = mini((value&0xff), 127);
- sound->MaxKey = mini(((value>>8)&0xff), 127);
- }
- else if(gen->mGenerator == 44)
- {
- sound->MinVelocity = mini((value&0xff), 127);
- sound->MaxVelocity = mini(((value>>8)&0xff), 127);
- }
- else
- {
- ALenum param = 0;
- if(gen->mGenerator < 60)
- param = Gen2Param[gen->mGenerator];
- if(param)
- {
- if(param == AL_BASE_KEY_SOFT)
- {
- if(!(value >= 0 && value <= 127))
- {
- if(value != -1)
- WARN("Invalid overridingRootKey generator value %d\n", value);
- continue;
- }
- }
- if(param == AL_FILTER_RESONANCE_SOFT || param == AL_ATTENUATION_SOFT)
- value = maxi(0, value);
- else if(param == AL_CHORUS_SEND_SOFT || param == AL_REVERB_SEND_SOFT)
- value = clampi(value, 0, 1000);
- else if(param == AL_LOOP_MODE_SOFT)
- value = getLoopMode(value);
- ALfontsound_setPropi(sound, context, param, value);
- }
- else
- {
- static ALuint warned[65536/32];
- if(!(warned[gen->mGenerator/32]&(1<<(gen->mGenerator&31))))
- {
- warned[gen->mGenerator/32] |= 1<<(gen->mGenerator&31);
- ERR("Unhandled generator %d\n", gen->mGenerator);
- }
- }
- }
- }
-}
-
-static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCcontext *context, ALbuffer *buffer, InstrumentHeader *inst, const PresetHeader *preset, const Soundfont *sfont, const GenModList *pzone)
-{
- const Generator *gen, *gen_end;
- const Modulator *mod, *mod_end;
- const Zone *zone, *zone_end;
- GenModList gzone;
- ALvoid *temp;
-
- if((inst+1)->mZoneIdx == inst->mZoneIdx)
- ERR("Instrument with no zones!");
-
- GenModList_Construct(&gzone);
- zone = sfont->ibag + inst->mZoneIdx;
- zone_end = sfont->ibag + (inst+1)->mZoneIdx;
- if(zone_end-zone > 1)
- {
- gen = sfont->igen + zone->mGenIdx;
- gen_end = sfont->igen + (zone+1)->mGenIdx;
-
- // If no generators, or last generator is not a sample, this is a global zone
- for(;gen != gen_end;gen++)
- {
- if(gen->mGenerator == 53)
- break;
- }
-
- if(gen == gen_end)
- {
- gen = sfont->igen + zone->mGenIdx;
- gen_end = sfont->igen + (zone+1)->mGenIdx;
- for(;gen != gen_end;gen++)
- GenModList_insertGen(&gzone, gen, AL_FALSE);
-
- mod = sfont->imod + zone->mModIdx;
- mod_end = sfont->imod + (zone+1)->mModIdx;
- for(;mod != mod_end;mod++)
- GenModList_insertMod(&gzone, mod);
-
- zone++;
- }
- }
-
- temp = realloc(*sounds, (zone_end-zone + *sounds_size)*sizeof((*sounds)[0]));
- if(!temp)
- {
- ERR("Failed reallocating fontsound storage to %d elements (from %d)\n",
- (ALsizei)(zone_end-zone) + *sounds_size, *sounds_size);
- return;
- }
- *sounds = temp;
- for(;zone != zone_end;zone++)
- {
- GenModList lzone = GenModList_clone(&gzone);
- mod = sfont->imod + zone->mModIdx;
- mod_end = sfont->imod + (zone+1)->mModIdx;
- for(;mod != mod_end;mod++)
- GenModList_insertMod(&lzone, mod);
-
- gen = sfont->igen + zone->mGenIdx;
- gen_end = sfont->igen + (zone+1)->mGenIdx;
- for(;gen != gen_end;gen++)
- {
- if(gen->mGenerator == 53)
- {
- const SampleHeader *samp;
- ALfontsound *sound;
-
- if(gen->mAmount >= sfont->shdr_size-1)
- {
- ERR("Generator %ld has invalid sample ID (%d of %d)\n",
- (long)(gen-sfont->igen), gen->mAmount, sfont->shdr_size-1);
- break;
- }
- samp = &sfont->shdr[gen->mAmount];
-
- gen = VECTOR_ITER_BEGIN(pzone->gens);
- gen_end = VECTOR_ITER_END(pzone->gens);
- for(;gen != gen_end;gen++)
- GenModList_accumGen(&lzone, gen);
-
- mod = VECTOR_ITER_BEGIN(pzone->mods);
- mod_end = VECTOR_ITER_END(pzone->mods);
- for(;mod != mod_end;mod++)
- GenModList_accumMod(&lzone, mod);
-
- if(!checkZone(&lzone, preset, inst, samp))
- break;
- /* Ignore ROM samples for now. */
- if((samp->mSampleType&0x8000))
- break;
-
- sound = NewFontsound(context);
- (*sounds)[(*sounds_size)++] = sound;
- ALfontsound_setPropi(sound, context, AL_BUFFER, buffer->id);
- ALfontsound_setPropi(sound, context, AL_SAMPLE_START_SOFT, samp->mStart);
- ALfontsound_setPropi(sound, context, AL_SAMPLE_END_SOFT, samp->mEnd);
- ALfontsound_setPropi(sound, context, AL_SAMPLE_LOOP_START_SOFT, samp->mStartloop);
- ALfontsound_setPropi(sound, context, AL_SAMPLE_LOOP_END_SOFT, samp->mEndloop);
- ALfontsound_setPropi(sound, context, AL_SAMPLE_RATE_SOFT, samp->mSampleRate);
- ALfontsound_setPropi(sound, context, AL_BASE_KEY_SOFT, (samp->mOriginalKey <= 127) ? samp->mOriginalKey : 60);
- ALfontsound_setPropi(sound, context, AL_KEY_CORRECTION_SOFT, samp->mCorrection);
- ALfontsound_setPropi(sound, context, AL_SAMPLE_TYPE_SOFT, getSampleType(samp->mSampleType&0x7fff));
- fillZone(sound, context, &lzone);
-
- break;
- }
- GenModList_insertGen(&lzone, gen, AL_FALSE);
- }
-
- GenModList_Destruct(&lzone);
- }
-
- GenModList_Destruct(&gzone);
-}
-
-static ALuint printStringChunk(Reader *stream, const RiffHdr *chnk, const char *title)
-{
- ALuint len = 0;
- if(chnk->mSize == 0 || (chnk->mSize&1))
- ERR("Invalid "FOURCCFMT" size: %d\n", FOURCCARGS(chnk->mCode), chnk->mSize);
- else
- {
- char *str = calloc(1, chnk->mSize+1);
- len = (ALuint)Reader_read(stream, str, chnk->mSize);
-
- TRACE("%s: %s\n", title, str);
- free(str);
- }
- return len;
-}
-
-ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
-{
- ALsfpreset **presets = NULL;
- ALsizei presets_size = 0;
- ALbuffer *buffer = NULL;
- ALuint ltype;
- Soundfont sfont;
- RiffHdr riff;
- RiffHdr list;
- ALsizei i;
-
- Soundfont_Construct(&sfont);
-
- RiffHdr_read(&riff, stream);
- if(riff.mCode != FOURCC('R','I','F','F'))
- ERROR_GOTO(error, "Invalid Format, expected RIFF got '"FOURCCFMT"'\n", FOURCCARGS(riff.mCode));
- if((ltype=read_le32(stream)) != FOURCC('s','f','b','k'))
- ERROR_GOTO(error, "Invalid Format, expected sfbk got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
-
- if(READERR(stream) != 0)
- ERROR_GOTO(error, "Error reading file header\n");
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('L','I','S','T'))
- ERROR_GOTO(error, "Invalid Format, expected LIST (INFO) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((ltype=read_le32(stream)) != FOURCC('I','N','F','O'))
- ERROR_GOTO(error, "Invalid Format, expected INFO got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
- list.mSize -= 4;
- while(list.mSize > 0 && !READERR(stream))
- {
- RiffHdr chnk;
-
- if(list.mSize < 8)
- {
- WARN("Unexpected end of INFO list (%u extra bytes)\n", list.mSize);
- skip(stream, list.mSize);
- list.mSize = 0;
- break;
- }
-
- RiffHdr_read(&chnk, stream);
- list.mSize -= 8;
- if(list.mSize < chnk.mSize)
- {
- WARN("INFO sub-chunk '"FOURCCFMT"' has %u bytes, but only %u bytes remain\n",
- FOURCCARGS(chnk.mCode), chnk.mSize, list.mSize);
- skip(stream, list.mSize);
- list.mSize = 0;
- break;
- }
- list.mSize -= chnk.mSize;
-
- if(chnk.mCode == FOURCC('i','f','i','l'))
- {
- if(chnk.mSize != 4)
- ERR("Invalid ifil chunk size: %d\n", chnk.mSize);
- else
- {
- ALushort major = read_le16(stream);
- ALushort minor = read_le16(stream);
- chnk.mSize -= 4;
-
- if(major != 2)
- ERROR_GOTO(error, "Unsupported SF2 format version: %d.%02d\n", major, minor);
- TRACE("SF2 format version: %d.%02d\n", major, minor);
-
- sfont.ifil = (major<<16) | minor;
- }
- }
- else if(chnk.mCode == FOURCC('i','r','o','m'))
- {
- if(chnk.mSize == 0 || (chnk.mSize&1))
- ERR("Invalid irom size: %d\n", chnk.mSize);
- else
- {
- free(sfont.irom);
- sfont.irom = calloc(1, chnk.mSize+1);
- chnk.mSize -= Reader_read(stream, sfont.irom, chnk.mSize);
-
- TRACE("SF2 ROM ID: %s\n", sfont.irom);
- }
- }
- else
- {
- static const struct {
- ALuint code;
- char title[16];
- } listinfos[] = {
- { FOURCC('i','s','n','g'), "Engine ID" },
- { FOURCC('I','N','A','M'), "Name" },
- { FOURCC('I','C','R','D'), "Creation Date" },
- { FOURCC('I','E','N','G'), "Creator" },
- { FOURCC('I','P','R','D'), "Product ID" },
- { FOURCC('I','C','O','P'), "Copyright" },
- { FOURCC('I','C','M','T'), "Comment" },
- { FOURCC('I','S','F','T'), "Created With" },
- { 0, "" },
- };
-
- for(i = 0;listinfos[i].code;i++)
- {
- if(listinfos[i].code == chnk.mCode)
- {
- chnk.mSize -= printStringChunk(stream, &chnk, listinfos[i].title);
- break;
- }
- }
- if(!listinfos[i].code)
- TRACE("Skipping INFO sub-chunk '"FOURCCFMT"' (%u bytes)\n", FOURCCARGS(chnk.mCode), chnk.mSize);
- }
- skip(stream, chnk.mSize);
- }
-
- if(READERR(stream) != 0)
- ERROR_GOTO(error, "Error reading INFO chunk\n");
- if(sfont.ifil == 0)
- ERROR_GOTO(error, "Missing ifil sub-chunk\n");
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('L','I','S','T'))
- ERROR_GOTO(error, "Invalid Format, expected LIST (sdta) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((ltype=read_le32(stream)) != FOURCC('s','d','t','a'))
- ERROR_GOTO(error, "Invalid Format, expected sdta got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
- list.mSize -= 4;
- {
- ALbyte *ptr;
- RiffHdr smpl;
- ALenum err;
-
- RiffHdr_read(&smpl, stream);
- if(smpl.mCode != FOURCC('s','m','p','l'))
- ERROR_GOTO(error, "Invalid Format, expected smpl got '"FOURCCFMT"'\n", FOURCCARGS(smpl.mCode));
- list.mSize -= 8;
-
- if(smpl.mSize > list.mSize)
- ERROR_GOTO(error, "Invalid Format, sample chunk size mismatch\n");
- list.mSize -= smpl.mSize;
-
- buffer = NewBuffer(context);
- if(!buffer)
- SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, error);
- /* Sample rate is unimportant, the individual fontsounds will specify it. */
- if((err=LoadData(buffer, 22050, AL_MONO16_SOFT, smpl.mSize/2, UserFmtMono, UserFmtShort, NULL, 1, AL_FALSE)) != AL_NO_ERROR)
- SET_ERROR_AND_GOTO(context, err, error);
-
- ptr = buffer->data;
- if(IS_LITTLE_ENDIAN)
- smpl.mSize -= (ALuint)Reader_read(stream, ptr, smpl.mSize);
- else
- {
- ALuint total = 0;
- while(total < smpl.mSize && !READERR(stream))
- {
- ALbyte buf[4096];
- ALuint todo = minu(smpl.mSize-total, sizeof(buf));
- ALuint i;
-
- smpl.mSize -= (ALuint)Reader_read(stream, buf, todo);
- for(i = 0;i < todo;i++)
- ptr[total+i] = buf[i^1];
-
- total += todo;
- }
- }
-
- skip(stream, list.mSize);
- }
-
- if(READERR(stream) != 0)
- ERROR_GOTO(error, "Error reading sdta chunk\n");
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('L','I','S','T'))
- ERROR_GOTO(error, "Invalid Format, expected LIST (pdta) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((ltype=read_le32(stream)) != FOURCC('p','d','t','a'))
- ERROR_GOTO(error, "Invalid Format, expected pdta got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
-
- //
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('p','h','d','r'))
- ERROR_GOTO(error, "Invalid Format, expected phdr got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%38) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad phdr size: %u\n", list.mSize);
- sfont.phdr_size = list.mSize/38;
- sfont.phdr = calloc(sfont.phdr_size, sizeof(sfont.phdr[0]));
- for(i = 0;i < sfont.phdr_size;i++)
- PresetHeader_read(&sfont.phdr[i], stream);
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('p','b','a','g'))
- ERROR_GOTO(error, "Invalid Format, expected pbag got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%4) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad pbag size: %u\n", list.mSize);
- sfont.pbag_size = list.mSize/4;
- sfont.pbag = calloc(sfont.pbag_size, sizeof(sfont.pbag[0]));
- for(i = 0;i < sfont.pbag_size;i++)
- Zone_read(&sfont.pbag[i], stream);
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('p','m','o','d'))
- ERROR_GOTO(error, "Invalid Format, expected pmod got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%10) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad pmod size: %u\n", list.mSize);
- sfont.pmod_size = list.mSize/10;
- sfont.pmod = calloc(sfont.pmod_size, sizeof(sfont.pmod[0]));
- for(i = 0;i < sfont.pmod_size;i++)
- Modulator_read(&sfont.pmod[i], stream);
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('p','g','e','n'))
- ERROR_GOTO(error, "Invalid Format, expected pgen got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%4) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad pgen size: %u\n", list.mSize);
- sfont.pgen_size = list.mSize/4;
- sfont.pgen = calloc(sfont.pgen_size, sizeof(sfont.pgen[0]));
- for(i = 0;i < sfont.pgen_size;i++)
- Generator_read(&sfont.pgen[i], stream);
-
- //
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('i','n','s','t'))
- ERROR_GOTO(error, "Invalid Format, expected inst got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%22) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad inst size: %u\n", list.mSize);
- sfont.inst_size = list.mSize/22;
- sfont.inst = calloc(sfont.inst_size, sizeof(sfont.inst[0]));
- for(i = 0;i < sfont.inst_size;i++)
- InstrumentHeader_read(&sfont.inst[i], stream);
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('i','b','a','g'))
- ERROR_GOTO(error, "Invalid Format, expected ibag got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%4) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad ibag size: %u\n", list.mSize);
- sfont.ibag_size = list.mSize/4;
- sfont.ibag = calloc(sfont.ibag_size, sizeof(sfont.ibag[0]));
- for(i = 0;i < sfont.ibag_size;i++)
- Zone_read(&sfont.ibag[i], stream);
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('i','m','o','d'))
- ERROR_GOTO(error, "Invalid Format, expected imod got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%10) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad imod size: %u\n", list.mSize);
- sfont.imod_size = list.mSize/10;
- sfont.imod = calloc(sfont.imod_size, sizeof(sfont.imod[0]));
- for(i = 0;i < sfont.imod_size;i++)
- Modulator_read(&sfont.imod[i], stream);
-
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('i','g','e','n'))
- ERROR_GOTO(error, "Invalid Format, expected igen got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%4) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad igen size: %u\n", list.mSize);
- sfont.igen_size = list.mSize/4;
- sfont.igen = calloc(sfont.igen_size, sizeof(sfont.igen[0]));
- for(i = 0;i < sfont.igen_size;i++)
- Generator_read(&sfont.igen[i], stream);
-
- //
- RiffHdr_read(&list, stream);
- if(list.mCode != FOURCC('s','h','d','r'))
- ERROR_GOTO(error, "Invalid Format, expected shdr got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
- if((list.mSize%46) != 0 || list.mSize == 0)
- ERROR_GOTO(error, "Invalid Format, bad shdr size: %u\n", list.mSize);
- sfont.shdr_size = list.mSize/46;
- sfont.shdr = calloc(sfont.shdr_size, sizeof(sfont.shdr[0]));
- for(i = 0;i < sfont.shdr_size;i++)
- SampleHeader_read(&sfont.shdr[i], stream);
-
- if(READERR(stream) != 0)
- ERROR_GOTO(error, "Error reading pdta chunk\n");
-
- if(!ensureFontSanity(&sfont))
- goto error;
-
- presets = calloc(1, (soundfont->NumPresets+sfont.phdr_size-1)*sizeof(presets[0]));
- if(!presets)
- ERROR_GOTO(error, "Error allocating presets\n");
- memcpy(presets, soundfont->Presets, soundfont->NumPresets*sizeof(presets[0]));
- presets_size = soundfont->NumPresets;
-
- for(i = 0;i < sfont.phdr_size-1;i++)
- {
- const Generator *gen, *gen_end;
- const Modulator *mod, *mod_end;
- const Zone *zone, *zone_end;
- ALfontsound **sounds = NULL;
- ALsizei sounds_size = 0;
- GenModList gzone;
-
- if(sfont.phdr[i+1].mZoneIdx == sfont.phdr[i].mZoneIdx)
- continue;
-
- GenModList_Construct(&gzone);
- zone = sfont.pbag + sfont.phdr[i].mZoneIdx;
- zone_end = sfont.pbag + sfont.phdr[i+1].mZoneIdx;
- if(zone_end-zone > 1)
- {
- gen = sfont.pgen + zone->mGenIdx;
- gen_end = sfont.pgen + (zone+1)->mGenIdx;
-
- // If no generators, or last generator is not an instrument, this is a global zone
- for(;gen != gen_end;gen++)
- {
- if(gen->mGenerator == 41)
- break;
- }
-
- if(gen == gen_end)
- {
- gen = sfont.pgen + zone->mGenIdx;
- gen_end = sfont.pgen + (zone+1)->mGenIdx;
- for(;gen != gen_end;gen++)
- GenModList_insertGen(&gzone, gen, AL_TRUE);
-
- mod = sfont.pmod + zone->mModIdx;
- mod_end = sfont.pmod + (zone+1)->mModIdx;
- for(;mod != mod_end;mod++)
- GenModList_insertMod(&gzone, mod);
-
- zone++;
- }
- }
-
- for(;zone != zone_end;zone++)
- {
- GenModList lzone = GenModList_clone(&gzone);
-
- mod = sfont.pmod + zone->mModIdx;
- mod_end = sfont.pmod + (zone+1)->mModIdx;
- for(;mod != mod_end;mod++)
- GenModList_insertMod(&lzone, mod);
-
- gen = sfont.pgen + zone->mGenIdx;
- gen_end = sfont.pgen + (zone+1)->mGenIdx;
- for(;gen != gen_end;gen++)
- {
- if(gen->mGenerator == 41)
- {
- if(gen->mAmount >= sfont.inst_size-1)
- ERR("Generator %ld has invalid instrument ID (%d of %d)\n",
- (long)(gen-sfont.pgen), gen->mAmount, sfont.inst_size-1);
- else
- processInstrument(
- &sounds, &sounds_size, context, buffer, &sfont.inst[gen->mAmount],
- &sfont.phdr[i], &sfont, &lzone
- );
- break;
- }
- GenModList_insertGen(&lzone, gen, AL_TRUE);
- }
- GenModList_Destruct(&lzone);
- }
-
- if(sounds_size > 0)
- {
- ALsizei j;
-
- presets[presets_size] = NewPreset(context);
- presets[presets_size]->Preset = sfont.phdr[i].mPreset;
- presets[presets_size]->Bank = sfont.phdr[i].mBank;
-
- for(j = 0;j < sounds_size;j++)
- IncrementRef(&sounds[j]->ref);
- sounds = ExchangePtr((XchgPtr*)&presets[presets_size]->Sounds, sounds);
- presets[presets_size]->NumSounds = sounds_size;
- presets_size++;
- }
- free(sounds);
-
- GenModList_Destruct(&gzone);
- }
-
- for(i = soundfont->NumPresets;i < presets_size;i++)
- IncrementRef(&presets[i]->ref);
- presets = ExchangePtr((XchgPtr*)&soundfont->Presets, presets);
- soundfont->NumPresets = presets_size;
-
- free(presets);
-
- Soundfont_Destruct(&sfont);
- /* If the buffer ends up unused, delete it. */
- if(ReadRef(&buffer->ref) == 0)
- {
- TRACE("Deleting unused buffer...\n");
- DeleteBuffer(context->Device, buffer);
- }
-
- return AL_TRUE;
-
-error:
- if(presets)
- {
- ALCdevice *device = context->Device;
- for(i = soundfont->NumPresets;i < presets_size;i++)
- DeletePreset(device, presets[i]);
- free(presets);
- }
-
- Soundfont_Destruct(&sfont);
- if(buffer)
- DeleteBuffer(context->Device, buffer);
-
- return AL_FALSE;
-}
diff --git a/Alc/midi/soft.c b/Alc/midi/soft.c
deleted file mode 100644
index a000266b..00000000
--- a/Alc/midi/soft.c
+++ /dev/null
@@ -1,139 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "alMain.h"
-#include "alError.h"
-#include "evtqueue.h"
-#include "alu.h"
-
-#include "midi/base.h"
-
-
-typedef struct SSynth {
- DERIVE_FROM_TYPE(MidiSynth);
-} SSynth;
-
-static void SSynth_mixSamples(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels);
-
-static void SSynth_Construct(SSynth *self, ALCdevice *device);
-static void SSynth_Destruct(SSynth *self);
-static DECLARE_FORWARD3(SSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*)
-static DECLARE_FORWARD1(SSynth, MidiSynth, void, setGain, ALfloat)
-static DECLARE_FORWARD(SSynth, MidiSynth, void, stop)
-static DECLARE_FORWARD(SSynth, MidiSynth, void, reset)
-static void SSynth_update(SSynth *self, ALCdevice *device);
-static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels);
-DECLARE_DEFAULT_ALLOCATORS(SSynth)
-DEFINE_MIDISYNTH_VTABLE(SSynth);
-
-
-static void SSynth_Construct(SSynth *self, ALCdevice *device)
-{
- MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
- SET_VTABLE2(SSynth, MidiSynth, self);
-}
-
-static void SSynth_Destruct(SSynth* UNUSED(self))
-{
-}
-
-
-static void SSynth_update(SSynth* UNUSED(self), ALCdevice* UNUSED(device))
-{
-}
-
-
-static void SSynth_mixSamples(SSynth* UNUSED(self), ALuint UNUSED(SamplesToDo), ALfloatBUFFERSIZE *restrict UNUSED(DryBuffer), ALuint UNUSED(NumChannels))
-{
-}
-
-
-static void SSynth_processQueue(SSynth *self, ALuint64 time)
-{
- EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
-
- while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
- queue->pos++;
-}
-
-static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE], ALuint NumChannels)
-{
- MidiSynth *synth = STATIC_CAST(MidiSynth, self);
- ALenum state = synth->State;
- ALuint64 curtime;
- ALuint total = 0;
-
- if(state == AL_INITIAL)
- return;
- if(state != AL_PLAYING)
- {
- SSynth_mixSamples(self, SamplesToDo, DryBuffer, NumChannels);
- return;
- }
-
- curtime = MidiSynth_getTime(synth);
- while(total < SamplesToDo)
- {
- ALuint64 time, diff;
- ALint tonext;
-
- time = MidiSynth_getNextEvtTime(synth);
- diff = maxu64(time, curtime) - curtime;
- if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX)
- {
- /* If there's no pending event, or if it's more than 1 second
- * away, do as many samples as we can. */
- tonext = INT_MAX;
- }
- else
- {
- /* Figure out how many samples until the next event. */
- tonext = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES);
- tonext -= total;
- /* For efficiency reasons, try to mix a multiple of 64 samples
- * (~1ms @ 44.1khz) before processing the next event. */
- tonext = (tonext+63) & ~63;
- }
-
- if(tonext > 0)
- {
- ALuint todo = mini(tonext, SamplesToDo-total);
- SSynth_mixSamples(self, todo, DryBuffer, NumChannels);
- total += todo;
- tonext -= todo;
- }
- if(total < SamplesToDo && tonext <= 0)
- SSynth_processQueue(self, time);
- }
-
- synth->SamplesDone += SamplesToDo;
- synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
- synth->SamplesDone %= synth->SampleRate;
-}
-
-
-MidiSynth *SSynth_create(ALCdevice *device)
-{
- SSynth *synth;
-
- /* This option is temporary. Once this synth is in a more usable state, a
- * more generic selector should be used. */
- if(!GetConfigValueBool(NULL, "midi", "internal-synth", 0))
- {
- TRACE("Not using internal MIDI synth\n");
- return NULL;
- }
-
- NEW_OBJ(synth, SSynth)(device);
- if(!synth)
- {
- ERR("Failed to allocate SSynth\n");
- return NULL;
- }
- return STATIC_CAST(MidiSynth, synth);
-}