aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Schickel2010-01-05 19:51:48 +0000
committerJohannes Schickel2010-01-05 19:51:48 +0000
commit63bccc213becabbfbaa56969b85601d3468f3ccf (patch)
treea162c9e3dd3ab20cf367ef3657cf89167cb96021
parentc4106653a8e6c618a96d593a837993fdc45444b0 (diff)
downloadscummvm-rg350-63bccc213becabbfbaa56969b85601d3468f3ccf.tar.gz
scummvm-rg350-63bccc213becabbfbaa56969b85601d3468f3ccf.tar.bz2
scummvm-rg350-63bccc213becabbfbaa56969b85601d3468f3ccf.zip
Create a generic Channel interface for the default Mixer implementation.
svn-id: r47031
-rw-r--r--sound/mixer.cpp169
1 files changed, 91 insertions, 78 deletions
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index 933b86e4a9..29a3b3c28c 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -44,68 +44,61 @@ namespace Audio {
*/
class Channel {
public:
- const Mixer::SoundType _type;
+ Channel(Mixer *mixer, Mixer::SoundType type, int id, bool permanent);
+ virtual ~Channel() {}
+
+ virtual void mix(int16 *data, uint len) = 0;
+
+ virtual bool isFinished() const = 0;
+
+ bool isPermanent() const { return _permanent; }
+
+ int getId() const { return _id; }
+
+ void pause(bool paused);
+ bool isPaused() const { return (_pauseLevel != 0); }
+
+ void setVolume(const byte volume) { _volume = volume; }
+ void setBalance(const int8 balance) { _balance = balance; }
+
+ uint32 getElapsedTime();
+
+public:
+ const Mixer::SoundType _type;
SoundHandle _handle;
+
private:
- Mixer *_mixer;
- bool _autofreeStream;
bool _permanent;
- byte _volume;
- int8 _balance;
int _pauseLevel;
int _id;
+
+protected:
+ Mixer *_mixer;
+ byte _volume;
+ int8 _balance;
+
uint32 _samplesConsumed;
uint32 _samplesDecoded;
uint32 _mixerTimeStamp;
uint32 _pauseStartTime;
uint32 _pauseTime;
+};
-protected:
+class SimpleChannel : public Channel {
+private:
+ bool _autofreeStream;
RateConverter *_converter;
AudioStream *_input;
public:
- Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *input, bool autofreeStream, bool reverseStereo = false, int id = -1, bool permanent = false);
- virtual ~Channel();
+ SimpleChannel(Mixer *mixer, Mixer::SoundType type, AudioStream *input, bool autofreeStream, bool reverseStereo = false, int id = -1, bool permanent = false);
+ ~SimpleChannel();
void mix(int16 *data, uint len);
- bool isPermanent() const {
- return _permanent;
- }
bool isFinished() const {
return _input->endOfStream();
}
- void pause(bool paused) {
- //assert((paused && _pauseLevel >= 0) || (!paused && _pauseLevel));
-
- if (paused) {
- _pauseLevel++;
-
- if (_pauseLevel == 1)
- _pauseStartTime = g_system->getMillis();
- } else if (_pauseLevel > 0) {
- _pauseLevel--;
-
- if (!_pauseLevel) {
- _pauseTime = (g_system->getMillis() - _pauseStartTime);
- _pauseStartTime = 0;
- }
- }
- }
- bool isPaused() {
- return _pauseLevel != 0;
- }
- void setVolume(const byte volume) {
- _volume = volume;
- }
- void setBalance(const int8 balance) {
- _balance = balance;
- }
- int getId() const {
- return _id;
- }
- uint32 getElapsedTime();
};
@@ -146,7 +139,6 @@ void MixerImpl::setOutputRate(uint sampleRate) {
}
void MixerImpl::insertChannel(SoundHandle *handle, Channel *chan) {
-
int index = -1;
for (int i = 0; i != NUM_CHANNELS; i++) {
if (_channels[i] == 0) {
@@ -209,7 +201,7 @@ void MixerImpl::playInputStream(
}
// Create the channel
- Channel *chan = new Channel(this, type, input, autofreeStream, reverseStereo, id, permanent);
+ SimpleChannel *chan = new SimpleChannel(this, type, input, autofreeStream, reverseStereo, id, permanent);
chan->setVolume(volume);
chan->setBalance(balance);
insertChannel(handle, chan);
@@ -388,13 +380,62 @@ int MixerImpl::getVolumeForSoundType(SoundType type) const {
#pragma mark --- Channel implementations ---
#pragma mark -
+Channel::Channel(Mixer *mixer, Mixer::SoundType type, int id, bool permanent)
+ : _type(type), _mixer(mixer), _id(id), _permanent(permanent), _volume(Mixer::kMaxChannelVolume),
+ _balance(0), _pauseLevel(0), _samplesConsumed(0), _samplesDecoded(0), _mixerTimeStamp(0),
+ _pauseStartTime(0), _pauseTime(0) {
+}
+
+void Channel::pause(bool paused) {
+ //assert((paused && _pauseLevel >= 0) || (!paused && _pauseLevel));
+
+ if (paused) {
+ _pauseLevel++;
+
+ if (_pauseLevel == 1)
+ _pauseStartTime = g_system->getMillis();
+ } else if (_pauseLevel > 0) {
+ _pauseLevel--;
+
+ if (!_pauseLevel) {
+ _pauseTime = (g_system->getMillis() - _pauseStartTime);
+ _pauseStartTime = 0;
+ }
+ }
+}
+
+uint32 Channel::getElapsedTime() {
+ if (_mixerTimeStamp == 0)
+ return 0;
+
+ const uint32 rate = _mixer->getOutputRate();
+ uint32 delta = 0;
+
+ if (isPaused())
+ delta = _pauseStartTime - _mixerTimeStamp;
+ else
+ delta = g_system->getMillis() - _mixerTimeStamp - _pauseTime;
+
+ // Convert the number of samples into a time duration.
+
+ Audio::Timestamp ts(0, rate);
+
+ ts = ts.addFrames(_samplesConsumed);
+ ts = ts.addMsecs(delta);
+
+ // In theory it would seem like a good idea to limit the approximation
+ // so that it never exceeds the theoretical upper bound set by
+ // _samplesDecoded. Meanwhile, back in the real world, doing so makes
+ // the Broken Sword cutscenes noticeably jerkier. I guess the mixer
+ // isn't invoked at the regular intervals that I first imagined.
-Channel::Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *input,
+ return ts.msecs();
+}
+
+SimpleChannel::SimpleChannel(Mixer *mixer, Mixer::SoundType type, AudioStream *input,
bool autofreeStream, bool reverseStereo, int id, bool permanent)
- : _type(type), _mixer(mixer), _autofreeStream(autofreeStream),
- _volume(Mixer::kMaxChannelVolume), _balance(0), _pauseLevel(0), _id(id), _samplesConsumed(0),
- _samplesDecoded(0), _mixerTimeStamp(0), _pauseStartTime(0), _pauseTime(0), _converter(0),
- _input(input), _permanent(permanent) {
+ : Channel(mixer, type, id, permanent), _autofreeStream(autofreeStream), _converter(0),
+ _input(input) {
assert(mixer);
assert(input);
@@ -402,7 +443,7 @@ Channel::Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *input,
_converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo(), reverseStereo);
}
-Channel::~Channel() {
+SimpleChannel::~SimpleChannel() {
delete _converter;
if (_autofreeStream)
delete _input;
@@ -412,7 +453,7 @@ Channel::~Channel() {
10 means that the buffer contains twice 10 sample, each
16 bits, for a total of 40 bytes.
*/
-void Channel::mix(int16 *data, uint len) {
+void SimpleChannel::mix(int16 *data, uint len) {
assert(_input);
if (_input->endOfData()) {
@@ -449,33 +490,5 @@ void Channel::mix(int16 *data, uint len) {
}
}
-uint32 Channel::getElapsedTime() {
- if (_mixerTimeStamp == 0)
- return 0;
-
- const uint32 rate = _mixer->getOutputRate();
- uint32 delta = 0;
-
- if (isPaused())
- delta = _pauseStartTime - _mixerTimeStamp;
- else
- delta = g_system->getMillis() - _mixerTimeStamp - _pauseTime;
-
- // Convert the number of samples into a time duration.
-
- Audio::Timestamp ts(0, rate);
-
- ts = ts.addFrames(_samplesConsumed);
- ts = ts.addMsecs(delta);
-
- // In theory it would seem like a good idea to limit the approximation
- // so that it never exceeds the theoretical upper bound set by
- // _samplesDecoded. Meanwhile, back in the real world, doing so makes
- // the Broken Sword cutscenes noticeably jerkier. I guess the mixer
- // isn't invoked at the regular intervals that I first imagined.
-
- return ts.msecs();
-}
-
} // End of namespace Audio