Skip to content

Commit

Permalink
Change #6684: Cutting point overrides for music base sets
Browse files Browse the repository at this point in the history
This improves bad looping of title screen song from Windows TTD, and fixes
a long silence at the end of "Can't get there from here" from Windows TTD.
  • Loading branch information
nielsmh authored and michicc committed Jun 15, 2018
1 parent 836d25e commit 276192f
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 19 deletions.
12 changes: 12 additions & 0 deletions bin/baseset/orig_win.obm
Expand Up @@ -142,5 +142,17 @@ GM_TT19.GM = Funk Central
GM_TT20.GM = Jammit
GM_TT21.GM = Movin' On

; MIDI timecodes where the playback should attemp to start and stop short.
; This is to allow fixing undesired silences in original MIDI files.
; However not all music drivers may support this.
[timingtrim]
; Theme has two beats silence at the beginning which prevents clean looping.
GM_TT00.GM = 768:53760
; Can't Get There From Here from the Windows version has a long silence at the end,
; followed by a solo repeat. This isn't in the original DOS version music and is likely
; unintentional from the people who converted the music from the DOS version.
; Actual song ends after measure 152.
GM_TT10.GM = 0:235008

[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
12 changes: 12 additions & 0 deletions media/baseset/orig_win.obm
Expand Up @@ -90,5 +90,17 @@ GM_TT19.GM = Funk Central
GM_TT20.GM = Jammit
GM_TT21.GM = Movin' On

; MIDI timecodes where the playback should attemp to start and stop short.
; This is to allow fixing undesired silences in original MIDI files.
; However not all music drivers may support this.
[timingtrim]
; Theme has two beats silence at the beginning which prevents clean looping.
GM_TT00.GM = 768:53760
; Can't Get There From Here from the Windows version has a long silence at the end,
; followed by a solo repeat. This isn't in the original DOS version music and is likely
; unintentional from the people who converted the music from the DOS version.
; Actual song ends after measure 152.
GM_TT10.GM = 0:235008

[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
2 changes: 2 additions & 0 deletions src/base_media_base.h
Expand Up @@ -301,6 +301,8 @@ struct MusicSongInfo {
const char *filename; ///< file on disk containing song (when used in MusicSet class, this pointer is owned by MD5File object for the file)
MusicTrackType filetype; ///< decoder required for song file
int cat_index; ///< entry index in CAT file, for filetype==MTT_MPSMIDI
int override_start; ///< MIDI ticks to skip over in beginning
int override_end; ///< MIDI tick to end the song at (0 if no override)
};

/** All data of a music set. */
Expand Down
17 changes: 14 additions & 3 deletions src/music.cpp
Expand Up @@ -125,6 +125,7 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f
this->num_available = 0;
IniGroup *names = ini->GetGroup("names");
IniGroup *catindex = ini->GetGroup("catindex");
IniGroup *timingtrim = ini->GetGroup("timingtrim");
for (uint i = 0, j = 1; i < lengthof(this->songinfo); i++) {
const char *filename = this->files[i].filename;
if (names == NULL || StrEmpty(filename)) {
Expand All @@ -150,15 +151,16 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f
this->songinfo[i].filetype = MTT_STANDARDMIDI;
}

const char *trimmed_filename = filename;
/* As we possibly add a path to the filename and we compare
* on the filename with the path as in the .obm, we need to
* keep stripping path elements until we find a match. */
for (const char *p = filename; p != NULL; p = strchr(p, PATHSEPCHAR)) {
for (; trimmed_filename != NULL; trimmed_filename = strchr(trimmed_filename, PATHSEPCHAR)) {
/* Remove possible double path separator characters from
* the beginning, so we don't start reading e.g. root. */
while (*p == PATHSEPCHAR) p++;
while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++;

item = names->GetItem(p, false);
item = names->GetItem(trimmed_filename, false);
if (item != NULL && !StrEmpty(item->value)) break;
}

Expand All @@ -173,6 +175,15 @@ bool MusicSet::FillSetDetails(IniFile *ini, const char *path, const char *full_f
this->num_available++;

this->songinfo[i].tracknr = j++;

item = timingtrim->GetItem(trimmed_filename, false);
if (item != NULL && !StrEmpty(item->value)) {
const char *endpos = strchr(item->value, ':');
if (endpos != NULL) {
this->songinfo[i].override_start = atoi(item->value);
this->songinfo[i].override_end = atoi(endpos + 1);
}
}
}
}
return ret;
Expand Down
20 changes: 10 additions & 10 deletions src/music/dmusic.cpp
Expand Up @@ -723,14 +723,6 @@ static void MidiThreadProc(void *)
while (current_block < current_file.blocks.size()) {
MidiFile::DataBlock &block = current_file.blocks[current_block];

/* check that block is not in the future */
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)block.realtime * MIDITIME_TO_REFTIME - playback_time) / MS_TO_REFTIME - _playback.preload_time, 0, 1000);
DEBUG(driver, 9, "DMusic thread: Next event in %u ms (music %u, ref %lld)", next_timeout, block.realtime * MIDITIME_TO_REFTIME, playback_time);
break;
}
/* check that block isn't at end-of-song override */
if (current_segment.end > 0 && block.ticktime >= current_segment.end) {
if (current_segment.loop) {
Expand All @@ -743,6 +735,14 @@ static void MidiThreadProc(void *)
next_timeout = 0;
break;
}
/* check that block is not in the future */
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)block.realtime * MIDITIME_TO_REFTIME - playback_time) / MS_TO_REFTIME - _playback.preload_time, 0, 1000);
DEBUG(driver, 9, "DMusic thread: Next event in %u ms (music %u, ref %lld)", 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;
Expand Down Expand Up @@ -1232,8 +1232,8 @@ void MusicDriver_DMusic::PlaySong(const MusicSongInfo &song)

if (!_playback.next_file.LoadSong(song)) return;

_playback.next_segment.start = 0;
_playback.next_segment.end = 0;
_playback.next_segment.start = song.override_start;
_playback.next_segment.end = song.override_end;
_playback.next_segment.loop = false;

_playback.do_start = true;
Expand Down
12 changes: 6 additions & 6 deletions src/music/win32_m.cpp
Expand Up @@ -209,10 +209,6 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DW
while (_midi.current_block < _midi.current_file.blocks.size()) {
MidiFile::DataBlock &block = _midi.current_file.blocks[_midi.current_block];

/* check that block is not in the future */
if (block.realtime / 1000 > playback_time) {
break;
}
/* check that block isn't at end-of-song override */
if (_midi.current_segment.end > 0 && block.ticktime >= _midi.current_segment.end) {
if (_midi.current_segment.loop) {
Expand All @@ -223,6 +219,10 @@ void CALLBACK TimerCallback(UINT uTimerID, UINT, DWORD_PTR dwUser, DWORD_PTR, DW
}
break;
}
/* check that block is not in the future */
if (block.realtime / 1000 > playback_time) {
break;
}

byte *data = block.data.Begin();
size_t remaining = block.data.Length();
Expand Down Expand Up @@ -315,8 +315,8 @@ void MusicDriver_Win32::PlaySong(const MusicSongInfo &song)
return;
}

_midi.next_segment.start = 0;
_midi.next_segment.end = 0;
_midi.next_segment.start = song.override_start;
_midi.next_segment.end = song.override_end;
_midi.next_segment.loop = false;

DEBUG(driver, 2, "Win32-MIDI: PlaySong: setting flag");
Expand Down

0 comments on commit 276192f

Please sign in to comment.