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.
This commit is contained in:
@@ -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, \
|
||||
|
||||
+41
-3
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user