aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Horn2009-03-09 16:15:35 +0000
committerMax Horn2009-03-09 16:15:35 +0000
commit4e6a7d83d116dc9ae81d51a7f0ac61134486304d (patch)
tree4b34fe34ee0bf0af8c2cb82610b6ba5112bcc86b
parent77b40251ca9f22b71680888ee6dd69e027f765ba (diff)
downloadscummvm-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.cfsml2
-rw-r--r--engines/sci/engine/savegame.cpp2
-rw-r--r--engines/sci/sfx/core.cpp62
-rw-r--r--engines/sci/sfx/core.h3
-rw-r--r--engines/sci/sfx/player/realtime.cpp2
-rw-r--r--engines/sci/sfx/songlib.cpp3
-rw-r--r--engines/sci/sfx/songlib.h7
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