diff options
author | Max Horn | 2009-03-09 16:15:35 +0000 |
---|---|---|
committer | Max Horn | 2009-03-09 16:15:35 +0000 |
commit | 4e6a7d83d116dc9ae81d51a7f0ac61134486304d (patch) | |
tree | 4b34fe34ee0bf0af8c2cb82610b6ba5112bcc86b | |
parent | 77b40251ca9f22b71680888ee6dd69e027f765ba (diff) | |
download | scummvm-rg350-4e6a7d83d116dc9ae81d51a7f0ac61134486304d.tar.gz scummvm-rg350-4e6a7d83d116dc9ae81d51a7f0ac61134486304d.tar.bz2 scummvm-rg350-4e6a7d83d116dc9ae81d51a7f0ac61134486304d.zip |
SCI: Rewrote handling of song wakeup times & (iterator) delays, to avoid rounding issues between ticks (1/60s) and milliseconds; also fixed a bug (coming from Glutton ;) where delays measured in millisecs were treated as ticks instead. Thanks to Walter for the precursor of this patch
svn-id: r39263
-rw-r--r-- | engines/sci/engine/savegame.cfsml | 2 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 2 | ||||
-rw-r--r-- | engines/sci/sfx/core.cpp | 62 | ||||
-rw-r--r-- | engines/sci/sfx/core.h | 3 | ||||
-rw-r--r-- | engines/sci/sfx/player/realtime.cpp | 2 | ||||
-rw-r--r-- | engines/sci/sfx/songlib.cpp | 3 | ||||
-rw-r--r-- | engines/sci/sfx/songlib.h | 7 |
7 files changed, 37 insertions, 44 deletions
diff --git a/engines/sci/engine/savegame.cfsml b/engines/sci/engine/savegame.cfsml index ce582ca730..0be2ab1dd4 100644 --- a/engines/sci/engine/savegame.cfsml +++ b/engines/sci/engine/savegame.cfsml @@ -505,7 +505,7 @@ int read_song_tp(Common::SeekableReadStream *fh, song_t **foo, const char *lastv *foo = (song_t*) malloc(sizeof(song_t)); token = _cfsml_get_identifier(fh, line, hiteof, &assignment); %CFSMLREAD song_t (*foo) FROM fh ERRVAR *hiteof FIRSTTOKEN token LINECOUNTER *line; - (*foo)->delay = 0; + (*foo)->_delay = 0; (*foo)->it = NULL; (*foo)->next_playing = (*foo)->next_stopping = (*foo)->next = NULL; return 0; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index ca9ecff0a1..afee660a16 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -4129,7 +4129,7 @@ int read_song_tp(Common::SeekableReadStream *fh, song_t **foo, const char *lastv } // End of auto-generated CFSML data reader code #line 508 "engines/sci/engine/savegame.cfsml" - (*foo)->delay = 0; + (*foo)->_delay = 0; (*foo)->it = NULL; (*foo)->next_playing = (*foo)->next_stopping = (*foo)->next = NULL; return 0; diff --git a/engines/sci/sfx/core.cpp b/engines/sci/sfx/core.cpp index a427a5fd7f..698dc9a465 100644 --- a/engines/sci/sfx/core.cpp +++ b/engines/sci/sfx/core.cpp @@ -73,14 +73,13 @@ int sfx_get_player_polyphony() { static void _freeze_time(sfx_state_t *self) { /* Freezes the top song delay time */ - uint32 ctime = g_system->getMillis(); + const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); song_t *song = self->song; while (song) { - if (ctime > song->wakeup_time) - song->delay = 0; - else - song->delay = song->wakeup_time - ctime; + song->_delay = song->_wakeupTime.frameDiff(ctime); + if (song->_delay < 0) + song->_delay = 0; song = song->next_playing; } @@ -132,11 +131,11 @@ static void _dump_songs(sfx_state_t *self) { static void _thaw_time(sfx_state_t *self) { /* inverse of _freeze_time() */ - uint32 ctime = g_system->getMillis(); + const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); song_t *song = self->song; while (song) { - song->wakeup_time = ctime + song->delay; + song->_wakeupTime = ctime.addFrames(song->_delay); song = song->next_playing; } @@ -156,21 +155,21 @@ static int is_playing(sfx_state_t *self, song_t *song) { } static void _sfx_set_song_status(sfx_state_t *self, song_t *song, int status) { + const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); + switch (status) { case SOUND_STATUS_STOPPED: - /* Reset */ + // Reset song->it->init(); break; case SOUND_STATUS_SUSPENDED: case SOUND_STATUS_WAITING: if (song->status == SOUND_STATUS_PLAYING) { - /* Update delay, set wakeup_time */ - uint32 time = g_system->getMillis(); - - song->delay -= long(time) - long(song->wakeup_time); - song->wakeup_time = time; + // Update delay, set wakeup_time + song->_delay += song->_wakeupTime.frameDiff(ctime); + song->_wakeupTime = ctime; } if (status == SOUND_STATUS_SUSPENDED) break; @@ -178,9 +177,10 @@ static void _sfx_set_song_status(sfx_state_t *self, song_t *song, int status) { /* otherwise... */ case SOUND_STATUS_PLAYING: - if (song->status == SOUND_STATUS_STOPPED) - /* Starting anew */ - song->wakeup_time = g_system->getMillis(); + if (song->status == SOUND_STATUS_STOPPED) { + // Starting anew + song->_wakeupTime = ctime; + } if (is_playing(self, song)) status = SOUND_STATUS_PLAYING; @@ -244,10 +244,9 @@ static void _update_single_song(sfx_state_t *self) { _thaw_time(self); /* Recover song delay time */ if (newsong && player) { - SongIterator *clonesong - = songit_clone(newsong->it, newsong->delay); + SongIterator *clonesong = songit_clone(newsong->it, newsong->_delay); - player->add_iterator(clonesong, newsong->wakeup_time); + player->add_iterator(clonesong, newsong->_wakeupTime.msecs()); } } } @@ -310,15 +309,13 @@ static void _update_multi_song(sfx_state_t *self) { oldseeker->next_playing = NULL; /* Clear this pointer; we don't need the tag anymore */ } - for (newseeker = newsong; newseeker; - newseeker = newseeker->next_playing) { + for (newseeker = newsong; newseeker; newseeker = newseeker->next_playing) { if (newseeker->status != SOUND_STATUS_PLAYING && player) { if (self->debug & SFX_DEBUG_SONGS) sciprintf("[SFX] Adding song %lx\n", newseeker->it->ID); - player->add_iterator(songit_clone(newseeker->it, - newseeker->delay), - g_system->getMillis()); + SongIterator *clonesong = songit_clone(newseeker->it, newseeker->_delay); + player->add_iterator(clonesong, g_system->getMillis()); } _sfx_set_song_status(self, newseeker, SOUND_STATUS_PLAYING); @@ -351,8 +348,7 @@ int sfx_play_iterator_pcm(SongIterator *it, song_handle_t handle) { return 0; } -#define FREQ 60 -#define DELAY (1000000 / FREQ) +#define DELAY (1000000 / SFX_TICKS_PER_SEC) static void _sfx_timer_callback(void *data) { @@ -483,7 +479,7 @@ int sfx_poll(sfx_state_t *self, song_handle_t *handle, int *cue) { } int sfx_poll_specific(sfx_state_t *self, song_handle_t handle, int *cue) { - uint32 ctime = g_system->getMillis(); + const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); song_t *song = self->song; while (song && song->handle != handle) @@ -497,13 +493,11 @@ int sfx_poll_specific(sfx_state_t *self, song_handle_t handle, int *cue) { } while (1) { - unsigned char buf[8]; - int result; - - if (song->wakeup_time > ctime) + if (song->_wakeupTime.frameDiff(ctime) > 0) return 0; /* Patience, young hacker! */ - result = songit_next(&(song->it), buf, cue, IT_READER_MASK_ALL); + unsigned char buf[8]; + int result = songit_next(&(song->it), buf, cue, IT_READER_MASK_ALL); switch (result) { @@ -532,7 +526,7 @@ int sfx_poll_specific(sfx_state_t *self, song_handle_t handle, int *cue) { default: if (result > 0) - song->wakeup_time += result * SOUND_TICK; + song->_wakeupTime = song->_wakeupTime.addFrames(result); /* Delay */ break; @@ -587,7 +581,7 @@ int sfx_add_song(sfx_state_t *self, SongIterator *it, int priority, song_handle_ song->resource_num = number; song->hold = 0; song->loops = 0; - song->wakeup_time = g_system->getMillis(); /* No need to delay */ + song->_wakeupTime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); song_lib_add(self->songlib, song); self->song = NULL; /* As above */ _update(self); diff --git a/engines/sci/sfx/core.h b/engines/sci/sfx/core.h index e7f8a8db07..3eb3cf1489 100644 --- a/engines/sci/sfx/core.h +++ b/engines/sci/sfx/core.h @@ -36,8 +36,7 @@ namespace Sci { class SongIterator; struct fade_params_t; -#define SOUND_TICK 1000 / 60 -/* Approximately 17 milliseconds */ +#define SFX_TICKS_PER_SEC 60 /* MIDI ticks per second */ #define SFX_STATE_FLAG_MULTIPLAY (1 << 0) /* More than one song playable diff --git a/engines/sci/sfx/player/realtime.cpp b/engines/sci/sfx/player/realtime.cpp index a3832ed51f..60053c57ae 100644 --- a/engines/sci/sfx/player/realtime.cpp +++ b/engines/sci/sfx/player/realtime.cpp @@ -100,7 +100,7 @@ static void play_song(SongIterator *it, uint32 *wakeup_time, int writeahead_time default: play_moredelay = delay - 1; - *wakeup_time += delay * SOUND_TICK; + *wakeup_time += delay * 1000 / SFX_TICKS_PER_SEC; if (seq->delay) seq->delay(delay); } diff --git a/engines/sci/sfx/songlib.cpp b/engines/sci/sfx/songlib.cpp index 3d6f22612e..2161bee779 100644 --- a/engines/sci/sfx/songlib.cpp +++ b/engines/sci/sfx/songlib.cpp @@ -43,7 +43,8 @@ song_t *song_new(song_handle_t handle, SongIterator *it, int priority) { retval->handle = handle; retval->priority = priority; retval->next = NULL; - retval->delay = 0; + retval->_delay = 0; + retval->_wakeupTime = Audio::Timestamp(); retval->it = it; retval->status = SOUND_STATUS_STOPPED; retval->next_playing = NULL; diff --git a/engines/sci/sfx/songlib.h b/engines/sci/sfx/songlib.h index 490bd47770..efce1e17b0 100644 --- a/engines/sci/sfx/songlib.h +++ b/engines/sci/sfx/songlib.h @@ -29,6 +29,7 @@ #define SCI_SFX_SFX_SONGLIB_H #include "common/scummsys.h" +#include "sound/timestamp.h" namespace Sci { @@ -63,11 +64,9 @@ struct song_t { int hold; SongIterator *it; - long delay; /* Delay before accessing the iterator, in microseconds */ + int _delay; /* Delay before accessing the iterator, in ticks */ - uint32 wakeup_time; /* Used by the sound core: - ** Playing -> time at which 'delay' has elapsed - ** Suspended/Waiting -> stopping time */ + Audio::Timestamp _wakeupTime; /**< Timestamp indicating the next MIDI event */ song_t *next; /* Next song or NULL if this is the last one */ song_t *next_playing; /* Next playing song; used by the |