1
0
Fork 0

Fix #14098: Use 64-bit type for MIDI realtime information. (#14144)

pull/10063/merge
Peter Nelson 2025-05-02 22:20:44 +01:00 committed by GitHub
parent c420ba349d
commit f7db4938ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 12 additions and 12 deletions

View File

@ -34,8 +34,8 @@
# pragma comment(lib, "ole32.lib") # pragma comment(lib, "ole32.lib")
#endif /* defined(_MSC_VER) */ #endif /* defined(_MSC_VER) */
static const int MS_TO_REFTIME = 1000 * 10; ///< DirectMusic time base is 100 ns. static constexpr REFERENCE_TIME 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 MIDITIME_TO_REFTIME = 10; ///< Time base of the midi file reader is 1 us.
#define FOURCC_INFO mmioFOURCC('I', 'N', 'F', 'O') #define FOURCC_INFO mmioFOURCC('I', 'N', 'F', 'O')
@ -665,14 +665,14 @@ static void MidiThreadProc()
preload_bytes += block.data.size(); preload_bytes += block.data.size();
if (block.ticktime >= current_segment.start) { if (block.ticktime >= current_segment.start) {
if (current_segment.loop) { 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; current_segment.start_block = bl;
break; break;
} else { } else {
/* Skip the transmission delay compensation performed in the Win32 MIDI driver. /* 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. * 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; playback_start_time -= block.realtime * MIDITIME_TO_REFTIME;
break; break;
} }
@ -718,14 +718,14 @@ static void MidiThreadProc()
REFERENCE_TIME playback_time = current_time - playback_start_time; REFERENCE_TIME playback_time = current_time - playback_start_time;
if (block.realtime * MIDITIME_TO_REFTIME > playback_time + 3 *_playback.preload_time * MS_TO_REFTIME) { 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. */ /* 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); Debug(driver, 9, "DMusic thread: Next event in {} ms (music {}, ref {})", next_timeout, block.realtime * MIDITIME_TO_REFTIME, playback_time);
break; break;
} }
/* Timestamp of the current block. */ /* Timestamp of the current block. */
block_time = playback_start_time + block.realtime * MIDITIME_TO_REFTIME; 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(); const uint8_t *data = block.data.data();
size_t remaining = block.data.size(); size_t remaining = block.data.size();

View File

@ -377,7 +377,7 @@ static bool FixupMidiData(MidiFile &target)
/* Annotate blocks with real time */ /* Annotate blocks with real time */
last_ticktime = 0; last_ticktime = 0;
uint32_t last_realtime = 0; int64_t last_realtime = 0;
size_t cur_tempo = 0, cur_block = 0; size_t cur_tempo = 0, cur_block = 0;
while (cur_block < target.blocks.size()) { while (cur_block < target.blocks.size()) {
MidiFile::DataBlock &block = target.blocks[cur_block]; MidiFile::DataBlock &block = target.blocks[cur_block];
@ -387,14 +387,14 @@ static bool FixupMidiData(MidiFile &target)
/* block is within the current tempo */ /* block is within the current tempo */
int64_t tickdiff = block.ticktime - last_ticktime; int64_t tickdiff = block.ticktime - last_ticktime;
last_ticktime = block.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; block.realtime = last_realtime;
cur_block++; cur_block++;
} else { } else {
/* tempo change occurs before this block */ /* tempo change occurs before this block */
int64_t tickdiff = next_tempo.ticktime - last_ticktime; int64_t tickdiff = next_tempo.ticktime - last_ticktime;
last_ticktime = next_tempo.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++; cur_tempo++;
} }
} }

View File

@ -18,7 +18,7 @@ struct MusicSongInfo;
struct MidiFile { struct MidiFile {
struct DataBlock { struct DataBlock {
uint32_t ticktime; ///< tick number since start of file this block should be triggered at 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<uint8_t> data; ///< raw midi data contained in block std::vector<uint8_t> data; ///< raw midi data contained in block
DataBlock(uint32_t _ticktime = 0) : ticktime(_ticktime) { } DataBlock(uint32_t _ticktime = 0) : ticktime(_ticktime) { }
}; };

View File

@ -202,7 +202,7 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR, DWORD_PTR, DWORD_PTR
preload_bytes += block.data.size(); preload_bytes += block.data.size();
if (block.ticktime >= _midi.current_segment.start) { if (block.ticktime >= _midi.current_segment.start) {
if (_midi.current_segment.loop) { 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; _midi.current_segment.start_block = bl;
break; break;
} else { } 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. * 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. * 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); _midi.playback_start_time -= block.realtime / 1000 - (DWORD)(preload_bytes * 1000 / 3125);
break; break;
} }