[Scummvm-cvs-logs] CVS: residual/mixer mixer.cpp,1.5,1.6 mixer.h,1.4,1.5
Pawel Kolodziejski
aquadran at users.sourceforge.net
Fri Dec 10 17:55:33 CET 2004
- Previous message: [Scummvm-cvs-logs] CVS: residual/mixer audiostream.cpp,1.3,1.4 audiostream.h,1.3,1.4 mixer.cpp,1.4,1.5
- Next message: [Scummvm-cvs-logs] CVS: residual sound.cpp,1.11,1.12 sound.h,1.8,1.9
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/scummvm/residual/mixer
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12064/mixer
Modified Files:
mixer.cpp mixer.h
Log Message:
synced mixer with main tree and adapt code
Index: mixer.cpp
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/mixer.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- mixer.cpp 10 Dec 2004 20:33:31 -0000 1.5
+++ mixer.cpp 10 Dec 2004 21:13:02 -0000 1.6
@@ -33,11 +33,13 @@
SoundMixer *_mixer;
PlayingSoundHandle *_handle;
bool _autofreeStream;
- const bool _isMusic;
+ bool _permanent;
byte _volume;
int8 _balance;
bool _paused;
int _id;
+ uint32 _samplesConsumed;
+ uint32 _samplesDecoded;
protected:
RateConverter *_converter;
@@ -46,17 +48,17 @@
public:
Channel(SoundMixer *mixer, PlayingSoundHandle *handle, bool isMusic, int id = -1);
- Channel(SoundMixer *mixer, PlayingSoundHandle *handle, AudioStream *input, bool autofreeStream, bool isMusic, bool reverseStereo = false, int id = -1);
+ Channel(SoundMixer *mixer, PlayingSoundHandle *handle, AudioStream *input, bool autofreeStream, bool isMusic, bool reverseStereo = false, int id = -1, bool permanent = false);
virtual ~Channel();
void mix(int16 *data, uint len);
+ bool isPermanent() const {
+ return _permanent;
+ }
bool isFinished() const {
return _input->endOfStream();
}
- bool isMusicChannel() const {
- return _isMusic;
- }
void pause(bool paused) {
_paused = paused;
}
@@ -72,20 +74,13 @@
int getId() const {
return _id;
}
+ uint32 getElapsedTime();
};
-class ChannelStream : public Channel {
-public:
- ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size);
- void append(void *sound, uint32 size);
-
- void finish();
-};
SoundMixer::SoundMixer() {
_mutex = createMutex();
- _premixParam = NULL;
- _premixProc = NULL;
+ _premixChannel = NULL;
_outputRate = 22050;
_globalVolume = 0;
_paused = false;
@@ -98,16 +93,23 @@
SoundMixer::~SoundMixer() {
SDL_CloseAudio();
- stopAll();
+ stopAll(true);
+
+ delete _premixChannel;
+ _premixChannel = NULL;
+
deleteMutex(_mutex);
}
+bool SoundMixer::isPaused() {
+ return _paused;
+}
+
bool SoundMixer::setSoundProc(SoundProc proc, void *param) {
SDL_AudioSpec desired;
memset(&desired, 0, sizeof(desired));
- /* only one format supported at the moment */
desired.freq = 22050;
desired.format = AUDIO_S16SYS;
desired.channels = 2;
@@ -123,76 +125,29 @@
return true;
}
-void SoundMixer::setupPremix(PremixProc *proc, void *param) {
- StackLock lock(_mutex);
- _premixParam = param;
- _premixProc = proc;
-}
-
-void SoundMixer::newStream(PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size, byte volume, int8 balance) {
- StackLock lock(_mutex);
-
- Channel *chan = new ChannelStream(this, handle, rate, flags, buffer_size);
- chan->setVolume(volume);
- chan->setBalance(balance);
- insertChannel(handle, chan);
-}
-
-void SoundMixer::appendStream(PlayingSoundHandle handle, void *sound, uint32 size) {
- StackLock lock(_mutex);
-
- if (!handle.isActive())
- return;
-
- int index = handle.getIndex();
-
- if ((index < 0) || (index >= NUM_CHANNELS)) {
- warning("soundMixer::appendStream has invalid index %d", index);
- return;
- }
-
- ChannelStream *chan;
- chan = dynamic_cast<ChannelStream *>(_channels[index]);
- if (!chan) {
- error("Trying to append to nonexistant stream : %d", index);
- } else {
- chan->append(sound, size);
- }
-}
-
-void SoundMixer::endStream(PlayingSoundHandle handle) {
+void SoundMixer::setupPremix(AudioStream *stream) {
StackLock lock(_mutex);
- // Simply ignore stop requests for handles of sounds that already terminated
- if (!handle.isActive())
- return;
-
- int index = handle.getIndex();
+ delete _premixChannel;
+ _premixChannel = NULL;
- if ((index < 0) || (index >= NUM_CHANNELS)) {
- warning("soundMixer::endStream has invalid index %d", index);
+ if (stream == NULL)
return;
- }
- ChannelStream *chan;
- chan = dynamic_cast<ChannelStream *>(_channels[index]);
- if (!chan) {
- error("Trying to end a nonexistant streamer : %d", index);
- } else {
- chan->finish();
- }
+ // Create the channel
+ _premixChannel = new Channel(this, NULL, stream, false, true);
}
void SoundMixer::insertChannel(PlayingSoundHandle *handle, Channel *chan) {
-
int index = -1;
+
for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] == 0) {
+ if (_channels[i] == NULL) {
index = i;
break;
}
}
- if(index == -1) {
+ if (index == -1) {
warning("SoundMixer::out of mixer slots");
delete chan;
return;
@@ -203,13 +158,14 @@
handle->setIndex(index);
}
-void SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id, byte volume, int8 balance, uint32 loopStart, uint32 loopEnd) {
+void SoundMixer::playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags,
+ int id, byte volume, int8 balance, uint32 loopStart, uint32 loopEnd) {
StackLock lock(_mutex);
// Prevent duplicate sounds
if (id != -1) {
for (int i = 0; i != NUM_CHANNELS; i++)
- if (_channels[i] != 0 && _channels[i]->getId() == id) {
+ if (_channels[i] != NULL && _channels[i]->getId() == id) {
if ((flags & SoundMixer::FLAG_AUTOFREE) != 0)
free(sound);
return;
@@ -236,18 +192,19 @@
insertChannel(handle, chan);
}
-void SoundMixer::playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic, byte volume, int8 balance, int id, bool autofreeStream) {
+void SoundMixer::playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic,
+ int id, byte volume, int8 balance, bool autofreeStream, bool permanent) {
StackLock lock(_mutex);
- if (input == 0) {
- warning("input stream is 0");
+ if (input == NULL) {
+ warning("input stream is NULL");
return;
}
// Prevent duplicate sounds
if (id != -1) {
for (int i = 0; i != NUM_CHANNELS; i++)
- if (_channels[i] != 0 && _channels[i]->getId() == id) {
+ if (_channels[i] != NULL && _channels[i]->getId() == id) {
if (autofreeStream)
delete input;
return;
@@ -255,7 +212,7 @@
}
// Create the channel
- Channel *chan = new Channel(this, handle, input, autofreeStream, isMusic, false, id);
+ Channel *chan = new Channel(this, handle, input, autofreeStream, isMusic, false, id, permanent);
chan->setVolume(volume);
chan->setBalance(balance);
insertChannel(handle, chan);
@@ -268,18 +225,19 @@
memset(buf, 0, 2 * len * sizeof(int16));
if (!_paused) {
- if (_premixProc)
- _premixProc(_premixParam, buf, len);
+ if (_premixChannel)
+ _premixChannel->mix(buf, len);
// now mix all channels
- for (int i = 0; i != NUM_CHANNELS; i++)
+ for (int i = 0; i != NUM_CHANNELS; i++) {
if (_channels[i]) {
if (_channels[i]->isFinished()) {
delete _channels[i];
- _channels[i] = 0;
+ _channels[i] = NULL;
} else if (!_channels[i]->isPaused())
_channels[i]->mix(buf, len);
}
+ }
}
}
@@ -291,21 +249,24 @@
((SoundMixer *)s)->mix((int16 *)samples, len >> 2);
}
-void SoundMixer::stopAll() {
+void SoundMixer::stopAll(bool force) {
StackLock lock(_mutex);
- for (int i = 0; i != NUM_CHANNELS; i++)
- if (_channels[i] != 0) {
- delete _channels[i];
- _channels[i] = 0;
+ for (int i = 0; i != NUM_CHANNELS; i++) {
+ if (_channels[i] != NULL) {
+ if (force || !_channels[i]->isPermanent()) {
+ delete _channels[i];
+ _channels[i] = NULL;
+ }
}
+ }
}
void SoundMixer::stopID(int id) {
StackLock lock(_mutex);
for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] != 0 && _channels[i]->getId() == id) {
+ if (_channels[i] != NULL && _channels[i]->getId() == id) {
delete _channels[i];
- _channels[i] = 0;
+ _channels[i] = NULL;
}
}
}
@@ -326,7 +287,7 @@
if (_channels[index]) {
delete _channels[index];
- _channels[index] = 0;
+ _channels[index] = NULL;
}
}
@@ -371,7 +332,7 @@
void SoundMixer::pauseID(int id, bool paused) {
StackLock lock(_mutex);
for (int i = 0; i != NUM_CHANNELS; i++) {
- if (_channels[i] != 0 && _channels[i]->getId() == id) {
+ if (_channels[i] != NULL && _channels[i]->getId() == id) {
_channels[i]->pause(paused);
return;
}
@@ -396,26 +357,37 @@
_channels[index]->pause(paused);
}
+bool SoundMixer::isSoundIDActive(int id) {
+ StackLock lock(_mutex);
+ for (int i = 0; i != NUM_CHANNELS; i++)
+ if (_channels[i] && _channels[i]->getId() == id)
+ return true;
+ return false;
+}
+
void SoundMixer::setVolume(int volume) {
// Check range
if (volume > 256)
volume = 256;
else if (volume < 0)
volume = 0;
-
+
_globalVolume = volume;
}
+
Channel::Channel(SoundMixer *mixer, PlayingSoundHandle *handle, bool isMusic, int id)
- : _mixer(mixer), _handle(handle), _autofreeStream(true), _isMusic(isMusic),
- _volume(255), _balance(0), _paused(false), _id(id), _converter(0), _input(0) {
+ : _mixer(mixer), _handle(handle), _autofreeStream(true),
+ _volume(255), _balance(0), _paused(false), _id(id), _samplesConsumed(0),
+ _samplesDecoded(0), _converter(0), _input(NULL) {
assert(mixer);
}
Channel::Channel(SoundMixer *mixer, PlayingSoundHandle *handle, AudioStream *input,
- bool autofreeStream, bool isMusic, bool reverseStereo, int id)
- : _mixer(mixer), _handle(handle), _autofreeStream(autofreeStream), _isMusic(isMusic),
- _volume(255), _balance(0), _paused(false), _id(id), _converter(0), _input(input) {
+ bool autofreeStream, bool isMusic, bool reverseStereo, int id, bool permanent)
+ : _mixer(mixer), _handle(handle), _autofreeStream(autofreeStream),
+ _volume(255), _balance(0), _paused(false), _id(id), _samplesConsumed(0),
+ _samplesDecoded(0), _converter(0), _input(input), _permanent(permanent) {
assert(mixer);
assert(input);
@@ -465,24 +437,10 @@
vol_r = vol / 255;
}
- _converter->flow(*_input, data, len, vol_l, vol_r);
- }
-}
-
-ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle,
- uint rate, byte flags, uint32 buffer_size)
- : Channel(mixer, handle, true) {
- // Create the input stream
- _input = makeAppendableAudioStream(rate, flags, buffer_size);
-
- // Get a rate converter instance
- _converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo(), (flags & SoundMixer::FLAG_REVERSE_STEREO) != 0);
-}
+ _samplesConsumed = _samplesDecoded;
-void ChannelStream::finish() {
- ((AppendableAudioStream *)_input)->finish();
-}
+ _converter->flow(*_input, data, len, vol_l, vol_r);
-void ChannelStream::append(void *data, uint32 len) {
- ((AppendableAudioStream *)_input)->append((const byte *)data, len);
+ _samplesDecoded += len;
+ }
}
Index: mixer.h
===================================================================
RCS file: /cvsroot/scummvm/residual/mixer/mixer.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- mixer.h 24 Feb 2004 08:20:45 -0000 1.4
+++ mixer.h 10 Dec 2004 21:13:03 -0000 1.5
@@ -37,103 +37,219 @@
bool isActive() const { return val > 0; }
};
-typedef void (*SoundProc)(void *param, byte *buf, int len);
-
class SoundMixer {
public:
- typedef void PremixProc (void *param, int16 *data, uint len);
-
enum {
- NUM_CHANNELS = 16
+ /** unsigned samples (default: signed) */
+ FLAG_UNSIGNED = 1 << 0,
+
+ /** sound is 16 bits wide (default: 8bit) */
+ FLAG_16BITS = 1 << 1,
+
+ /** sample is little endian (default: big endian) */
+ FLAG_LITTLE_ENDIAN = 1 << 2,
+
+ /** sound is in stereo (default: mono) */
+ FLAG_STEREO = 1 << 3,
+
+ /** reverse the left and right stereo channel */
+ FLAG_REVERSE_STEREO = 1 << 4,
+
+ /** sound buffer is freed automagically at the end of playing */
+ FLAG_AUTOFREE = 1 << 5,
+
+ /** loop the audio */
+ FLAG_LOOP = 1 << 6
};
+private:
enum {
- FLAG_UNSIGNED = 1 << 0, /** unsigned samples (default: signed) */
- FLAG_16BITS = 1 << 1, /** sound is 16 bits wide (default: 8bit) */
- FLAG_LITTLE_ENDIAN = 1 << 2, /** sample is little endian (default: big endian) */
- FLAG_STEREO = 1 << 3, /** sound is in stereo (default: mono) */
- FLAG_REVERSE_STEREO = 1 << 4, /** reverse the left and right stereo channel */
- FLAG_AUTOFREE = 1 << 5, /** sound buffer is freed automagically at the end of playing */
- FLAG_LOOP = 1 << 6 /** loop the audio */
+ NUM_CHANNELS = 16
};
-private:
MutexRef _mutex;
- void *_premixParam;
- PremixProc *_premixProc;
+ Channel *_premixChannel;
uint _outputRate;
+
int _globalVolume;
- bool _paused;
- bool _mixerReady;
+ bool _paused;
+
Channel *_channels[NUM_CHANNELS];
+ bool _mixerReady;
+
public:
SoundMixer();
~SoundMixer();
+
+
+ /**
+ * Is the mixer ready and setup? This may not be the case on systems which
+ * don't support digital sound output. In that case, the mixer proc may
+ * never be called. That in turn can cause breakage in games which use the
+ * premix callback for syncing. In particular, the Adlib MIDI emulation...
+ *
+ * @return whether the mixer is ready and setup
+ */
bool isReady() const { return _mixerReady; };
- void setupPremix(PremixProc *proc, void *param);
- // start playing a raw sound
- void playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags,
- int id = -1, byte volume = 255, int8 balance = 0, uint32 loopStart = 0, uint32 loopEnd = 0);
- void playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic, byte volume = 255, int8 balance = 0, int id = -1, bool autofreeStream = true);
+ /**
+ * Set the premix stream. This is mainly used for the adlib music, but
+ * is not limited to it. The premix stream is invoked by the mixer whenever
+ * it needs to generate any data, before any other mixing takes place.
+ */
+ void setupPremix(AudioStream *stream);
- /** Start a new stream. */
- void newStream(PlayingSoundHandle *handle, uint rate, byte flags, uint32 buffer_size, byte volume = 255, int8 balance = 0);
- /** Append to an existing stream. */
- void appendStream(PlayingSoundHandle handle, void *sound, uint32 size);
- /** Mark a stream as finished - it will play all its remaining data, then stop. */
- void endStream(PlayingSoundHandle handle);
+ /**
+ * Start playing the given raw sound data.
+ * Internally, this simply creates an audio input stream wrapping the data
+ * (using the makeLinearInputStream factory function), which is then
+ * passed on to playInputStream.
+ */
+ void playRaw(PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags,
+ int id = -1, byte volume = 255, int8 balance = 0,
+ uint32 loopStart = 0, uint32 loopEnd = 0);
- /** stop all currently playing sounds */
- void stopAll();
+ /**
+ * Start playing the given audio input stream.
+ */
+ void playInputStream(PlayingSoundHandle *handle, AudioStream *input, bool isMusic,
+ int id = -1, byte volume = 255, int8 balance = 0,
+ bool autofreeStream = true, bool permanent = false);
- /** stop playing the sound with given ID */
+
+
+ /**
+ * Stop all currently playing sounds.
+ */
+ void stopAll(bool force = false);
+
+ /**
+ * Stop playing the sound with given ID.
+ *
+ * @param id the ID of the sound to affect
+ */
void stopID(int id);
- /** stop playing the channel for the given handle */
+ /**
+ * Stop playing the sound corresponding to the given handle.
+ *
+ * @param handle the sound to affect
+ */
void stopHandle(PlayingSoundHandle handle);
- /** pause/unpause all channels */
+
+
+ /**
+ * Pause/unpause the mixer (this temporarily stops all audio processing,
+ * including all regular channels and the premix channel).
+ *
+ * @param paused true to pause the mixer, false to unpause it
+ */
void pauseAll(bool paused);
- /** pause/unpause the sound with the given ID */
+ /**
+ * Pause/unpause the sound with the given ID.
+ *
+ * @param id the ID of the sound to affect
+ * @param paused true to pause the sound, false to unpause it
+ */
void pauseID(int id, bool paused);
- /** pause/unpause the channel for the given handle */
+ /**
+ * Pause/unpause the sound corresponding to the given handle.
+ *
+ * @param handle the sound to affect
+ * @param paused true to pause the sound, false to unpause it
+ */
void pauseHandle(PlayingSoundHandle handle, bool paused);
- /** set the channel volume for the given handle (0 - 255) */
+
+
+ /**
+ * Check if a sound with the given ID is active.
+ *
+ * @param id the ID of the sound to query
+ * @return true if the sound is active
+ */
+ bool isSoundIDActive(int id);
+
+ /**
+ * Check if the mixer is paused (using pauseAll).
+ *
+ * @return true if the mixer is paused
+ */
+ bool isPaused();
+
+
+
+ /**
+ * Set the channel volume for the given handle.
+ *
+ * @param handle the sound to affect
+ * @param volume the new channel volume (0 - 255)
+ */
void setChannelVolume(PlayingSoundHandle handle, byte volume);
- /** set the channel balance for the given handle (-127 ... 0 ... 127) (left ... center ... right)*/
+ /**
+ * Set the channel balance for the given handle.
+ *
+ * @param handle the sound to affect
+ * @param balance the new channel balance:
+ * (-127 ... 0 ... 127) corresponds to (left ... center ... right)
+ */
void setChannelBalance(PlayingSoundHandle handle, int8 balance);
- /** set the global volume, 0-256 */
+ /**
+ * Get approximation of for how long the channel has been playing.
+ */
+ uint32 getSoundElapsedTime(PlayingSoundHandle handle);
+
+ /**
+ * Set the global volume.
+ *
+ * @param volume the new global volume, 0-256
+ */
void setVolume(int volume);
- /** query the global volume, 0-256 */
+ /**
+ * Query the global volume.
+ *
+ * @return the global music volume, 0-256
+ */
int getVolume() const { return _globalVolume; }
- /** query the output rate in kHz */
+ /**
+ * Query the system's audio output sample rate. This returns
+ * the same value as OSystem::getOutputSampleRate().
+ *
+ * @return the output sample rate in Hz
+ */
uint getOutputRate() const { return _outputRate; }
private:
+ typedef void (*SoundProc)(void *param, byte *buf, int len);
bool setSoundProc(SoundProc proc, void *param);
void insertChannel(PlayingSoundHandle *handle, Channel *chan);
- /** main mixer method */
+ /**
+ * Internal main method -- all the actual mixing work is done from here.
+ */
void mix(int16 * buf, uint len);
+ /**
+ * The mixer callback function, passed on to OSystem::setSoundCallback().
+ * This simply calls the mix() method.
+ */
static void mixCallback(void *s, byte *samples, int len);
};
- Previous message: [Scummvm-cvs-logs] CVS: residual/mixer audiostream.cpp,1.3,1.4 audiostream.h,1.3,1.4 mixer.cpp,1.4,1.5
- Next message: [Scummvm-cvs-logs] CVS: residual sound.cpp,1.11,1.12 sound.h,1.8,1.9
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Scummvm-git-logs
mailing list