diff options
author | Chris Robinson <[email protected]> | 2013-12-13 13:40:53 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2013-12-13 13:40:53 -0800 |
commit | a343d78724cf59f6368971f871493c0e45f66cea (patch) | |
tree | e3b256986bd78fa6ab1a5d15a0bee062669d2ac2 | |
parent | 57eef756c3feac7e7c364ac56b70978fb29aa822 (diff) |
Update behavior for alMidiStopSOFT
alMidiStopSOFT now has the following behavior:
* All pending MIDI events up to the current time are processed first, before
the queue is flushed.
* All channels then receive an All Notes Off event so that notes go through
their release phase. Controllers are *NOT* reset.
* Clock time is reset to 0, like before.
-rw-r--r-- | OpenAL32/Include/alMidi.h | 3 | ||||
-rw-r--r-- | OpenAL32/alMidi.c | 44 |
2 files changed, 44 insertions, 3 deletions
diff --git a/OpenAL32/Include/alMidi.h b/OpenAL32/Include/alMidi.h index 847af04e..eb36adcf 100644 --- a/OpenAL32/Include/alMidi.h +++ b/OpenAL32/Include/alMidi.h @@ -45,6 +45,7 @@ struct MidiSynthVtable { void (*const setGain)(MidiSynth *self, ALfloat gain); void (*const setState)(MidiSynth *self, ALenum state); + void (*const stop)(MidiSynth *self); void (*const reset)(MidiSynth *self); void (*const update)(MidiSynth *self, ALCdevice *device); @@ -59,6 +60,7 @@ DECLARE_THUNK1(T, MidiSynth, ALboolean, isSoundfont, const char*) \ DECLARE_THUNK1(T, MidiSynth, ALenum, loadSoundfont, const char*) \ DECLARE_THUNK1(T, MidiSynth, void, setGain, ALfloat) \ DECLARE_THUNK1(T, MidiSynth, void, setState, ALenum) \ +DECLARE_THUNK(T, MidiSynth, void, stop) \ DECLARE_THUNK(T, MidiSynth, void, reset) \ DECLARE_THUNK1(T, MidiSynth, void, update, ALCdevice*) \ DECLARE_THUNK2(T, MidiSynth, void, process, ALuint, ALfloatBUFFERSIZE*restrict) \ @@ -71,6 +73,7 @@ static const struct MidiSynthVtable T##_MidiSynth_vtable = { \ T##_MidiSynth_loadSoundfont, \ T##_MidiSynth_setGain, \ T##_MidiSynth_setState, \ + T##_MidiSynth_stop, \ T##_MidiSynth_reset, \ T##_MidiSynth_update, \ T##_MidiSynth_process, \ diff --git a/OpenAL32/alMidi.c b/OpenAL32/alMidi.c index 8f9acd7d..2f87faad 100644 --- a/OpenAL32/alMidi.c +++ b/OpenAL32/alMidi.c @@ -25,6 +25,7 @@ static void MidiSynth_Destruct(MidiSynth *self); static inline const char *MidiSynth_getFontName(const MidiSynth *self, const char *filename); static inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain); static inline void MidiSynth_setState(MidiSynth *self, ALenum state); +static inline void MidiSynth_stop(MidiSynth *self); static inline void MidiSynth_reset(MidiSynth *self); ALuint64 MidiSynth_getTime(const MidiSynth *self); static inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self); @@ -82,7 +83,7 @@ static inline void MidiSynth_setState(MidiSynth *self, ALenum state) ExchangeInt(&self->State, state); } -static inline void MidiSynth_reset(MidiSynth *self) +static inline void MidiSynth_stop(MidiSynth *self) { ResetEvtQueue(&self->EventQueue); @@ -92,6 +93,11 @@ static inline void MidiSynth_reset(MidiSynth *self) self->SamplesToNext = 0.0; } +static inline void MidiSynth_reset(MidiSynth *self) +{ + MidiSynth_stop(self); +} + ALuint64 MidiSynth_getTime(const MidiSynth *self) { ALuint64 time = self->LastEvtTime + (self->SamplesSinceLast/self->SamplesPerTick); @@ -197,8 +203,10 @@ static ALboolean FSynth_isSoundfont(FSynth *self, const char *filename); static ALenum FSynth_loadSoundfont(FSynth *self, const char *filename); static void FSynth_setGain(FSynth *self, ALfloat gain); static void FSynth_setState(FSynth *self, ALenum state); +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]); static void FSynth_Delete(FSynth *self); DEFINE_MIDISYNTH_VTABLE(FSynth); @@ -306,12 +314,41 @@ static void FSynth_setState(FSynth *self, ALenum state) MidiSynth_setState(STATIC_CAST(MidiSynth, self), state); } +static void FSynth_stop(FSynth *self) +{ + MidiSynth *synth = STATIC_CAST(MidiSynth, self); + ALsizei chan; + + /* Make sure all pending events are processed. */ + while(!(synth->SamplesToNext >= 1.0)) + { + ALuint64 time = synth->NextEvtTime; + if(time == UINT64_MAX) + break; + + synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick; + synth->SamplesSinceLast = maxd(synth->SamplesSinceLast, 0.0); + synth->LastEvtTime = time; + FSynth_processQueue(self, time); + + synth->NextEvtTime = MidiSynth_getNextEvtTime(synth); + if(synth->NextEvtTime != UINT64_MAX) + synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick; + } + + /* All notes off */ + for(chan = 0;chan < 16;chan++) + fluid_synth_cc(self->Synth, chan, 123, 0); + + MidiSynth_stop(STATIC_CAST(MidiSynth, self)); +} + static void FSynth_reset(FSynth *self) { ALsizei chan; + /* All sounds off + reset all controllers */ for(chan = 0;chan < 16;chan++) { - /* All sounds off + reset all controllers */ fluid_synth_cc(self->Synth, chan, 120, 0); fluid_synth_cc(self->Synth, chan, 121, 0); } @@ -471,6 +508,7 @@ static ALboolean DSynth_isSoundfont(DSynth *self, const char *filename); static ALenum DSynth_loadSoundfont(DSynth *self, const char *filename); static DECLARE_FORWARD1(DSynth, MidiSynth, void, setGain, ALfloat) static DECLARE_FORWARD1(DSynth, MidiSynth, void, setState, ALenum) +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]); @@ -750,7 +788,7 @@ AL_API void AL_APIENTRY alMidiStopSOFT(void) V(synth,setState)(AL_STOPPED); ALCdevice_Lock(device); - V0(synth,reset)(); + V0(synth,stop)(); ALCdevice_Unlock(device); WriteUnlock(&synth->Lock); |