aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scumm/sound.cpp4
-rw-r--r--sound/mixer.cpp63
-rw-r--r--sound/mixer.h27
3 files changed, 59 insertions, 35 deletions
diff --git a/scumm/sound.cpp b/scumm/sound.cpp
index 19f4c74c13..5eaf0beedc 100644
--- a/scumm/sound.cpp
+++ b/scumm/sound.cpp
@@ -958,7 +958,7 @@ void Sound::stopSfxSound() {
}
bool Sound::isSfxFinished() {
- return !_scumm->_mixer->hasActiveChannel();
+ return !_scumm->_mixer->hasActiveSFXChannel();
}
uint32 Sound::decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo = false) {
@@ -1577,7 +1577,7 @@ int Sound::updateMP3CD() {
return -1;
}
- if (_scumm->_mixer->_channels[_dig_cd_index]->soundFinished()) {
+ if (!_scumm->_mixer->isActiveChannel(_dig_cd_index)) {
if (_dig_cd_num_loops == -1 || --_dig_cd_num_loops > 0)
playMP3CDTrack(_dig_cd_track, _dig_cd_num_loops, _dig_cd_start, _dig_cd_delay);
else
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index b919ced842..9e1ca4cfc7 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -26,6 +26,22 @@
#include "common/file.h"
+class Channel {
+protected:
+ SoundMixer *_mixer;
+public:
+ bool _toBeDestroyed;
+ int _id;
+ Channel() : _mixer(0), _toBeDestroyed(false), _id(-1) {}
+ virtual ~Channel() {}
+ virtual void mix(int16 *data, uint len) = 0;
+ void destroy() {
+ _toBeDestroyed = true;
+ }
+ virtual bool isActive();
+ virtual bool isMusicChannel() = 0;
+};
+
class ChannelRaw : public Channel {
byte *_ptr;
uint32 _pos;
@@ -42,6 +58,9 @@ public:
~ChannelRaw();
void mix(int16 *data, uint len);
+ bool isMusicChannel() {
+ return false; // TODO: IS this correct? Or does any Scumm game us this for music?
+ }
};
class ChannelStream : public Channel {
@@ -61,6 +80,9 @@ public:
void mix(int16 *data, uint len);
void append(void *sound, uint32 size);
+ bool isMusicChannel() {
+ return true;
+ }
};
#ifdef USE_MAD
@@ -81,6 +103,9 @@ public:
~ChannelMP3();
void mix(int16 *data, uint len);
+ bool isMusicChannel() {
+ return false;
+ }
};
class ChannelMP3CDMusic : public Channel {
@@ -101,7 +126,10 @@ public:
~ChannelMP3CDMusic();
void mix(int16 *data, uint len);
- bool soundFinished();
+ bool isActive();
+ bool isMusicChannel() {
+ return true;
+ }
};
#endif
@@ -116,7 +144,10 @@ public:
ChannelVorbis(SoundMixer *mixer, OggVorbis_File *ov_file, int duration, bool is_cd_track);
void mix(int16 *data, uint len);
- bool soundFinished();
+ bool isActive();
+ bool isMusicChannel() {
+ return _is_cd_track;
+ }
};
#endif
@@ -276,13 +307,23 @@ void SoundMixer::pause(bool paused) {
_paused = paused;
}
-bool SoundMixer::hasActiveChannel() {
+bool SoundMixer::hasActiveSFXChannel() {
+ // FIXME/TODO: We need to distinguish between SFX and music channels
+ // (and maybe also voice) here to work properly in iMuseDigital
+ // games. In the past that was achieve using the _beginSlots hack.
+ // Since we don't have that anymore, it's not that simple anymore.
for (int i = 0; i != NUM_CHANNELS; i++)
- if (_channels[i])
+ if (_channels[i] && !_channels[i]->isMusicChannel())
return true;
return false;
}
+bool SoundMixer::isActiveChannel(int index) {
+ if (_channels[index])
+ return _channels[index]->isActive();
+ return false;
+}
+
void SoundMixer::setupPremix(void *param, PremixProc *proc) {
_premixParam = param;
_premixProc = proc;
@@ -596,9 +637,9 @@ static int16 mixer_element_size[] = {
4, 4
};
-bool Channel::soundFinished() {
- warning("sound_finished should never be called on a non-MP3 mixer ");
- return false;
+bool Channel::isActive() {
+ error("isActive should never be called on a non-MP3 mixer ");
+ return true;
}
/* RAW mixer */
@@ -979,8 +1020,8 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) {
}
}
-bool ChannelMP3CDMusic::soundFinished() {
- return mad_timer_compare(_duration, mad_timer_zero) <= 0;
+bool ChannelMP3CDMusic::isActive() {
+ return mad_timer_compare(_duration, mad_timer_zero) > 0;
}
#endif
@@ -1061,8 +1102,8 @@ void ChannelVorbis::mix(int16 *data, uint len) {
destroy();
}
-bool ChannelVorbis::soundFinished() {
- return _eof_flag || (_end_pos > 0 && ov_pcm_tell(_ov_file) >= _end_pos);
+bool ChannelVorbis::isActive() {
+ return !_eof_flag && (_end_pos <= 0 && ov_pcm_tell(_ov_file) >= _end_pos);
}
#endif
diff --git a/sound/mixer.h b/sound/mixer.h
index 06f22e38fc..bced868538 100644
--- a/sound/mixer.h
+++ b/sound/mixer.h
@@ -41,26 +41,6 @@ typedef uint32 PlayingSoundHandle;
class Channel;
class File;
-class SoundMixer;
-
-// TODO: class Channel should really be declared non-public, inside mixer.cpp
-// However, right now Sound::updateMP3CD directly calls soundFinished. That
-// should be changed, by adding proper API abstraction to SoundMixer for
-// MP3/Vorbis "CD" playback.
-class Channel {
-protected:
- SoundMixer *_mixer;
-public:
- bool _toBeDestroyed;
- int _id;
- Channel() : _mixer(0), _toBeDestroyed(false), _id(-1) {}
- virtual ~Channel() {}
- virtual void mix(int16 *data, uint len) = 0;
- void destroy() {
- _toBeDestroyed = true;
- }
- virtual bool soundFinished();
-};
class SoundMixer {
public:
@@ -133,8 +113,11 @@ public:
/** append to existing sound */
int append(int index, void * sound, uint32 size);
- /** is any channel active? */
- bool hasActiveChannel();
+ /** Check whether any SFX channel is active.*/
+ bool hasActiveSFXChannel();
+
+ /** Check whether the specified channel si active. */
+ bool isActiveChannel(int index);
/** bind to the OSystem object => mixer will be
* invoked automatically when samples need