mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-04 08:17:40 +00:00
Patch ##1956946 (Audio::Mixer internal API revision) with some tweaks
svn-id: r32828
This commit is contained in:
parent
e68efca5a1
commit
c45d632f3b
@ -37,7 +37,7 @@
|
||||
#include <SDL_gp2x.h>
|
||||
|
||||
namespace Audio {
|
||||
class Mixer;
|
||||
class MixerImpl;
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
@ -367,7 +367,7 @@ protected:
|
||||
Common::SaveFileManager *_savefile;
|
||||
FilesystemFactory *getFilesystemFactory();
|
||||
|
||||
Audio::Mixer *_mixer;
|
||||
Audio::MixerImpl *_mixer;
|
||||
|
||||
SDL_TimerID _timerID;
|
||||
Common::TimerManager *_timer;
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
#include "backends/plugins/posix/posix-provider.h"
|
||||
#include "backends/fs/posix/posix-fs-factory.h" // for getFilesystemFactory()
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/mixer_intern.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -225,8 +225,7 @@ void OSystem_GP2X::initBackend() {
|
||||
// Create and hook up the mixer, if none exists yet (we check for this to
|
||||
// allow subclasses to provide their own).
|
||||
if (_mixer == 0) {
|
||||
_mixer = new Audio::Mixer();
|
||||
setSoundCallback(Audio::Mixer::mixCallback, _mixer);
|
||||
setupMixer();
|
||||
}
|
||||
|
||||
// Create and hook up the timer manager, if none exists yet (we check for
|
||||
@ -445,7 +444,7 @@ void OSystem_GP2X::deleteMutex(MutexRef mutex) {
|
||||
#pragma mark --- Audio ---
|
||||
#pragma mark -
|
||||
|
||||
bool OSystem_GP2X::setSoundCallback(SoundProc proc, void *param) {
|
||||
void OSystem_GP2X::setupMixer() {
|
||||
SDL_AudioSpec desired;
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/scaler.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/mixer_intern.h"
|
||||
|
||||
#include <pspgu.h>
|
||||
|
||||
@ -99,7 +99,7 @@ OSystem_PSP::~OSystem_PSP() {
|
||||
|
||||
void OSystem_PSP::initBackend() {
|
||||
_savefile = new DefaultSaveFileManager();
|
||||
_mixer = new Audio::Mixer();
|
||||
_mixer = new Audio::MixerImpl(this);
|
||||
_timer = new DefaultTimerManager();
|
||||
setSoundCallback(Audio::Mixer::mixCallback, _mixer);
|
||||
setTimerCallback(&timer_handler, 10);
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#include "backends/saves/default/default-saves.h"
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/mixer_intern.h"
|
||||
|
||||
#include "icons/scummvm.xpm"
|
||||
|
||||
@ -131,9 +131,7 @@ void OSystem_SDL::initBackend() {
|
||||
// Create and hook up the mixer, if none exists yet (we check for this to
|
||||
// allow subclasses to provide their own).
|
||||
if (_mixer == 0) {
|
||||
_mixer = new Audio::Mixer();
|
||||
bool result = setSoundCallback(Audio::Mixer::mixCallback, _mixer);
|
||||
_mixer->setReady(result);
|
||||
setupMixer();
|
||||
}
|
||||
|
||||
// Create and hook up the timer manager, if none exists yet (we check for
|
||||
@ -391,7 +389,15 @@ void OSystem_SDL::deleteMutex(MutexRef mutex) {
|
||||
#pragma mark --- Audio ---
|
||||
#pragma mark -
|
||||
|
||||
bool OSystem_SDL::setSoundCallback(SoundProc proc, void *param) {
|
||||
void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) {
|
||||
OSystem_SDL *this_ = (OSystem_SDL *)sys;
|
||||
assert(this_);
|
||||
|
||||
if (this_->_mixer)
|
||||
this_->_mixer->mixCallback(samples, len);
|
||||
}
|
||||
|
||||
void OSystem_SDL::setupMixer() {
|
||||
SDL_AudioSpec desired;
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
@ -415,23 +421,30 @@ bool OSystem_SDL::setSoundCallback(SoundProc proc, void *param) {
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = (uint16)samples;
|
||||
desired.callback = proc;
|
||||
desired.userdata = param;
|
||||
desired.callback = mixCallback;
|
||||
desired.userdata = this;
|
||||
|
||||
// Create the mixer instance
|
||||
assert(!_mixer);
|
||||
_mixer = new Audio::MixerImpl(this);
|
||||
assert(_mixer);
|
||||
|
||||
if (SDL_OpenAudio(&desired, &obtained) != 0) {
|
||||
warning("Could not open audio device: %s", SDL_GetError());
|
||||
return false;
|
||||
_samplesPerSec = 0;
|
||||
_mixer->setReady(false);
|
||||
} else {
|
||||
// Note: This should be the obtained output rate, but it seems that at
|
||||
// least on some platforms SDL will lie and claim it did get the rate
|
||||
// even if it didn't. Probably only happens for "weird" rates, though.
|
||||
_samplesPerSec = obtained.freq;
|
||||
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
|
||||
|
||||
// Tell the mixer that we are ready and start the sound processing
|
||||
_mixer->setOutputRate(_samplesPerSec);
|
||||
_mixer->setReady(true);
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
// Note: This should be the obtained output rate, but it seems that at
|
||||
// least on some platforms SDL will lie and claim it did get the rate
|
||||
// even if it didn't. Probably only happens for "weird" rates, though.
|
||||
_samplesPerSec = obtained.freq;
|
||||
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
|
||||
SDL_PauseAudio(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
int OSystem_SDL::getOutputSampleRate() const {
|
||||
return _samplesPerSec;
|
||||
}
|
||||
|
||||
Audio::Mixer *OSystem_SDL::getMixer() {
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
|
||||
namespace Audio {
|
||||
class Mixer;
|
||||
class MixerImpl;
|
||||
}
|
||||
|
||||
namespace Common {
|
||||
@ -134,8 +134,9 @@ public:
|
||||
virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
|
||||
|
||||
// Set function that generates samples
|
||||
typedef void (*SoundProc)(void *param, byte *buf, int len);
|
||||
virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend
|
||||
virtual void setupMixer();
|
||||
static void mixCallback(void *s, byte *samples, int len);
|
||||
|
||||
virtual Audio::Mixer *getMixer();
|
||||
|
||||
// Poll CD status
|
||||
@ -186,7 +187,6 @@ public:
|
||||
|
||||
virtual void setWindowCaption(const char *caption);
|
||||
virtual bool openCD(int drive);
|
||||
virtual int getOutputSampleRate() const;
|
||||
|
||||
virtual bool hasFeature(Feature f);
|
||||
virtual void setFeatureState(Feature f, bool enable);
|
||||
@ -371,7 +371,7 @@ protected:
|
||||
|
||||
|
||||
Common::SaveFileManager *_savefile;
|
||||
Audio::Mixer *_mixer;
|
||||
Audio::MixerImpl *_mixer;
|
||||
|
||||
SDL_TimerID _timerID;
|
||||
Common::TimerManager *_timer;
|
||||
|
@ -173,11 +173,8 @@ void OSystem_SDL_Symbian::quit() {
|
||||
OSystem_SDL::quit();
|
||||
}
|
||||
|
||||
bool OSystem_SDL_Symbian::setSoundCallback(SoundProc proc, void *param) {
|
||||
void OSystem_SDL_Symbian::setupMixer() {
|
||||
|
||||
// First save the proc and param
|
||||
_sound_proc_param = param;
|
||||
_sound_proc = proc;
|
||||
SDL_AudioSpec desired;
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
@ -207,48 +204,53 @@ bool OSystem_SDL_Symbian::setSoundCallback(SoundProc proc, void *param) {
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = (uint16)samples;
|
||||
#ifdef S60
|
||||
desired.callback = symbianMixCallback;
|
||||
desired.userdata = this;
|
||||
#else
|
||||
desired.callback = proc;
|
||||
desired.userdata = param;
|
||||
#endif
|
||||
|
||||
// Create the mixer instance
|
||||
assert(!_mixer);
|
||||
_mixer = new Audio::MixerImpl(this);
|
||||
assert(_mixer);
|
||||
|
||||
if (SDL_OpenAudio(&desired, &obtained) != 0) {
|
||||
warning("Could not open audio device: %s", SDL_GetError());
|
||||
return false;
|
||||
_samplesPerSec = 0;
|
||||
_mixer->setReady(false);
|
||||
} else {
|
||||
// Note: This should be the obtained output rate, but it seems that at
|
||||
// least on some platforms SDL will lie and claim it did get the rate
|
||||
// even if it didn't. Probably only happens for "weird" rates, though.
|
||||
_samplesPerSec = obtained.freq;
|
||||
_channels = obtained.channels;
|
||||
|
||||
// Need to create mixbuffer for stereo mix to downmix
|
||||
if (_channels != 2) {
|
||||
_stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values
|
||||
}
|
||||
|
||||
// Tell the mixer that we are ready and start the sound processing
|
||||
_mixer->setOutputRate(_samplesPerSec);
|
||||
_mixer->setReady(true);
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
// Note: This should be the obtained output rate, but it seems that at
|
||||
// least on some platforms SDL will lie and claim it did get the rate
|
||||
// even if it didn't. Probably only happens for "weird" rates, though.
|
||||
_samplesPerSec = obtained.freq;
|
||||
_channels = obtained.channels;
|
||||
|
||||
// Need to create mixbuffer for stereo mix to downmix
|
||||
if (_channels != 2) {
|
||||
_stereo_mix_buffer = new byte [obtained.size*2];//*2 for stereo values
|
||||
}
|
||||
|
||||
SDL_PauseAudio(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The mixer callback function, passed on to OSystem::setSoundCallback().
|
||||
* This simply calls the mix() method.
|
||||
*/
|
||||
void OSystem_SDL_Symbian::symbianMixCallback(void *s, byte *samples, int len) {
|
||||
static_cast <OSystem_SDL_Symbian*>(s)->symbianMix(samples,len);
|
||||
}
|
||||
void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len) {
|
||||
OSystem_SDL_Symbian *this_ = (OSystem_SDL_Symbian *)sys;
|
||||
assert(this_);
|
||||
|
||||
if (!this_->_mixer)
|
||||
return;
|
||||
|
||||
/**
|
||||
* Actual mixing implementation
|
||||
*/
|
||||
void OSystem_SDL_Symbian::symbianMix(byte *samples, int len) {
|
||||
#ifdef S60
|
||||
// If not stereo then we need to downmix
|
||||
if (_channels != 2) {
|
||||
_sound_proc(_sound_proc_param, _stereo_mix_buffer, len * 2);
|
||||
this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2);
|
||||
|
||||
int16 *bitmixDst = (int16 *)samples;
|
||||
int16 *bitmixSrc = (int16 *)_stereo_mix_buffer;
|
||||
|
||||
@ -258,9 +260,12 @@ void OSystem_SDL_Symbian::symbianMix(byte *samples, int len) {
|
||||
bitmixSrc += 2;
|
||||
}
|
||||
} else
|
||||
_sound_proc(_sound_proc_param, samples, len);
|
||||
#else
|
||||
this_->_mixer->mixCallback(samples, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is an implementation by the remapKey function
|
||||
* @param SDL_Event to remap
|
||||
|
@ -58,7 +58,7 @@ public:
|
||||
// This function is overridden by the symbian port in order to provide MONO audio
|
||||
// downmix is done by supplying our own audiocallback
|
||||
//
|
||||
virtual bool setSoundCallback(SoundProc proc, void *param); // overloaded by CE backend
|
||||
virtual void setupMixer(); // overloaded by CE backend
|
||||
|
||||
// Overloaded from SDL_Commmon
|
||||
void quit();
|
||||
@ -70,11 +70,6 @@ protected:
|
||||
//
|
||||
static void symbianMixCallback(void *s, byte *samples, int len);
|
||||
|
||||
//
|
||||
// Actual mixing implementation
|
||||
//
|
||||
void symbianMix(byte *samples, int len);
|
||||
|
||||
virtual FilesystemFactory *getFilesystemFactory();
|
||||
public:
|
||||
// vibration support
|
||||
@ -121,8 +116,6 @@ protected:
|
||||
// Audio
|
||||
int _channels;
|
||||
|
||||
SoundProc _sound_proc;
|
||||
void *_sound_proc_param;
|
||||
byte *_stereo_mix_buffer;
|
||||
|
||||
// Used to handle joystick navi zones
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "base/main.h"
|
||||
#include "base/plugins.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/mixer_intern.h"
|
||||
#include "sound/fmopl.h"
|
||||
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
@ -404,7 +404,7 @@ void OSystem_WINCE3::initBackend()
|
||||
// Instantiate our own sound mixer
|
||||
// mixer init is postponed until a game engine is selected.
|
||||
if (_mixer == 0) {
|
||||
_mixer = new Audio::Mixer();
|
||||
_mixer = new Audio::Mixer(this);
|
||||
}
|
||||
|
||||
// Create the timer. CE SDL does not support multiple timers (SDL_AddTimer).
|
||||
@ -770,7 +770,7 @@ void OSystem_WINCE3::create_toolbar() {
|
||||
_toolbarHandler.setVisible(false);
|
||||
}
|
||||
|
||||
bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {
|
||||
void OSystem_WINCE3::setupMixer(SoundProc proc, void *param) {
|
||||
SDL_AudioSpec desired;
|
||||
int thread_priority;
|
||||
|
||||
@ -785,12 +785,16 @@ bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {
|
||||
desired.channels = 2;
|
||||
desired.samples = 128;
|
||||
desired.callback = private_sound_proc;
|
||||
desired.userdata = param;
|
||||
desired.userdata = this;
|
||||
|
||||
// Create the mixer instance
|
||||
assert(!_mixer);
|
||||
_mixer = new Audio::MixerImpl(this);
|
||||
assert(_mixer);
|
||||
|
||||
// Add sound thread priority
|
||||
if (!ConfMan.hasKey("sound_thread_priority")) {
|
||||
if (!ConfMan.hasKey("sound_thread_priority"))
|
||||
thread_priority = THREAD_PRIORITY_NORMAL;
|
||||
}
|
||||
else
|
||||
thread_priority = ConfMan.getInt("sound_thread_priority");
|
||||
|
||||
@ -799,16 +803,24 @@ bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) {
|
||||
SDL_CloseAudio();
|
||||
if (SDL_OpenAudio(&desired, NULL) != 0) {
|
||||
warning("Could not open audio device: %s", SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
_mixer->setReady(false);
|
||||
|
||||
} else {
|
||||
debug(1, "Sound opened OK, mixing at %d Hz", _sampleRate);
|
||||
SDL_PauseAudio(0);
|
||||
return true;
|
||||
|
||||
// Tell the mixer that we are ready and start the sound processing
|
||||
_mixer->setOutputRate(_sampleRate);
|
||||
_mixer->setReady(true);
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_WINCE3::private_sound_proc(void *param, byte *buf, int len) {
|
||||
(*_originalSoundProc)(param, buf, len);
|
||||
OSystem_WINCE3 *this_ = (OSystem_WINCE3 *)param;
|
||||
assert(this_);
|
||||
|
||||
if (this_->_mixer)
|
||||
this_->_mixer->mixCallback(buf, len);
|
||||
if (!_soundMaster)
|
||||
memset(buf, 0, len);
|
||||
}
|
||||
@ -838,7 +850,7 @@ bool OSystem_WINCE3::checkOggHighSampleRate() {
|
||||
}
|
||||
#endif
|
||||
|
||||
void OSystem_WINCE3::get_sample_rate() {
|
||||
void OSystem_WINCE3::compute_sample_rate() {
|
||||
// Force at least medium quality FM synthesis for FOTAQ
|
||||
Common::String gameid(ConfMan.get("gameid"));
|
||||
if (gameid == "queen") {
|
||||
@ -875,9 +887,8 @@ void OSystem_WINCE3::setWindowCaption(const char *caption) {
|
||||
|
||||
//update_game_settings();
|
||||
// finalize mixer init
|
||||
get_sample_rate();
|
||||
bool result = setSoundCallback(Audio::Mixer::mixCallback, _mixer);
|
||||
_mixer->setReady(result);
|
||||
compute_sample_rate();
|
||||
setupMixer();
|
||||
|
||||
// handle the actual event
|
||||
OSystem_SDL::setWindowCaption(caption);
|
||||
@ -1050,7 +1061,7 @@ void OSystem_WINCE3::update_game_settings() {
|
||||
}
|
||||
}
|
||||
|
||||
get_sample_rate();
|
||||
compute_sample_rate();
|
||||
}
|
||||
|
||||
void OSystem_WINCE3::initSize(uint w, uint h) {
|
||||
|
@ -82,7 +82,7 @@ public:
|
||||
// Overloaded from SDL_Commmon
|
||||
void quit();
|
||||
// Overloaded from SDL_Commmon (master volume and sample rate subtleties)
|
||||
bool setSoundCallback(SoundProc proc, void *param);
|
||||
void setupMixer();
|
||||
// Overloaded from OSystem
|
||||
//void engineInit();
|
||||
void getTimeAndDate(struct tm &t) const;
|
||||
@ -160,13 +160,12 @@ private:
|
||||
#endif
|
||||
|
||||
static void private_sound_proc(void *param, byte *buf, int len);
|
||||
static SoundProc _originalSoundProc;
|
||||
|
||||
bool update_scalers();
|
||||
void create_toolbar();
|
||||
void update_game_settings();
|
||||
void check_mappings();
|
||||
void get_sample_rate();
|
||||
void compute_sample_rate();
|
||||
|
||||
void retrieve_mouse_location(int &x, int &y);
|
||||
|
||||
|
@ -814,15 +814,6 @@ public:
|
||||
*/
|
||||
virtual Audio::Mixer *getMixer() = 0;
|
||||
|
||||
/**
|
||||
* Determine the output sample rate. Audio data provided by the sound
|
||||
* callback will be played using this rate.
|
||||
* @note Client code other than the sound mixer should _not_ use this
|
||||
* method. Instead, call Mixer::getOutputRate()!
|
||||
* @return the output sample rate
|
||||
*/
|
||||
virtual int getOutputSampleRate() const = 0;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "common/util.h"
|
||||
#include "common/system.h"
|
||||
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/mixer_intern.h"
|
||||
#include "sound/rate.h"
|
||||
#include "sound/audiostream.h"
|
||||
|
||||
@ -103,32 +103,38 @@ public:
|
||||
#pragma mark -
|
||||
|
||||
|
||||
Mixer::Mixer() {
|
||||
_syst = g_system;
|
||||
MixerImpl::MixerImpl(OSystem *system)
|
||||
: _syst(system), _sampleRate(0), _mixerReady(false), _handleSeed(0) {
|
||||
|
||||
_handleSeed = 0;
|
||||
|
||||
int i = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAYSIZE(_volumeForSoundType); i++)
|
||||
_volumeForSoundType[i] = kMaxMixerVolume;
|
||||
|
||||
for (i = 0; i != NUM_CHANNELS; i++)
|
||||
_channels[i] = 0;
|
||||
|
||||
_mixerReady = false;
|
||||
}
|
||||
|
||||
Mixer::~Mixer() {
|
||||
MixerImpl::~MixerImpl() {
|
||||
for (int i = 0; i != NUM_CHANNELS; i++)
|
||||
delete _channels[i];
|
||||
}
|
||||
|
||||
uint Mixer::getOutputRate() const {
|
||||
return (uint)_syst->getOutputSampleRate();
|
||||
void MixerImpl::setReady(bool ready) {
|
||||
_mixerReady = ready;
|
||||
}
|
||||
|
||||
void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {
|
||||
uint MixerImpl::getOutputRate() const {
|
||||
return _sampleRate;
|
||||
}
|
||||
|
||||
void MixerImpl::setOutputRate(uint sampleRate) {
|
||||
if (_sampleRate != 0 && _sampleRate != sampleRate)
|
||||
error("Changing the Audio::Mixer output sample rate is not supported");
|
||||
_sampleRate = sampleRate;
|
||||
}
|
||||
|
||||
void MixerImpl::insertChannel(SoundHandle *handle, Channel *chan) {
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i != NUM_CHANNELS; i++) {
|
||||
@ -138,7 +144,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {
|
||||
}
|
||||
}
|
||||
if (index == -1) {
|
||||
warning("Mixer::out of mixer slots");
|
||||
warning("MixerImpl::out of mixer slots");
|
||||
delete chan;
|
||||
return;
|
||||
}
|
||||
@ -151,7 +157,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::playRaw(
|
||||
void MixerImpl::playRaw(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
void *sound,
|
||||
@ -166,7 +172,7 @@ void Mixer::playRaw(
|
||||
playInputStream(type, handle, input, id, volume, balance, true, false, ((flags & Mixer::FLAG_REVERSE_STEREO) != 0));
|
||||
}
|
||||
|
||||
void Mixer::playInputStream(
|
||||
void MixerImpl::playInputStream(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
AudioStream *input,
|
||||
@ -198,8 +204,13 @@ void Mixer::playInputStream(
|
||||
insertChannel(handle, chan);
|
||||
}
|
||||
|
||||
void Mixer::mix(int16 *buf, uint len) {
|
||||
void MixerImpl::mixCallback(byte *samples, uint len) {
|
||||
assert(samples);
|
||||
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
int16 *buf = (int16 *)samples;
|
||||
len >>= 2;
|
||||
|
||||
// Since the mixer callback has been called, the mixer must be ready...
|
||||
_mixerReady = true;
|
||||
@ -218,15 +229,7 @@ void Mixer::mix(int16 *buf, uint len) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::mixCallback(void *s, byte *samples, int len) {
|
||||
assert(s);
|
||||
assert(samples);
|
||||
// Len is the number of bytes in the buffer; we divide it by
|
||||
// four to get the number of samples (stereo 16 bit).
|
||||
((Mixer *)s)->mix((int16 *)samples, len >> 2);
|
||||
}
|
||||
|
||||
void Mixer::stopAll() {
|
||||
void MixerImpl::stopAll() {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++) {
|
||||
if (_channels[i] != 0 && !_channels[i]->isPermanent()) {
|
||||
@ -236,7 +239,7 @@ void Mixer::stopAll() {
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::stopID(int id) {
|
||||
void MixerImpl::stopID(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++) {
|
||||
if (_channels[i] != 0 && _channels[i]->getId() == id) {
|
||||
@ -246,7 +249,7 @@ void Mixer::stopID(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::stopHandle(SoundHandle handle) {
|
||||
void MixerImpl::stopHandle(SoundHandle handle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
// Simply ignore stop requests for handles of sounds that already terminated
|
||||
@ -258,7 +261,7 @@ void Mixer::stopHandle(SoundHandle handle) {
|
||||
_channels[index] = 0;
|
||||
}
|
||||
|
||||
void Mixer::setChannelVolume(SoundHandle handle, byte volume) {
|
||||
void MixerImpl::setChannelVolume(SoundHandle handle, byte volume) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
const int index = handle._val % NUM_CHANNELS;
|
||||
@ -268,7 +271,7 @@ void Mixer::setChannelVolume(SoundHandle handle, byte volume) {
|
||||
_channels[index]->setVolume(volume);
|
||||
}
|
||||
|
||||
void Mixer::setChannelBalance(SoundHandle handle, int8 balance) {
|
||||
void MixerImpl::setChannelBalance(SoundHandle handle, int8 balance) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
const int index = handle._val % NUM_CHANNELS;
|
||||
@ -278,7 +281,7 @@ void Mixer::setChannelBalance(SoundHandle handle, int8 balance) {
|
||||
_channels[index]->setBalance(balance);
|
||||
}
|
||||
|
||||
uint32 Mixer::getSoundElapsedTime(SoundHandle handle) {
|
||||
uint32 MixerImpl::getSoundElapsedTime(SoundHandle handle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
const int index = handle._val % NUM_CHANNELS;
|
||||
@ -288,7 +291,7 @@ uint32 Mixer::getSoundElapsedTime(SoundHandle handle) {
|
||||
return _channels[index]->getElapsedTime();
|
||||
}
|
||||
|
||||
void Mixer::pauseAll(bool paused) {
|
||||
void MixerImpl::pauseAll(bool paused) {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++) {
|
||||
if (_channels[i] != 0) {
|
||||
@ -297,7 +300,7 @@ void Mixer::pauseAll(bool paused) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::pauseID(int id, bool paused) {
|
||||
void MixerImpl::pauseID(int id, bool paused) {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++) {
|
||||
if (_channels[i] != 0 && _channels[i]->getId() == id) {
|
||||
@ -307,7 +310,7 @@ void Mixer::pauseID(int id, bool paused) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mixer::pauseHandle(SoundHandle handle, bool paused) {
|
||||
void MixerImpl::pauseHandle(SoundHandle handle, bool paused) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
// Simply ignore (un)pause requests for sounds that already terminated
|
||||
@ -318,7 +321,7 @@ void Mixer::pauseHandle(SoundHandle handle, bool paused) {
|
||||
_channels[index]->pause(paused);
|
||||
}
|
||||
|
||||
bool Mixer::isSoundIDActive(int id) {
|
||||
bool MixerImpl::isSoundIDActive(int id) {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++)
|
||||
if (_channels[i] && _channels[i]->getId() == id)
|
||||
@ -326,7 +329,7 @@ bool Mixer::isSoundIDActive(int id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int Mixer::getSoundID(SoundHandle handle) {
|
||||
int MixerImpl::getSoundID(SoundHandle handle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
const int index = handle._val % NUM_CHANNELS;
|
||||
if (_channels[index] && _channels[index]->_handle._val == handle._val)
|
||||
@ -334,13 +337,13 @@ int Mixer::getSoundID(SoundHandle handle) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Mixer::isSoundHandleActive(SoundHandle handle) {
|
||||
bool MixerImpl::isSoundHandleActive(SoundHandle handle) {
|
||||
Common::StackLock lock(_mutex);
|
||||
const int index = handle._val % NUM_CHANNELS;
|
||||
return _channels[index] && _channels[index]->_handle._val == handle._val;
|
||||
}
|
||||
|
||||
bool Mixer::hasActiveChannelOfType(SoundType type) {
|
||||
bool MixerImpl::hasActiveChannelOfType(SoundType type) {
|
||||
Common::StackLock lock(_mutex);
|
||||
for (int i = 0; i != NUM_CHANNELS; i++)
|
||||
if (_channels[i] && _channels[i]->_type == type)
|
||||
@ -348,7 +351,7 @@ bool Mixer::hasActiveChannelOfType(SoundType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Mixer::setVolumeForSoundType(SoundType type, int volume) {
|
||||
void MixerImpl::setVolumeForSoundType(SoundType type, int volume) {
|
||||
assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));
|
||||
|
||||
// Check range
|
||||
@ -363,7 +366,7 @@ void Mixer::setVolumeForSoundType(SoundType type, int volume) {
|
||||
_volumeForSoundType[type] = volume;
|
||||
}
|
||||
|
||||
int Mixer::getVolumeForSoundType(SoundType type) const {
|
||||
int MixerImpl::getVolumeForSoundType(SoundType type) const {
|
||||
assert(0 <= type && type < ARRAYSIZE(_volumeForSoundType));
|
||||
|
||||
return _volumeForSoundType[type];
|
||||
@ -443,7 +446,7 @@ uint32 Channel::getElapsedTime() {
|
||||
// Convert the number of samples into a time duration. To avoid
|
||||
// overflow, this has to be done in a somewhat non-obvious way.
|
||||
|
||||
uint rate = _mixer->getOutputRate();
|
||||
uint32 rate = _mixer->getOutputRate();
|
||||
|
||||
uint32 seconds = _samplesConsumed / rate;
|
||||
uint32 milliseconds = (1000 * (_samplesConsumed % rate)) / rate;
|
||||
|
@ -38,6 +38,7 @@ namespace Audio {
|
||||
class AudioStream;
|
||||
class Channel;
|
||||
class Mixer;
|
||||
class MixerImpl;
|
||||
|
||||
/**
|
||||
* A SoundHandle instances corresponds to a specific sound
|
||||
@ -47,7 +48,7 @@ class Mixer;
|
||||
*/
|
||||
class SoundHandle {
|
||||
friend class Channel;
|
||||
friend class Mixer;
|
||||
friend class MixerImpl;
|
||||
uint32 _val;
|
||||
public:
|
||||
inline SoundHandle() : _val(0xFFFFFFFF) {}
|
||||
@ -104,24 +105,9 @@ public:
|
||||
kMaxMixerVolume = 256
|
||||
};
|
||||
|
||||
private:
|
||||
enum {
|
||||
NUM_CHANNELS = 16
|
||||
};
|
||||
|
||||
OSystem *_syst;
|
||||
Common::Mutex _mutex;
|
||||
|
||||
int _volumeForSoundType[4];
|
||||
|
||||
uint32 _handleSeed;
|
||||
Channel *_channels[NUM_CHANNELS];
|
||||
|
||||
bool _mixerReady;
|
||||
|
||||
public:
|
||||
Mixer();
|
||||
~Mixer();
|
||||
Mixer() {}
|
||||
virtual ~Mixer() {}
|
||||
|
||||
|
||||
|
||||
@ -132,8 +118,10 @@ public:
|
||||
* sync with an audio stream. In particular, the Adlib MIDI emulation...
|
||||
*
|
||||
* @return whether the mixer is ready and setup
|
||||
*
|
||||
* @todo get rid of this?
|
||||
*/
|
||||
bool isReady() const { return _mixerReady; }
|
||||
virtual bool isReady() const = 0;
|
||||
|
||||
|
||||
|
||||
@ -143,12 +131,12 @@ public:
|
||||
* (using the makeLinearInputStream factory function), which is then
|
||||
* passed on to playInputStream.
|
||||
*/
|
||||
void playRaw(
|
||||
virtual void playRaw(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
void *sound, uint32 size, uint rate, byte flags,
|
||||
int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0,
|
||||
uint32 loopStart = 0, uint32 loopEnd = 0);
|
||||
uint32 loopStart = 0, uint32 loopEnd = 0) = 0;
|
||||
|
||||
/**
|
||||
* Start playing the given audio input stream.
|
||||
@ -170,35 +158,35 @@ public:
|
||||
* not stop this particular stream
|
||||
* @param reverseStereo a flag indicating whether left and right channels shall be swapped
|
||||
*/
|
||||
void playInputStream(
|
||||
virtual void playInputStream(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
AudioStream *input,
|
||||
int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0,
|
||||
bool autofreeStream = true,
|
||||
bool permanent = false,
|
||||
bool reverseStereo = false);
|
||||
bool reverseStereo = false) = 0;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Stop all currently playing sounds.
|
||||
*/
|
||||
void stopAll();
|
||||
virtual void stopAll() = 0;
|
||||
|
||||
/**
|
||||
* Stop playing the sound with given ID.
|
||||
*
|
||||
* @param id the ID of the sound to affect
|
||||
*/
|
||||
void stopID(int id);
|
||||
virtual void stopID(int id) = 0;
|
||||
|
||||
/**
|
||||
* Stop playing the sound corresponding to the given handle.
|
||||
*
|
||||
* @param handle the sound to affect
|
||||
*/
|
||||
void stopHandle(SoundHandle handle);
|
||||
virtual void stopHandle(SoundHandle handle) = 0;
|
||||
|
||||
|
||||
|
||||
@ -208,7 +196,7 @@ public:
|
||||
*
|
||||
* @param paused true to pause everything, false to unpause
|
||||
*/
|
||||
void pauseAll(bool paused);
|
||||
virtual void pauseAll(bool paused) = 0;
|
||||
|
||||
/**
|
||||
* Pause/unpause the sound with the given ID.
|
||||
@ -216,7 +204,7 @@ public:
|
||||
* @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);
|
||||
virtual void pauseID(int id, bool paused) = 0;
|
||||
|
||||
/**
|
||||
* Pause/unpause the sound corresponding to the given handle.
|
||||
@ -224,7 +212,7 @@ public:
|
||||
* @param handle the sound to affect
|
||||
* @param paused true to pause the sound, false to unpause it
|
||||
*/
|
||||
void pauseHandle(SoundHandle handle, bool paused);
|
||||
virtual void pauseHandle(SoundHandle handle, bool paused) = 0;
|
||||
|
||||
|
||||
|
||||
@ -234,7 +222,7 @@ public:
|
||||
* @param id the ID of the sound to query
|
||||
* @return true if the sound is active
|
||||
*/
|
||||
bool isSoundIDActive(int id);
|
||||
virtual bool isSoundIDActive(int id) = 0;
|
||||
|
||||
/**
|
||||
* Get the sound ID of handle sound
|
||||
@ -242,7 +230,7 @@ public:
|
||||
* @param handle sound to query
|
||||
* @return sound ID if active
|
||||
*/
|
||||
int getSoundID(SoundHandle handle);
|
||||
virtual int getSoundID(SoundHandle handle) = 0;
|
||||
|
||||
/**
|
||||
* Check if a sound with the given handle is active.
|
||||
@ -250,7 +238,7 @@ public:
|
||||
* @param handle sound to query
|
||||
* @return true if the sound is active
|
||||
*/
|
||||
bool isSoundHandleActive(SoundHandle handle);
|
||||
virtual bool isSoundHandleActive(SoundHandle handle) = 0;
|
||||
|
||||
|
||||
|
||||
@ -260,7 +248,7 @@ public:
|
||||
* @param handle the sound to affect
|
||||
* @param volume the new channel volume (0 - kMaxChannelVolume)
|
||||
*/
|
||||
void setChannelVolume(SoundHandle handle, byte volume);
|
||||
virtual void setChannelVolume(SoundHandle handle, byte volume) = 0;
|
||||
|
||||
/**
|
||||
* Set the channel balance for the given handle.
|
||||
@ -269,12 +257,12 @@ public:
|
||||
* @param balance the new channel balance:
|
||||
* (-127 ... 0 ... 127) corresponds to (left ... center ... right)
|
||||
*/
|
||||
void setChannelBalance(SoundHandle handle, int8 balance);
|
||||
virtual void setChannelBalance(SoundHandle handle, int8 balance) = 0;
|
||||
|
||||
/**
|
||||
* Get approximation of for how long the channel has been playing.
|
||||
*/
|
||||
uint32 getSoundElapsedTime(SoundHandle handle);
|
||||
virtual uint32 getSoundElapsedTime(SoundHandle handle) = 0;
|
||||
|
||||
/**
|
||||
* Check whether any channel of the given sound type is active.
|
||||
@ -284,7 +272,7 @@ public:
|
||||
* @param type the sound type to look for
|
||||
* @return true if any channels of the specified type are active.
|
||||
*/
|
||||
bool hasActiveChannelOfType(SoundType type);
|
||||
virtual bool hasActiveChannelOfType(SoundType type) = 0;
|
||||
|
||||
/**
|
||||
* Set the volume for the given sound type.
|
||||
@ -292,7 +280,7 @@ public:
|
||||
* @param type the sound type
|
||||
* @param volume the new global volume, 0 - kMaxMixerVolume
|
||||
*/
|
||||
void setVolumeForSoundType(SoundType type, int volume);
|
||||
virtual void setVolumeForSoundType(SoundType type, int volume) = 0;
|
||||
|
||||
/**
|
||||
* Query the global volume.
|
||||
@ -300,7 +288,7 @@ public:
|
||||
* @param type the sound type
|
||||
* @return the global music volume, 0 - kMaxMixerVolume
|
||||
*/
|
||||
int getVolumeForSoundType(SoundType type) const;
|
||||
virtual int getVolumeForSoundType(SoundType type) const = 0;
|
||||
|
||||
/**
|
||||
* Query the system's audio output sample rate. This returns
|
||||
@ -308,26 +296,7 @@ public:
|
||||
*
|
||||
* @return the output sample rate in Hz
|
||||
*/
|
||||
uint getOutputRate() const;
|
||||
|
||||
protected:
|
||||
void insertChannel(SoundHandle *handle, Channel *chan);
|
||||
|
||||
/**
|
||||
* Internal main method -- all the actual mixing work is done from here.
|
||||
*/
|
||||
void mix(int16 * buf, uint len);
|
||||
|
||||
// FIXME: temporary "public" to allow access to mixCallback
|
||||
// from within OSystem::makeMixer()
|
||||
public:
|
||||
/**
|
||||
* The mixer callback function, passed on to OSystem::setSoundCallback().
|
||||
* This simply calls the mix() method.
|
||||
*/
|
||||
static void mixCallback(void *s, byte *samples, int len);
|
||||
|
||||
void setReady(bool ready) { _mixerReady = ready; }
|
||||
virtual uint getOutputRate() const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
154
sound/mixer_intern.h
Normal file
154
sound/mixer_intern.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SOUND_MIXER_INTERN_H
|
||||
#define SOUND_MIXER_INTERN_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/mutex.h"
|
||||
#include "sound/mixer.h"
|
||||
|
||||
namespace Audio {
|
||||
|
||||
/**
|
||||
* The (default) implementation of the ScummVM audio mixing subsystem.
|
||||
*
|
||||
* Backends are responsible for allocating (and later releasing) an instance
|
||||
* of this class, which engines can access via OSystem::getMixer().
|
||||
*
|
||||
* Initialisation of instances of this class usually happens as follows:
|
||||
* 1) Creat a new Audio::MixerImpl instance.
|
||||
* 2) Set the hardware output sample rate via the setSampleRate() method.
|
||||
* 3) Hook up the mixCallback() in a suitable audio processing thread/callback.
|
||||
* 4) Change the mixer into ready mode via setReady(true).
|
||||
* 5) Start audio processing (e.g. by resuming the audio thread, if applicable).
|
||||
*
|
||||
* In the future, we might make it possible for backends to provide
|
||||
* (partial) alternative implementations of the mixer, e.g. to make
|
||||
* better use of native sound mixing support on low-end devices.
|
||||
*
|
||||
* @see OSystem::getMixer()
|
||||
*/
|
||||
class MixerImpl : public Mixer {
|
||||
private:
|
||||
enum {
|
||||
NUM_CHANNELS = 16
|
||||
};
|
||||
|
||||
OSystem *_syst;
|
||||
Common::Mutex _mutex;
|
||||
|
||||
uint _sampleRate;
|
||||
bool _mixerReady;
|
||||
uint32 _handleSeed;
|
||||
|
||||
int _volumeForSoundType[4];
|
||||
Channel *_channels[NUM_CHANNELS];
|
||||
|
||||
|
||||
public:
|
||||
MixerImpl(OSystem *system);
|
||||
~MixerImpl();
|
||||
|
||||
virtual bool isReady() const { return _mixerReady; }
|
||||
|
||||
virtual void playRaw(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
void *sound, uint32 size, uint rate, byte flags,
|
||||
int id = -1, byte volume = 255, int8 balance = 0,
|
||||
uint32 loopStart = 0, uint32 loopEnd = 0);
|
||||
|
||||
virtual void playInputStream(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
AudioStream *input,
|
||||
int id = -1, byte volume = 255, int8 balance = 0,
|
||||
bool autofreeStream = true,
|
||||
bool permanent = false,
|
||||
bool reverseStereo = false);
|
||||
|
||||
|
||||
|
||||
virtual void stopAll();
|
||||
virtual void stopID(int id);
|
||||
virtual void stopHandle(SoundHandle handle);
|
||||
|
||||
virtual void pauseAll(bool paused);
|
||||
virtual void pauseID(int id, bool paused);
|
||||
virtual void pauseHandle(SoundHandle handle, bool paused);
|
||||
|
||||
virtual bool isSoundIDActive(int id);
|
||||
virtual int getSoundID(SoundHandle handle);
|
||||
|
||||
virtual bool isSoundHandleActive(SoundHandle handle);
|
||||
|
||||
virtual void setChannelVolume(SoundHandle handle, byte volume);
|
||||
virtual void setChannelBalance(SoundHandle handle, int8 balance);
|
||||
|
||||
virtual uint32 getSoundElapsedTime(SoundHandle handle);
|
||||
|
||||
virtual bool hasActiveChannelOfType(SoundType type);
|
||||
|
||||
virtual void setVolumeForSoundType(SoundType type, int volume);
|
||||
virtual int getVolumeForSoundType(SoundType type) const;
|
||||
|
||||
virtual uint getOutputRate() const;
|
||||
|
||||
protected:
|
||||
void insertChannel(SoundHandle *handle, Channel *chan);
|
||||
|
||||
public:
|
||||
/**
|
||||
* The mixer callback function, to be called at regular intervals by
|
||||
* the backend (e.g. from an audio mixing thread). All the actual mixing
|
||||
* work is done from here.
|
||||
*/
|
||||
void mixCallback(byte *samples, uint len);
|
||||
|
||||
/**
|
||||
* Set the internal 'is ready' flag of the mixer.
|
||||
* Backends should invoke Mixer::setReady(true) once initialisation of
|
||||
* their audio system has been completed (and in particular, *after*
|
||||
* setOutputRate() has been called).
|
||||
*/
|
||||
void setReady(bool ready);
|
||||
|
||||
/**
|
||||
* Set the output sample rate.
|
||||
*
|
||||
* @param sampleRate the new output sample rate
|
||||
*
|
||||
* @note Right now, this can be done exactly ONCE. That is, the mixer
|
||||
* currently does not support changing the output sample rate after it
|
||||
* has been set for the first time. This may change in the future.
|
||||
*/
|
||||
void setOutputRate(uint sampleRate);
|
||||
};
|
||||
|
||||
|
||||
} // End of namespace Audio
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user