synced mixer changes with upstream
This commit is contained in:
parent
71cf7f03b3
commit
3f9e42f1e9
12 changed files with 352 additions and 249 deletions
|
@ -44,6 +44,7 @@ class Bitmap;
|
|||
class Timer;
|
||||
|
||||
namespace Audio {
|
||||
class MixerImpl;
|
||||
class Mixer;
|
||||
}
|
||||
|
||||
|
@ -51,12 +52,6 @@ class Driver {
|
|||
public:
|
||||
Driver() { ; }
|
||||
virtual ~Driver() { ; }
|
||||
Driver(int screenW, int screenH, int screenBPP, bool fullscreen = false) {
|
||||
_screenWidth = screenW;
|
||||
_screenHeight = screenH;
|
||||
_screenBPP = screenBPP;
|
||||
_isFullscreen = fullscreen;
|
||||
}
|
||||
|
||||
struct TextObjectHandle {
|
||||
uint16 *bitmapData;
|
||||
|
@ -67,6 +62,8 @@ public:
|
|||
int height;
|
||||
};
|
||||
|
||||
virtual void init() = 0;
|
||||
|
||||
virtual void toggleFullscreenMode() = 0;
|
||||
|
||||
virtual bool isHardwareAccelerated() = 0;
|
||||
|
@ -231,27 +228,7 @@ public:
|
|||
/** Delay/sleep for the specified amount of milliseconds. */
|
||||
virtual void delayMillis(uint msecs) = 0;
|
||||
|
||||
/**
|
||||
* Set the timer callback, a function which is periodically invoked by the
|
||||
* driver. This can for example be done via a background thread.
|
||||
* There is at most one active timer; if this method is called while there
|
||||
* is already an active timer, then the new timer callback should replace
|
||||
* the previous one. In particular, passing a callback pointer value of 0
|
||||
* is legal and can be used to clear the current timer callback.
|
||||
* @see Timer
|
||||
* @note The implementation of this method must be 'atomic' in the sense
|
||||
* that when the method returns, the previously set callback must
|
||||
* not be in use anymore (in particular, if timers are implemented
|
||||
* via threads, then it must be ensured that the timer thread is
|
||||
* not using the old callback function anymore).
|
||||
*
|
||||
* @param callback pointer to the callback. May be 0 to reset the timer
|
||||
* @param interval the interval (in milliseconds) between invocations
|
||||
* of the callback
|
||||
*/
|
||||
virtual void setTimerCallback() = 0;
|
||||
|
||||
virtual void clearTimerCallback() = 0;
|
||||
virtual Common::TimerManager *getTimerManager() = 0;
|
||||
|
||||
//@}
|
||||
|
||||
|
@ -301,31 +278,9 @@ public:
|
|||
|
||||
/** @name Sound */
|
||||
//@{
|
||||
typedef void (*SoundProc)(void *param, byte *buf, int len);
|
||||
virtual void setupMixer() = 0;
|
||||
|
||||
/**
|
||||
* Set the audio callback which is invoked whenever samples need to be generated.
|
||||
* Currently, only the 16-bit signed mode is ever used for GF
|
||||
* @param proc pointer to the callback.
|
||||
* @param param an arbitrary parameter which is stored and passed to proc.
|
||||
*/
|
||||
virtual bool setSoundCallback(SoundProc proc, void *param) = 0;
|
||||
|
||||
/**
|
||||
* Remove any audio callback previously set via setSoundCallback, thus effectively
|
||||
* stopping all audio output immediately.
|
||||
* @see setSoundCallback
|
||||
*/
|
||||
virtual void clearSoundCallback() = 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;
|
||||
virtual Audio::Mixer *getMixer() = 0;
|
||||
|
||||
//@}
|
||||
|
||||
|
@ -342,7 +297,5 @@ protected:
|
|||
};
|
||||
|
||||
extern Driver *g_driver;
|
||||
extern DefaultTimerManager *g_timer;
|
||||
extern Audio::Mixer *g_mixer;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,12 +25,17 @@
|
|||
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "mixer/mixer_intern.h"
|
||||
|
||||
#include "engine/backend/sdl/driver_sdl.h"
|
||||
#include "engine/backend/default-timer.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define SAMPLES_PER_SEC 22050
|
||||
|
||||
// NOTE: This is not a complete driver, it needs to be subclassed
|
||||
// to provide rendering functionality.
|
||||
|
||||
|
@ -278,6 +283,34 @@ static byte SDLModToDriverKeyFlags(SDLMod mod) {
|
|||
return b;
|
||||
}
|
||||
|
||||
static Uint32 timer_handler(Uint32 interval, void *param) {
|
||||
((DefaultTimerManager *)param)->handler();
|
||||
return interval;
|
||||
}
|
||||
|
||||
Common::TimerManager *DriverSDL::getTimerManager() {
|
||||
assert(_timer);
|
||||
return _timer;
|
||||
}
|
||||
|
||||
DriverSDL::DriverSDL() {
|
||||
_mixer = NULL;
|
||||
_timer = NULL;
|
||||
}
|
||||
|
||||
DriverSDL::~DriverSDL() {
|
||||
SDL_RemoveTimer(_timerID);
|
||||
SDL_CloseAudio();
|
||||
|
||||
delete _mixer;
|
||||
delete _timer;
|
||||
}
|
||||
|
||||
void DriverSDL::init() {
|
||||
_timer = new DefaultTimerManager();
|
||||
_timerID = SDL_AddTimer(10, &timer_handler, _timer);
|
||||
}
|
||||
|
||||
char *DriverSDL::getVideoDeviceName() {
|
||||
return "SDL Video Device";
|
||||
}
|
||||
|
@ -366,21 +399,6 @@ void DriverSDL::delayMillis(uint msecs) {
|
|||
SDL_Delay(msecs);
|
||||
}
|
||||
|
||||
static SDL_TimerID _timerID = NULL;
|
||||
|
||||
static Uint32 timer_handler(Uint32 interval, void *param) {
|
||||
((DefaultTimerManager *)param)->handler();
|
||||
return interval;
|
||||
}
|
||||
|
||||
void DriverSDL::setTimerCallback() {
|
||||
_timerID = SDL_AddTimer(10, &timer_handler, g_timer);
|
||||
}
|
||||
|
||||
void DriverSDL::clearTimerCallback() {
|
||||
SDL_RemoveTimer(_timerID);
|
||||
}
|
||||
|
||||
Common::MutexRef DriverSDL::createMutex() {
|
||||
return (MutexRef)SDL_CreateMutex();
|
||||
}
|
||||
|
@ -397,40 +415,60 @@ void DriverSDL::deleteMutex(MutexRef mutex) {
|
|||
SDL_DestroyMutex((SDL_mutex *)mutex);
|
||||
}
|
||||
|
||||
bool DriverSDL::setSoundCallback(SoundProc proc, void *param) {
|
||||
void DriverSDL::mixCallback(void *sys, byte *samples, int len) {
|
||||
DriverSDL *this_ = (DriverSDL *)sys;
|
||||
assert(this_);
|
||||
|
||||
if (this_->_mixer)
|
||||
this_->_mixer->mixCallback(samples, len);
|
||||
}
|
||||
|
||||
void DriverSDL::setupMixer() {
|
||||
SDL_AudioSpec desired;
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
// Determine the desired output sampling frequency.
|
||||
_samplesPerSec = 0;
|
||||
|
||||
if (_samplesPerSec <= 0)
|
||||
_samplesPerSec = SAMPLES_PER_SEC;
|
||||
|
||||
// Determine the sample buffer size. We want it to store enough data for
|
||||
// about 1/10th of a second. Note that it must be a power of two.
|
||||
// about 1/16th of a second. Note that it must be a power of two.
|
||||
// So e.g. at 22050 Hz, we request a sample buffer size of 2048.
|
||||
int samples = 0x8000;
|
||||
while (10 * samples >= _samplesPerSec) {
|
||||
int samples = 8192;
|
||||
while (16 * samples >= _samplesPerSec) {
|
||||
samples >>= 1;
|
||||
}
|
||||
|
||||
memset(&desired, 0, sizeof(desired));
|
||||
|
||||
desired.freq = _samplesPerSec;
|
||||
desired.format = AUDIO_S16SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = (uint16)samples;
|
||||
desired.callback = proc;
|
||||
desired.userdata = param;
|
||||
desired.callback = mixCallback;
|
||||
desired.userdata = this;
|
||||
|
||||
if (SDL_OpenAudio(&desired, NULL) != 0) {
|
||||
return false;
|
||||
}
|
||||
// Create the mixer instance
|
||||
assert(!_mixer);
|
||||
_mixer = new Audio::MixerImpl();
|
||||
assert(_mixer);
|
||||
|
||||
if (SDL_OpenAudio(&desired, &obtained) != 0) {
|
||||
warning("Could not open audio device: %s", SDL_GetError());
|
||||
_samplesPerSec = 0;
|
||||
_mixer->setReady(false);
|
||||
} else {
|
||||
_samplesPerSec = obtained.freq;
|
||||
_mixer->setOutputRate(_samplesPerSec);
|
||||
_mixer->setReady(true);
|
||||
SDL_PauseAudio(0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void DriverSDL::clearSoundCallback() {
|
||||
SDL_CloseAudio();
|
||||
}
|
||||
|
||||
int DriverSDL::getOutputSampleRate() const {
|
||||
return _samplesPerSec;
|
||||
Audio::Mixer *DriverSDL::getMixer() {
|
||||
assert(_mixer);
|
||||
return _mixer;
|
||||
}
|
||||
|
||||
/* This function sends the SDL signal to
|
||||
|
|
|
@ -40,10 +40,17 @@
|
|||
// NOTE: This is not a complete driver, it needs to be subclassed
|
||||
// to provide rendering functionality.
|
||||
|
||||
namespace Audio {
|
||||
class MixerImpl;
|
||||
class Mixer;
|
||||
}
|
||||
|
||||
class DriverSDL : public Driver {
|
||||
public:
|
||||
DriverSDL() : _samplesPerSec(22050) { ; }
|
||||
virtual ~DriverSDL() { ; }
|
||||
DriverSDL();
|
||||
virtual ~DriverSDL();
|
||||
|
||||
virtual void init();
|
||||
|
||||
char *getVideoDeviceName();
|
||||
|
||||
|
@ -55,22 +62,28 @@ public:
|
|||
bool pollEvent(Event &event);
|
||||
uint32 getMillis();
|
||||
void delayMillis(uint msecs);
|
||||
void setTimerCallback();
|
||||
void clearTimerCallback();
|
||||
Common::TimerManager *getTimerManager();
|
||||
|
||||
MutexRef createMutex();
|
||||
void lockMutex(MutexRef mutex);
|
||||
void unlockMutex(MutexRef mutex);
|
||||
void deleteMutex(MutexRef mutex);
|
||||
|
||||
bool setSoundCallback(SoundProc proc, void *param);
|
||||
void clearSoundCallback();
|
||||
int getOutputSampleRate() const;
|
||||
void setupMixer();
|
||||
static void mixCallback(void *s, byte *samples, int len);
|
||||
Audio::Mixer *getMixer();
|
||||
|
||||
void quit();
|
||||
|
||||
private:
|
||||
|
||||
int _samplesPerSec;
|
||||
Common::TimerManager *_timer;
|
||||
SDL_TimerID _timerID;
|
||||
|
||||
protected:
|
||||
|
||||
Audio::MixerImpl *_mixer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -66,11 +66,11 @@ Imuse::Imuse(int fps) {
|
|||
vimaInit(imuseDestTable);
|
||||
_stateMusicTable = grimStateMusicTable;
|
||||
_seqMusicTable = grimSeqMusicTable;
|
||||
g_timer->installTimerProc(timerHandler, 1000000 / _callbackFps, this);
|
||||
g_driver->getTimerManager()->installTimerProc(timerHandler, 1000000 / _callbackFps, this);
|
||||
}
|
||||
|
||||
Imuse::~Imuse() {
|
||||
g_timer->removeTimerProc(timerHandler);
|
||||
g_driver->getTimerManager()->removeTimerProc(timerHandler);
|
||||
stopAllSounds();
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
delete _track[l];
|
||||
|
@ -139,11 +139,11 @@ void Imuse::restoreState(SaveGame *savedState) {
|
|||
track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
|
||||
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
|
||||
g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||
g_mixer->pauseHandle(track->handle, true);
|
||||
g_driver->getMixer()->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||
g_driver->getMixer()->pauseHandle(track->handle, true);
|
||||
}
|
||||
savedState->endSection();
|
||||
g_mixer->pauseAll(false);
|
||||
g_driver->getMixer()->pauseAll(false);
|
||||
|
||||
printf("Imuse::restoreState() finished.\n");
|
||||
}
|
||||
|
@ -205,7 +205,7 @@ void Imuse::callback() {
|
|||
// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
|
||||
// mark it as unused.
|
||||
if (!track->stream) {
|
||||
if (!g_mixer->isSoundHandleActive(track->handle))
|
||||
if (!g_driver->getMixer()->isSoundHandleActive(track->handle))
|
||||
memset(track, 0, sizeof(Track));
|
||||
continue;
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ void Imuse::callback() {
|
|||
if (result > mixer_size)
|
||||
result = mixer_size;
|
||||
|
||||
if (g_mixer->isReady()) {
|
||||
if (g_driver->getMixer()->isReady()) {
|
||||
track->stream->queueBuffer(data, result);
|
||||
track->regionOffset += result;
|
||||
} else
|
||||
|
@ -311,9 +311,9 @@ void Imuse::callback() {
|
|||
mixer_size -= result;
|
||||
assert(mixer_size >= 0);
|
||||
} while (mixer_size);
|
||||
if (g_mixer->isReady()) {
|
||||
g_mixer->setChannelVolume(track->handle, track->getVol());
|
||||
g_mixer->setChannelBalance(track->handle, track->getPan());
|
||||
if (g_driver->getMixer()->isReady()) {
|
||||
g_driver->getMixer()->setChannelVolume(track->handle, track->getVol());
|
||||
g_driver->getMixer()->setChannelBalance(track->handle, track->getPan());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ void Imuse::flushTrack(Track *track) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!g_mixer->isSoundHandleActive(track->handle)) {
|
||||
if (!g_driver->getMixer()->isSoundHandleActive(track->handle)) {
|
||||
memset(track, 0, sizeof(Track));
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ void Imuse::flushTracks() {
|
|||
Common::StackLock lock(_mutex);
|
||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && track->toBeRemoved && !g_mixer->isSoundHandleActive(track->handle)) {
|
||||
if (track->used && track->toBeRemoved && !g_driver->getMixer()->isSoundHandleActive(track->handle)) {
|
||||
memset(track, 0, sizeof(Track));
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ bool Imuse::isVoicePlaying() {
|
|||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used && track->volGroupId == IMUSE_VOLGRP_VOICE) {
|
||||
if (g_mixer->isSoundHandleActive(track->handle))
|
||||
if (g_driver->getMixer()->isSoundHandleActive(track->handle))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ bool Imuse::getSoundStatus(const char *soundName) {
|
|||
|
||||
track = findTrack(soundName);
|
||||
// Warn the user if the track was not found
|
||||
if (track == NULL || !g_mixer->isSoundHandleActive(track->handle)) {
|
||||
if (track == NULL || !g_driver->getMixer()->isSoundHandleActive(track->handle)) {
|
||||
// This debug warning should be "light" since this function gets called
|
||||
// on occassion to see if a sound has stopped yet
|
||||
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
|
||||
|
@ -180,7 +180,7 @@ void Imuse::stopAllSounds() {
|
|||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||
Track *track = _track[l];
|
||||
if (track->used) {
|
||||
g_mixer->stopHandle(track->handle);
|
||||
g_driver->getMixer()->stopHandle(track->handle);
|
||||
if (track->soundDesc) {
|
||||
_sound->closeSound(track->soundDesc);
|
||||
}
|
||||
|
|
|
@ -63,7 +63,7 @@ int Imuse::allocSlot(int priority) {
|
|||
Track *track = _track[trackId];
|
||||
|
||||
// Stop the track immediately
|
||||
g_mixer->stopHandle(track->handle);
|
||||
g_driver->getMixer()->stopHandle(track->handle);
|
||||
if (track->soundDesc) {
|
||||
_sound->closeSound(track->soundDesc);
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int vo
|
|||
}
|
||||
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
|
||||
g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||
g_driver->getMixer()->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||
track->used = true;
|
||||
|
||||
return true;
|
||||
|
@ -362,7 +362,7 @@ Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
|
|||
|
||||
if (fadeTrack->used) {
|
||||
flushTrack(fadeTrack);
|
||||
g_mixer->stopHandle(fadeTrack->handle);
|
||||
g_driver->getMixer()->stopHandle(fadeTrack->handle);
|
||||
}
|
||||
|
||||
// Clone the settings of the given track
|
||||
|
@ -383,7 +383,7 @@ Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
|
|||
|
||||
// Create an appendable output buffer
|
||||
fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags));
|
||||
g_mixer->playInputStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
|
||||
g_driver->getMixer()->playInputStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
|
||||
fadeTrack->used = true;
|
||||
|
||||
return fadeTrack;
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include "common/util.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "mixer/mixer.h"
|
||||
|
||||
#include "engine/lua.h"
|
||||
#include "engine/resource.h"
|
||||
#include "engine/actor.h"
|
||||
|
@ -52,8 +54,6 @@
|
|||
|
||||
#include "engine/imuse/imuse.h"
|
||||
|
||||
#include "mixer/mixer.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
|
@ -1959,32 +1959,32 @@ static void ImSetVoiceEffect() {
|
|||
|
||||
static void ImSetMusicVol() {
|
||||
DEBUG_FUNCTION();
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, check_int(1));
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, check_int(1));
|
||||
}
|
||||
|
||||
static void ImGetMusicVol() {
|
||||
DEBUG_FUNCTION();
|
||||
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
|
||||
lua_pushnumber(g_driver->getMixer()->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
|
||||
}
|
||||
|
||||
static void ImSetVoiceVol() {
|
||||
DEBUG_FUNCTION();
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, check_int(1));
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, check_int(1));
|
||||
}
|
||||
|
||||
static void ImGetVoiceVol() {
|
||||
DEBUG_FUNCTION();
|
||||
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
|
||||
lua_pushnumber(g_driver->getMixer()->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
|
||||
}
|
||||
|
||||
static void ImSetSfxVol() {
|
||||
DEBUG_FUNCTION();
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, check_int(1));
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, check_int(1));
|
||||
}
|
||||
|
||||
static void ImGetSfxVol() {
|
||||
DEBUG_FUNCTION();
|
||||
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
|
||||
lua_pushnumber(g_driver->getMixer()->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
|
||||
}
|
||||
|
||||
static void ImSetParam() {
|
||||
|
|
|
@ -52,8 +52,6 @@ enDebugLevels debugLevel = DEBUG_NONE;
|
|||
|
||||
static bool g_lua_initialized = false;
|
||||
Driver *g_driver = NULL;
|
||||
DefaultTimerManager *g_timer = NULL;
|
||||
Audio::Mixer *g_mixer = NULL;
|
||||
|
||||
static bool parseBoolStr(const char *val) {
|
||||
if (val == NULL || val[0] == 0)
|
||||
|
@ -165,15 +163,12 @@ needshelp:
|
|||
g_driver = new DriverTinyGL(640, 480, 16, fullscreen);
|
||||
else
|
||||
g_driver = new DriverGL(640, 480, 24, fullscreen);
|
||||
g_timer = new DefaultTimerManager();
|
||||
g_driver->setTimerCallback();
|
||||
g_mixer = new Audio::Mixer();
|
||||
g_driver->setSoundCallback(Audio::Mixer::mixCallback, g_mixer);
|
||||
g_mixer->setReady(true);
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127);
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||
g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||
g_driver->init();
|
||||
g_driver->setupMixer();
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127);
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||
g_driver->getMixer()->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||
g_engine = new Engine();
|
||||
g_resourceloader = new ResourceLoader();
|
||||
g_localizer = new Localizer();
|
||||
|
@ -213,6 +208,7 @@ needshelp:
|
|||
g_engine->setMode(ENGINE_MODE_NORMAL);
|
||||
g_engine->mainLoop();
|
||||
|
||||
|
||||
quit();
|
||||
|
||||
return 0;
|
||||
|
@ -229,8 +225,6 @@ void quit() {
|
|||
delete g_registry;
|
||||
g_registry = NULL;
|
||||
}
|
||||
if (g_driver)
|
||||
g_driver->clearTimerCallback();
|
||||
delete g_smush;
|
||||
g_smush = NULL;
|
||||
delete g_imuse;
|
||||
|
@ -241,10 +235,6 @@ void quit() {
|
|||
g_engine = NULL;
|
||||
delete g_resourceloader;
|
||||
g_resourceloader = NULL;
|
||||
delete g_timer;
|
||||
g_timer = NULL;
|
||||
delete g_mixer;
|
||||
g_mixer = NULL;
|
||||
delete g_driver;
|
||||
g_driver = NULL;
|
||||
|
||||
|
|
|
@ -90,11 +90,11 @@ void Smush::init() {
|
|||
_externalBuffer = new byte[_width * _height * 2];
|
||||
|
||||
vimaInit(smushDestTable);
|
||||
g_timer->installTimerProc(&timerCallback, _speed, NULL);
|
||||
g_driver->getTimerManager()->installTimerProc(&timerCallback, _speed, NULL);
|
||||
}
|
||||
|
||||
void Smush::deinit() {
|
||||
g_timer->removeTimerProc(&timerCallback);
|
||||
g_driver->getTimerManager()->removeTimerProc(&timerCallback);
|
||||
|
||||
if (_internalBuffer) {
|
||||
delete[] _internalBuffer;
|
||||
|
@ -112,7 +112,7 @@ void Smush::deinit() {
|
|||
if (_stream) {
|
||||
_stream->finish();
|
||||
_stream = NULL;
|
||||
g_mixer->stopHandle(_soundHandle);
|
||||
g_driver->getMixer()->stopHandle(_soundHandle);
|
||||
}
|
||||
_videoLooping = false;
|
||||
_videoFinished = true;
|
||||
|
@ -130,9 +130,9 @@ void Smush::handleWave(const byte *src, uint32 size) {
|
|||
|
||||
if (!_stream) {
|
||||
_stream = Audio::makeAppendableAudioStream(_freq, flags);
|
||||
g_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_soundHandle, _stream);
|
||||
g_driver->getMixer()->playInputStream(Audio::Mixer::kMusicSoundType, &_soundHandle, _stream);
|
||||
}
|
||||
if (g_mixer->isReady()) {
|
||||
if (g_driver->getMixer()->isReady()) {
|
||||
_stream->queueBuffer((byte *)dst, size * _channels * 2);
|
||||
} else {
|
||||
delete[] dst;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||
*
|
||||
* Residual is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the AUTHORS
|
||||
* 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
|
||||
|
@ -23,16 +23,15 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include "common/sys.h"
|
||||
#include "common/util.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#include "engine/backend/driver.h"
|
||||
|
||||
#include "mixer/mixer.h"
|
||||
#include "mixer/mixer_intern.h"
|
||||
#include "mixer/rate.h"
|
||||
#include "mixer/audiostream.h"
|
||||
|
||||
#include "engine/backend/driver.h"
|
||||
|
||||
namespace Audio {
|
||||
|
||||
#pragma mark -
|
||||
|
@ -104,30 +103,38 @@ public:
|
|||
#pragma mark -
|
||||
|
||||
|
||||
Mixer::Mixer() {
|
||||
_handleSeed = 0;
|
||||
MixerImpl::MixerImpl()
|
||||
: _sampleRate(0), _mixerReady(false), _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)g_driver->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++) {
|
||||
|
@ -137,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;
|
||||
}
|
||||
|
@ -150,7 +157,7 @@ void Mixer::insertChannel(SoundHandle *handle, Channel *chan) {
|
|||
}
|
||||
}
|
||||
|
||||
void Mixer::playRaw(
|
||||
void MixerImpl::playRaw(
|
||||
SoundType type,
|
||||
SoundHandle *handle,
|
||||
void *sound,
|
||||
|
@ -165,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,
|
||||
|
@ -197,9 +204,14 @@ 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;
|
||||
|
||||
|
@ -217,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()) {
|
||||
|
@ -235,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) {
|
||||
|
@ -245,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
|
||||
|
@ -257,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;
|
||||
|
@ -267,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;
|
||||
|
@ -277,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;
|
||||
|
@ -287,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) {
|
||||
|
@ -296,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) {
|
||||
|
@ -306,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
|
||||
|
@ -317,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)
|
||||
|
@ -325,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)
|
||||
|
@ -333,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)
|
||||
|
@ -347,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
|
||||
|
@ -362,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];
|
||||
|
@ -442,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;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||
*
|
||||
* Residual is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the AUTHORS
|
||||
* 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
|
||||
|
@ -29,11 +29,13 @@
|
|||
#include "common/sys.h"
|
||||
#include "common/mutex.h"
|
||||
|
||||
|
||||
namespace Audio {
|
||||
|
||||
class AudioStream;
|
||||
class Channel;
|
||||
class Mixer;
|
||||
class MixerImpl;
|
||||
|
||||
/**
|
||||
* A SoundHandle instances corresponds to a specific sound
|
||||
|
@ -43,7 +45,7 @@ class Mixer;
|
|||
*/
|
||||
class SoundHandle {
|
||||
friend class Channel;
|
||||
friend class Mixer;
|
||||
friend class MixerImpl;
|
||||
uint32 _val;
|
||||
public:
|
||||
inline SoundHandle() : _val(0xFFFFFFFF) {}
|
||||
|
@ -100,23 +102,9 @@ public:
|
|||
kMaxMixerVolume = 256
|
||||
};
|
||||
|
||||
private:
|
||||
enum {
|
||||
NUM_CHANNELS = 32
|
||||
};
|
||||
|
||||
Common::Mutex _mutex;
|
||||
|
||||
int _volumeForSoundType[4];
|
||||
|
||||
uint32 _handleSeed;
|
||||
Channel *_channels[NUM_CHANNELS];
|
||||
|
||||
bool _mixerReady;
|
||||
|
||||
public:
|
||||
Mixer();
|
||||
~Mixer();
|
||||
Mixer() {}
|
||||
virtual ~Mixer() {}
|
||||
|
||||
|
||||
|
||||
|
@ -127,8 +115,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;
|
||||
|
||||
|
||||
|
||||
|
@ -138,12 +128,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 = 255, int8 balance = 0,
|
||||
uint32 loopStart = 0, uint32 loopEnd = 0);
|
||||
int id = -1, byte volume = kMaxChannelVolume, int8 balance = 0,
|
||||
uint32 loopStart = 0, uint32 loopEnd = 0) = 0;
|
||||
|
||||
/**
|
||||
* Start playing the given audio input stream.
|
||||
|
@ -165,35 +155,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 = 255, int8 balance = 0,
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
@ -203,7 +193,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.
|
||||
|
@ -211,7 +201,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.
|
||||
|
@ -219,7 +209,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;
|
||||
|
||||
|
||||
|
||||
|
@ -229,7 +219,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
|
||||
|
@ -237,7 +227,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.
|
||||
|
@ -245,7 +235,7 @@ public:
|
|||
* @param handle sound to query
|
||||
* @return true if the sound is active
|
||||
*/
|
||||
bool isSoundHandleActive(SoundHandle handle);
|
||||
virtual bool isSoundHandleActive(SoundHandle handle) = 0;
|
||||
|
||||
|
||||
|
||||
|
@ -253,9 +243,9 @@ public:
|
|||
* Set the channel volume for the given handle.
|
||||
*
|
||||
* @param handle the sound to affect
|
||||
* @param volume the new channel volume (0 - 255)
|
||||
* @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.
|
||||
|
@ -264,12 +254,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.
|
||||
|
@ -279,23 +269,23 @@ 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.
|
||||
*
|
||||
* @param type the sound type
|
||||
* @param volume the new global volume, 0-kMaxMixerVolume
|
||||
* @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.
|
||||
*
|
||||
* @param type the sound type
|
||||
* @return the global music volume, 0-kMaxMixerVolume
|
||||
* @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
|
||||
|
@ -303,26 +293,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;
|
||||
};
|
||||
|
||||
|
||||
|
|
134
mixer/mixer_intern.h
Normal file
134
mixer/mixer_intern.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||
*
|
||||
* Residual 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/sound/mixer_intern.h $
|
||||
* $Id: mixer_intern.h 32828 2008-06-28 15:28:29Z fingolfin $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SOUND_MIXER_INTERN_H
|
||||
#define SOUND_MIXER_INTERN_H
|
||||
|
||||
#include "common/sys.h"
|
||||
#include "common/mutex.h"
|
||||
#include "mixer/mixer.h"
|
||||
|
||||
namespace Audio {
|
||||
|
||||
class MixerImpl : public Mixer {
|
||||
private:
|
||||
enum {
|
||||
NUM_CHANNELS = 32
|
||||
};
|
||||
|
||||
Common::Mutex _mutex;
|
||||
|
||||
uint _sampleRate;
|
||||
bool _mixerReady;
|
||||
uint32 _handleSeed;
|
||||
|
||||
int _volumeForSoundType[4];
|
||||
Channel *_channels[NUM_CHANNELS];
|
||||
|
||||
|
||||
public:
|
||||
MixerImpl();
|
||||
~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…
Add table
Add a link
Reference in a new issue