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")
#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();

View File

@ -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++;
}
}

View File

@ -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<uint8_t> data; ///< raw midi data contained in block
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();
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;
}