aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2013-11-28 04:52:53 -0800
committerChris Robinson <[email protected]>2013-11-28 04:52:53 -0800
commitf8c68291d3b0ebbfa710c95a28b042393fb4b7d6 (patch)
treea13f3957a57d3f543239318a59d0b9b696c0ef18
parent29a4ac329a8d6f8c4432217e1e1f3e55cbf146fe (diff)
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.
-rw-r--r--Alc/ALc.c1
-rw-r--r--OpenAL32/Include/alMain.h2
-rw-r--r--OpenAL32/Include/alMidi.h3
-rw-r--r--OpenAL32/alMidi.c50
4 files changed, 56 insertions, 0 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 91c365dc..38da53c7 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -284,6 +284,7 @@ static const ALCfunction alcFunctions[] = {
DECL(alMidiEventSOFT),
DECL(alMidiPlaySOFT),
DECL(alMidiPauseSOFT),
+ DECL(alMidiStopSOFT),
DECL(alGetInteger64SOFT),
DECL(alGetInteger64vSOFT),
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)
{