From f7db4938ce15369aabd6c893bc6e5bd33a3456f4 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 2 May 2025 22:20:44 +0100 Subject: [PATCH] Fix #14098: Use 64-bit type for MIDI realtime information. (#14144) --- src/music/dmusic.cpp | 12 ++++++------ src/music/midifile.cpp | 6 +++--- src/music/midifile.hpp | 2 +- src/music/win32_m.cpp | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/music/dmusic.cpp b/src/music/dmusic.cpp index e4863997b1..ca7d5aece9 100644 --- a/src/music/dmusic.cpp +++ b/src/music/dmusic.cpp @@ -34,8 +34,8 @@ # pragma comment(lib, "ole32.lib") #endif /* defined(_MSC_VER) */ -static const int MS_TO_REFTIME = 1000 * 10; ///< DirectMusic time base is 100 ns. -static const int MIDITIME_TO_REFTIME = 10; ///< Time base of the midi file reader is 1 us. +static constexpr REFERENCE_TIME MS_TO_REFTIME = 1000 * 10; ///< DirectMusic time base is 100 ns. +static constexpr REFERENCE_TIME MIDITIME_TO_REFTIME = 10; ///< Time base of the midi file reader is 1 us. #define FOURCC_INFO mmioFOURCC('I', 'N', 'F', 'O') @@ -665,14 +665,14 @@ static void MidiThreadProc() preload_bytes += block.data.size(); if (block.ticktime >= current_segment.start) { if (current_segment.loop) { - Debug(driver, 2, "DMusic: timer: loop from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, ((int)block.realtime) / 1000.0, preload_bytes); + Debug(driver, 2, "DMusic: timer: loop from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, block.realtime / 1000.0, preload_bytes); current_segment.start_block = bl; break; } else { /* Skip the transmission delay compensation performed in the Win32 MIDI driver. * The DMusic driver will most likely be used with the MS softsynth, which is not subject to transmission delays. */ - Debug(driver, 2, "DMusic: timer: start from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, ((int)block.realtime) / 1000.0, preload_bytes); + Debug(driver, 2, "DMusic: timer: start from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, block.realtime / 1000.0, preload_bytes); playback_start_time -= block.realtime * MIDITIME_TO_REFTIME; break; } @@ -718,14 +718,14 @@ static void MidiThreadProc() REFERENCE_TIME playback_time = current_time - playback_start_time; if (block.realtime * MIDITIME_TO_REFTIME > playback_time + 3 *_playback.preload_time * MS_TO_REFTIME) { /* Stop the thread loop until we are at the preload time of the next block. */ - next_timeout = Clamp(((int64_t)block.realtime * MIDITIME_TO_REFTIME - playback_time) / MS_TO_REFTIME - _playback.preload_time, 0, 1000); + next_timeout = Clamp((block.realtime * MIDITIME_TO_REFTIME - playback_time) / MS_TO_REFTIME - _playback.preload_time, 0, 1000); Debug(driver, 9, "DMusic thread: Next event in {} ms (music {}, ref {})", next_timeout, block.realtime * MIDITIME_TO_REFTIME, playback_time); break; } /* Timestamp of the current block. */ block_time = playback_start_time + block.realtime * MIDITIME_TO_REFTIME; - Debug(driver, 9, "DMusic thread: Streaming block {} (cur={}, block={})", current_block, (long long)(current_time / MS_TO_REFTIME), (long long)(block_time / MS_TO_REFTIME)); + Debug(driver, 9, "DMusic thread: Streaming block {} (cur={}, block={})", current_block, current_time / MS_TO_REFTIME, block_time / MS_TO_REFTIME); const uint8_t *data = block.data.data(); size_t remaining = block.data.size(); diff --git a/src/music/midifile.cpp b/src/music/midifile.cpp index 2ec38161fe..c94625c233 100644 --- a/src/music/midifile.cpp +++ b/src/music/midifile.cpp @@ -377,7 +377,7 @@ static bool FixupMidiData(MidiFile &target) /* Annotate blocks with real time */ last_ticktime = 0; - uint32_t last_realtime = 0; + int64_t last_realtime = 0; size_t cur_tempo = 0, cur_block = 0; while (cur_block < target.blocks.size()) { MidiFile::DataBlock &block = target.blocks[cur_block]; @@ -387,14 +387,14 @@ static bool FixupMidiData(MidiFile &target) /* block is within the current tempo */ int64_t tickdiff = block.ticktime - last_ticktime; last_ticktime = block.ticktime; - last_realtime += uint32_t(tickdiff * tempo.tempo / target.tickdiv); + last_realtime += tickdiff * tempo.tempo / target.tickdiv; block.realtime = last_realtime; cur_block++; } else { /* tempo change occurs before this block */ int64_t tickdiff = next_tempo.ticktime - last_ticktime; last_ticktime = next_tempo.ticktime; - last_realtime += uint32_t(tickdiff * tempo.tempo / target.tickdiv); // current tempo until the tempo change + last_realtime += tickdiff * tempo.tempo / target.tickdiv; // current tempo until the tempo change cur_tempo++; } } diff --git a/src/music/midifile.hpp b/src/music/midifile.hpp index dd6eb37a83..27cb05db5b 100644 --- a/src/music/midifile.hpp +++ b/src/music/midifile.hpp @@ -18,7 +18,7 @@ struct MusicSongInfo; struct MidiFile { struct DataBlock { uint32_t ticktime; ///< tick number since start of file this block should be triggered at - uint32_t realtime = 0; ///< real-time (microseconds) since start of file this block should be triggered at + int64_t realtime = 0; ///< real-time (microseconds) since start of file this block should be triggered at std::vector data; ///< raw midi data contained in block DataBlock(uint32_t _ticktime = 0) : ticktime(_ticktime) { } }; diff --git a/src/music/win32_m.cpp b/src/music/win32_m.cpp index 00900f8161..a8c3c1d783 100644 --- a/src/music/win32_m.cpp +++ b/src/music/win32_m.cpp @@ -202,7 +202,7 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR preload_bytes += block.data.size(); if (block.ticktime >= _midi.current_segment.start) { if (_midi.current_segment.loop) { - Debug(driver, 2, "Win32-MIDI: timer: loop from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, ((int)block.realtime)/1000.0, preload_bytes); + Debug(driver, 2, "Win32-MIDI: timer: loop from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, block.realtime / 1000.0, preload_bytes); _midi.current_segment.start_block = bl; break; } else { @@ -211,7 +211,7 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR * which have a bitrate of 31,250 bits/sec, and transmit 1+8+1 start/data/stop bits per byte. * The delay compensation is needed to avoid time-compression of following messages. */ - Debug(driver, 2, "Win32-MIDI: timer: start from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, ((int)block.realtime) / 1000.0, preload_bytes); + Debug(driver, 2, "Win32-MIDI: timer: start from block {} (ticktime {}, realtime {:.3f}, bytes {})", bl, block.ticktime, block.realtime / 1000.0, preload_bytes); _midi.playback_start_time -= block.realtime / 1000 - (DWORD)(preload_bytes * 1000 / 3125); break; }