winmidi: Prevent hanging notes when pausing game (#1069)

This commit is contained in:
ceski 2023-05-21 23:54:59 -07:00 committed by GitHub
parent e89612a0c9
commit e053e04331
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -76,6 +76,9 @@ static byte channel_volume[MIDI_CHANNELS_PER_TRACK];
static float volume_factor = 0.0f; static float volume_factor = 0.0f;
static boolean update_volume = false; static boolean update_volume = false;
static boolean playing;
static boolean paused;
static DWORD timediv; static DWORD timediv;
static DWORD tempo; static DWORD tempo;
@ -354,6 +357,17 @@ static void ResetVolume(void)
} }
} }
static void StopSound(void)
{
int i;
for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
{
SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_NOTES_OFF, 0);
SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_SOUND_OFF, 0);
}
}
static void ResetControllers(void) static void ResetControllers(void)
{ {
int i; int i;
@ -393,14 +407,8 @@ static void ResetPitchBendSensitivity(void)
static void ResetDevice(void) static void ResetDevice(void)
{ {
int i; // Stop sound prior to reset to prevent volume spikes.
StopSound();
for (i = 0; i < MIDI_CHANNELS_PER_TRACK; ++i)
{
// Stop sound prior to reset to prevent volume spikes.
SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_NOTES_OFF, 0);
SendShortMsg(0, MIDI_EVENT_CONTROLLER, i, MIDI_CONTROLLER_ALL_SOUND_OFF, 0);
}
MIDI_ResetFallback(); MIDI_ResetFallback();
use_fallback = false; use_fallback = false;
@ -1228,6 +1236,21 @@ static void FillBuffer(void)
return; return;
} }
if (paused)
{
if (playing)
{
playing = false;
StopSound();
}
// Send a NOP every 100 ms while paused.
SendDelayMsg(100);
StreamOut();
return;
}
playing = true;
for (num_events = 0; num_events < STREAM_MAX_EVENTS; ) for (num_events = 0; num_events < STREAM_MAX_EVENTS; )
{ {
midi_event_t *event = NULL; midi_event_t *event = NULL;
@ -1469,6 +1492,7 @@ static void I_WIN_PlaySong(void *handle, boolean looping)
SetThreadPriority(hPlayerThread, THREAD_PRIORITY_TIME_CRITICAL); SetThreadPriority(hPlayerThread, THREAD_PRIORITY_TIME_CRITICAL);
initial_playback = true; initial_playback = true;
paused = false;
SetEvent(hBufferReturnEvent); SetEvent(hBufferReturnEvent);
@ -1481,34 +1505,22 @@ static void I_WIN_PlaySong(void *handle, boolean looping)
static void I_WIN_PauseSong(void *handle) static void I_WIN_PauseSong(void *handle)
{ {
MMRESULT mmr;
if (!hMidiStream) if (!hMidiStream)
{ {
return; return;
} }
mmr = midiStreamPause(hMidiStream); paused = true;
if (mmr != MMSYSERR_NOERROR)
{
MidiError("midiStreamPause", mmr);
}
} }
static void I_WIN_ResumeSong(void *handle) static void I_WIN_ResumeSong(void *handle)
{ {
MMRESULT mmr;
if (!hMidiStream) if (!hMidiStream)
{ {
return; return;
} }
mmr = midiStreamRestart(hMidiStream); paused = false;
if (mmr != MMSYSERR_NOERROR)
{
MidiError("midiStreamRestart", mmr);
}
} }
static void *I_WIN_RegisterSong(void *data, int len) static void *I_WIN_RegisterSong(void *data, int len)