diff options
author | Niels Martin Hansen <nielsm@indvikleren.dk> | 2019-07-04 21:51:01 +0200 |
---|---|---|
committer | Niels Martin Hansen <nielsm@indvikleren.dk> | 2019-07-04 22:27:34 +0200 |
commit | a0c78c73e3c19dcbb1c295b30f17c38f7289b608 (patch) | |
tree | a84cef189de1660fc952f26fc92b607bfab2b944 | |
parent | 27b7c5a5fde021d0b00cd73b5fb1412fcf0431cd (diff) | |
download | openttd-a0c78c73e3c19dcbb1c295b30f17c38f7289b608.tar.xz |
Fix: Correctly reset playback between songs in win32_m driver
-rw-r--r-- | src/music/win32_m.cpp | 115 |
1 files changed, 60 insertions, 55 deletions
diff --git a/src/music/win32_m.cpp b/src/music/win32_m.cpp index 1447fd88a..21ffe1ed3 100644 --- a/src/music/win32_m.cpp +++ b/src/music/win32_m.cpp @@ -36,7 +36,7 @@ static struct { std::mutex lock; ///< synchronization for playback status fields bool playing; ///< flag indicating that playback is active - bool do_start; ///< flag for starting playback of next_file at next opportunity + int do_start; ///< flag for starting playback of next_file at next opportunity bool do_stop; ///< flag for stopping playback at next opportunity byte current_volume; ///< current effective volume setting byte new_volume; ///< volume setting to change to @@ -115,66 +115,77 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DW std::unique_lock<std::mutex> mutex_lock(_midi.lock, std::defer_lock); if (!mutex_lock.try_lock()) return; - { - /* check for stop */ - if (_midi.do_stop) { - DEBUG(driver, 2, "Win32-MIDI: timer: do_stop is set"); - midiOutReset(_midi.midi_out); - _midi.playing = false; - _midi.do_stop = false; + /* check for stop */ + if (_midi.do_stop) { + DEBUG(driver, 2, "Win32-MIDI: timer: do_stop is set"); + midiOutReset(_midi.midi_out); + _midi.playing = false; + _midi.do_stop = false; + return; + } + + /* check for start/restart/change song */ + if (_midi.do_start != 0) { + /* Have a delay between playback start steps, prevents jumbled-together notes at the start of song */ + if (timeGetTime() - _midi.playback_start_time < 50) { return; } + DEBUG(driver, 2, "Win32-MIDI: timer: do_start step %d", _midi.do_start); - /* check for start/restart/change song */ - if (_midi.do_start) { - DEBUG(driver, 2, "Win32-MIDI: timer: do_start is set"); - if (_midi.playing) { - midiOutReset(_midi.midi_out); - /* Some songs change the "Pitch bend range" registered - * parameter. If this doesn't get reset, everything else - * will start sounding wrong. */ - for (int ch = 0; ch < 16; ch++) { - /* Running status, only need status for first message */ - /* Select RPN 00.00, set value to 02.00, and unselect again */ - TransmitChannelMsg(MIDIST_CONTROLLER | ch, MIDICT_RPN_SELECT_LO, 0x00); - TransmitChannelMsg(MIDICT_RPN_SELECT_HI, 0x00); - TransmitChannelMsg(MIDICT_DATAENTRY, 0x02); - TransmitChannelMsg(MIDICT_DATAENTRY_LO, 0x00); - TransmitChannelMsg(MIDICT_RPN_SELECT_LO, 0x7F); - TransmitChannelMsg(MIDICT_RPN_SELECT_HI, 0x7F); - } - } + if (_midi.do_start == 1) { + /* Send "all notes off" */ + midiOutReset(_midi.midi_out); + _midi.playback_start_time = timeGetTime(); + _midi.do_start = 2; + + return; + } else if (_midi.do_start == 2) { + /* Reset the device to General MIDI defaults */ + TransmitStandardSysex(MidiSysexMessage::ResetGM); + _midi.playback_start_time = timeGetTime(); + _midi.do_start = 3; + + return; + } else if (_midi.do_start == 3) { + /* Set up device-specific effects */ + TransmitStandardSysex(MidiSysexMessage::RolandSetReverb); + _midi.playback_start_time = timeGetTime(); + _midi.do_start = 4; + + return; + } else if (_midi.do_start == 4) { + /* Load the new file */ _midi.current_file.MoveFrom(_midi.next_file); std::swap(_midi.next_segment, _midi.current_segment); _midi.current_segment.start_block = 0; _midi.playback_start_time = timeGetTime(); _midi.playing = true; - _midi.do_start = false; + _midi.do_start = 0; _midi.current_block = 0; MemSetT<byte>(_midi.channel_volumes, 127, lengthof(_midi.channel_volumes)); - } else if (!_midi.playing) { - /* not playing, stop the timer */ - DEBUG(driver, 2, "Win32-MIDI: timer: not playing, stopping timer"); - timeKillEvent(uTimerID); - _midi.timer_id = 0; - return; } + } else if (!_midi.playing) { + /* not playing, stop the timer */ + DEBUG(driver, 2, "Win32-MIDI: timer: not playing, stopping timer"); + timeKillEvent(uTimerID); + _midi.timer_id = 0; + return; + } - /* check for volume change */ - static int volume_throttle = 0; - if (_midi.current_volume != _midi.new_volume) { - if (volume_throttle == 0) { - DEBUG(driver, 2, "Win32-MIDI: timer: volume change"); - _midi.current_volume = _midi.new_volume; - volume_throttle = 20 / _midi.time_period; - for (int ch = 0; ch < 16; ch++) { - int vol = ScaleVolume(_midi.channel_volumes[ch], _midi.current_volume); - TransmitChannelMsg(MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol); - } - } else { - volume_throttle--; + /* check for volume change */ + static int volume_throttle = 0; + if (_midi.current_volume != _midi.new_volume) { + if (volume_throttle == 0) { + DEBUG(driver, 2, "Win32-MIDI: timer: volume change"); + _midi.current_volume = _midi.new_volume; + volume_throttle = 20 / _midi.time_period; + for (int ch = 0; ch < 16; ch++) { + byte vol = ScaleVolume(_midi.channel_volumes[ch], _midi.current_volume); + TransmitChannelMsg(MIDIST_CONTROLLER | ch, MIDICT_CHANVOLUME, vol); } + } else { + volume_throttle--; } } @@ -326,7 +337,7 @@ void MusicDriver_Win32::PlaySong(const MusicSongInfo &song) DEBUG(driver, 2, "Win32-MIDI: PlaySong: setting flag"); _midi.do_stop = _midi.playing; - _midi.do_start = true; + _midi.do_start = 1; if (_midi.timer_id == 0) { DEBUG(driver, 2, "Win32-MIDI: PlaySong: starting timer"); @@ -344,7 +355,7 @@ void MusicDriver_Win32::StopSong() bool MusicDriver_Win32::IsSongPlaying() { - return _midi.playing || _midi.do_start; + return _midi.playing || (_midi.do_start != 0); } void MusicDriver_Win32::SetVolume(byte vol) @@ -375,12 +386,6 @@ const char *MusicDriver_Win32::Start(const char * const *parm) midiOutReset(_midi.midi_out); - /* Standard "Enable General MIDI" message */ - TransmitStandardSysex(MidiSysexMessage::ResetGM); - - /* Roland-specific reverb room control, used by the original game */ - TransmitStandardSysex(MidiSysexMessage::RolandSetReverb); - /* prepare multimedia timer */ TIMECAPS timecaps; if (timeGetDevCaps(&timecaps, sizeof(timecaps)) == MMSYSERR_NOERROR) { |