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.
This commit is contained in:
parent
29a4ac329a
commit
f8c68291d3
@ -284,6 +284,7 @@ static const ALCfunction alcFunctions[] = {
|
||||
DECL(alMidiEventSOFT),
|
||||
DECL(alMidiPlaySOFT),
|
||||
DECL(alMidiPauseSOFT),
|
||||
DECL(alMidiStopSOFT),
|
||||
DECL(alGetInteger64SOFT),
|
||||
DECL(alGetInteger64vSOFT),
|
||||
|
||||
|
@ -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
|
||||
|
@ -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, \
|
||||
\
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user