From f8c68291d3b0ebbfa710c95a28b042393fb4b7d6 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 28 Nov 2013 04:52:53 -0800 Subject: Add a method to stop MIDI playback Unlike pausing, this resets the MIDI clock time to 0, clears the existing event queue, stops all MIDI sounds, and resets MIDI controllers. --- OpenAL32/Include/alMain.h | 2 ++ OpenAL32/Include/alMidi.h | 3 +++ OpenAL32/alMidi.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) (limited to 'OpenAL32') diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 4715dc99..6a2f8a9a 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -41,6 +41,7 @@ typedef void (AL_APIENTRY*LPALMIDISOUNDFONTSOFT)(const char *filename); typedef void (AL_APIENTRY*LPALMIDIEVENTSOFT)(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2); typedef void (AL_APIENTRY*LPALMIDIPLAYSOFT)(void); typedef void (AL_APIENTRY*LPALMIDIPAUSESOFT)(void); +typedef void (AL_APIENTRY*LPALMIDISTOPSOFT)(void); typedef ALint64SOFT (AL_APIENTRY*LPALGETINTEGER64SOFT)(ALenum pname); typedef void (AL_APIENTRY*LPALGETINTEGER64VSOFT)(ALenum pname, ALint64SOFT *values); #ifdef AL_ALEXT_PROTOTYPES @@ -48,6 +49,7 @@ AL_API void AL_APIENTRY alMidiSoundfontSOFT(const char *filename); AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2); AL_API void AL_APIENTRY alMidiPlaySOFT(void); AL_API void AL_APIENTRY alMidiPauseSOFT(void); +AL_API void AL_APIENTRY alMidiStopSOFT(void); AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname); AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values); #endif diff --git a/OpenAL32/Include/alMidi.h b/OpenAL32/Include/alMidi.h index d648e179..400b8b9b 100644 --- a/OpenAL32/Include/alMidi.h +++ b/OpenAL32/Include/alMidi.h @@ -40,6 +40,7 @@ struct MidiSynthVtable { ALenum (*const loadSoundfont)(MidiSynth *self, const char *filename); void (*const setState)(MidiSynth *self, ALenum state); + void (*const reset)(MidiSynth *self); void (*const update)(MidiSynth *self, ALCdevice *device); void (*const process)(MidiSynth *self, ALuint samples, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); @@ -50,6 +51,7 @@ struct MidiSynthVtable { DECLARE_THUNK(T, MidiSynth, void, Destruct) \ DECLARE_THUNK1(T, MidiSynth, ALenum, loadSoundfont, const char*) \ DECLARE_THUNK1(T, MidiSynth, void, setState, ALenum) \ +DECLARE_THUNK(T, MidiSynth, void, reset) \ DECLARE_THUNK1(T, MidiSynth, void, update, ALCdevice*) \ DECLARE_THUNK2(T, MidiSynth, void, process, ALuint, ALfloatBUFFERSIZE*restrict) \ DECLARE_THUNK(T, MidiSynth, void, Delete) \ @@ -59,6 +61,7 @@ static const struct MidiSynthVtable T##_MidiSynth_vtable = { \ \ T##_MidiSynth_loadSoundfont, \ T##_MidiSynth_setState, \ + T##_MidiSynth_reset, \ T##_MidiSynth_update, \ T##_MidiSynth_process, \ \ diff --git a/OpenAL32/alMidi.c b/OpenAL32/alMidi.c index b45a92e0..f9fe5601 100644 --- a/OpenAL32/alMidi.c +++ b/OpenAL32/alMidi.c @@ -19,6 +19,7 @@ static void MidiSynth_Construct(MidiSynth *self, ALCdevice *device); static void MidiSynth_Destruct(MidiSynth *self); static inline void MidiSynth_setState(MidiSynth *self, ALenum state); +static inline void MidiSynth_reset(MidiSynth *self); ALuint64 MidiSynth_getTime(const MidiSynth *self); static inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self); static void MidiSynth_update(MidiSynth *self, ALCdevice *device); @@ -54,6 +55,16 @@ static inline void MidiSynth_setState(MidiSynth *self, ALenum state) ExchangeInt(&self->State, state); } +static inline void MidiSynth_reset(MidiSynth *self) +{ + ResetEvtQueue(&self->EventQueue); + + self->LastEvtTime = 0; + self->NextEvtTime = UINT64_MAX; + self->SamplesSinceLast = 0.0; + self->SamplesToNext = 0.0; +} + ALuint64 MidiSynth_getTime(const MidiSynth *self) { ALuint64 time = self->LastEvtTime + (self->SamplesSinceLast/self->SamplesPerTick); @@ -119,6 +130,7 @@ static void FSynth_Destruct(FSynth *self); static ALboolean FSynth_init(FSynth *self, ALCdevice *device); static ALenum FSynth_loadSoundfont(FSynth *self, const char *filename); static void FSynth_setState(FSynth *self, ALenum state); +static void FSynth_reset(FSynth *self); static void FSynth_update(FSynth *self, ALCdevice *device); static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); static void FSynth_Delete(FSynth *self); @@ -215,6 +227,20 @@ static void FSynth_setState(FSynth *self, ALenum state) MidiSynth_setState(STATIC_CAST(MidiSynth, self), state); } +static void FSynth_reset(FSynth *self) +{ + ALsizei chan; + 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); + } + + MidiSynth_reset(STATIC_CAST(MidiSynth, self)); +} + + static void FSynth_update(FSynth *self, ALCdevice *device) { fluid_settings_setnum(self->Settings, "synth.sample-rate", device->Frequency); @@ -338,6 +364,7 @@ static void DSynth_Construct(DSynth *self, ALCdevice *device); static DECLARE_FORWARD(DSynth, MidiSynth, void, Destruct) static ALenum DSynth_loadSoundfont(DSynth *self, const char *filename); static DECLARE_FORWARD1(DSynth, MidiSynth, void, setState, ALenum) +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]); static void DSynth_Delete(DSynth *self); @@ -544,6 +571,29 @@ AL_API void AL_APIENTRY alMidiPauseSOFT(void) ALCcontext_DecRef(context); } +AL_API void AL_APIENTRY alMidiStopSOFT(void) +{ + ALCdevice *device; + ALCcontext *context; + MidiSynth *synth; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + synth = device->Synth; + + WriteLock(&synth->Lock); + V(synth,setState)(AL_STOPPED); + + ALCdevice_Lock(device); + V0(synth,reset)(); + ALCdevice_Unlock(device); + WriteUnlock(&synth->Lock); + + ALCcontext_DecRef(context); +} + void InitEvtQueue(EvtQueue *queue) { -- cgit v1.2.3