From cb8378065d2831fa1512dfce138cc0039eff98fb Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Tue, 30 Jan 2007 22:19:55 +0000 Subject: - Changed _soundFlags and implemented "compositions" - Changed Snd to be a permanent audiostream, to have better control over stopping, looping and compositions - Some clean-up svn-id: r25292 --- engines/gob/game.cpp | 7 ++ engines/gob/game_v1.cpp | 2 - engines/gob/game_v2.cpp | 8 --- engines/gob/global.cpp | 3 +- engines/gob/global.h | 1 - engines/gob/gob.cpp | 15 ++--- engines/gob/init.cpp | 13 +--- engines/gob/init_v1.cpp | 15 ----- engines/gob/init_v2.cpp | 18 +----- engines/gob/inter_v1.cpp | 2 +- engines/gob/inter_v2.cpp | 11 +++- engines/gob/mult_v2.cpp | 1 - engines/gob/music.cpp | 114 +++++++++++++++------------------ engines/gob/music.h | 37 +++-------- engines/gob/sound.cpp | 163 ++++++++++++++++++++++++++++++++++++----------- engines/gob/sound.h | 41 ++++++++++-- 16 files changed, 245 insertions(+), 206 deletions(-) (limited to 'engines') diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index e239248807..205258d628 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -351,6 +351,13 @@ void Game::freeSoundSlot(int16 slot) { if ((slot < 0) || (slot >= 60) || (_soundSamples[slot] == 0)) return; + if (slot == _vm->_snd->getCompositionSlot()) { + if (_vm->_quitRequested) + _vm->_snd->stopComposition(); + else + _vm->_snd->waitEndPlay(); + } + if (_soundADL[slot]) { if (_vm->_adlib && (_vm->_adlib->getIndex() == slot)) _vm->_adlib->stopPlay(); diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index 7c807aef70..47f5475950 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -579,8 +579,6 @@ int16 Game_v1::checkCollisions(char handleMouse, int16 deltaTime, int16 *pResId, _vm->_draw->animateCursor(-1); _vm->_util->delay(10); - - _vm->_snd->loopSounds(); } } diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index 1669da9e40..f9aa540308 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -92,18 +92,12 @@ void Game_v2::playTot(int16 skipPlay) { _vm->_mult->initAll(); _vm->_mult->zeroMultData(); -/* for (i = 0; i < 50; i++) - _vm->_draw->_spritesArray[i] = 0;*/ - _vm->_draw->_spritesArray[20] = _vm->_draw->_frontSurface; _vm->_draw->_spritesArray[21] = _vm->_draw->_backSurface; _vm->_draw->_cursorSpritesBack = _vm->_draw->_cursorSprites; } else _vm->_inter->initControlVars(0); - for (i = 0; i < 20; i++) - _soundSamples[i] = 0; - _totTextData = 0; _totResourceTable = 0; _imFileData = 0; @@ -661,8 +655,6 @@ int16 Game_v2::checkCollisions(char handleMouse, int16 deltaTime, int16 *pResId, _vm->_draw->animateCursor(-1); _vm->_util->delay(10); - - _vm->_snd->loopSounds(); } } diff --git a/engines/gob/global.cpp b/engines/gob/global.cpp index d78b3eca29..6b2c54ecdd 100644 --- a/engines/gob/global.cpp +++ b/engines/gob/global.cpp @@ -37,8 +37,7 @@ Global::Global(GobEngine *vm) : _vm(vm) { _videoMode = 0; /* Sound */ - _presentSound = 0x8000; /* undefined values */ - _soundFlags = 0x8000; + _soundFlags = 0; _blasterPort = 0; _disableSoundCfg = 0; diff --git a/engines/gob/global.h b/engines/gob/global.h index 4fd5455201..aa1c6d95ca 100644 --- a/engines/gob/global.h +++ b/engines/gob/global.h @@ -80,7 +80,6 @@ public: int16 _disableVideoCfg; - uint16 _presentSound; uint16 _soundFlags; int16 _disableSoundCfg; int16 _blasterPort; diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 82302b3616..90ca277a9e 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -614,14 +614,10 @@ int GobEngine::init() { else error("GobEngine::init(): Unknown version of game engine"); _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; - if (!(_features & Gob::GF_AMIGA) && - (((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) || - (_features & Gob::GF_GOB2))) { - if (_noMusic) - _adlib = new Adlib_Dummy(this); - else - _adlib = new Adlib(this); - } + if (!_noMusic && !(_features & Gob::GF_AMIGA) && + (((_features & Gob::GF_MAC) && (_features & Gob::GF_GOB1)) || + (_features & Gob::GF_GOB2))) + _adlib = new Adlib(this); _vm = this; _system->beginGFXTransaction(); @@ -642,7 +638,7 @@ int GobEngine::init() { _global->_videoMode = 0x13; _global->_useMouse = 1; - _global->_soundFlags = 0; + _global->_soundFlags = MIDI_FLAG | SPEAKER_FLAG | BLASTER_FLAG | ADLIB_FLAG; if (ConfMan.hasKey("language")) _language = Common::parseLanguage(ConfMan.get("language")); @@ -687,7 +683,6 @@ int GobEngine::init() { // 640x480. g_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true); - return 0; } diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index a026354eb2..c093f80851 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -50,18 +50,7 @@ Init::Init(GobEngine *vm) : _vm(vm) { void Init::findBestCfg(void) { _vm->_global->_videoMode = VIDMODE_VGA; _vm->_global->_useMouse = _vm->_global->_mousePresent; - if (_vm->_global->_presentSound & BLASTER_FLAG) - _vm->_global->_soundFlags = BLASTER_FLAG | SPEAKER_FLAG | MIDI_FLAG; - else if (_vm->_global->_presentSound & PROAUDIO_FLAG) - _vm->_global->_soundFlags = PROAUDIO_FLAG | SPEAKER_FLAG | MIDI_FLAG; - else if (_vm->_global->_presentSound & ADLIB_FLAG) - _vm->_global->_soundFlags = ADLIB_FLAG | SPEAKER_FLAG | MIDI_FLAG; - else if (_vm->_global->_presentSound & INTERSOUND_FLAG) - _vm->_global->_soundFlags = INTERSOUND_FLAG | SPEAKER_FLAG; - else if (_vm->_global->_presentSound & SPEAKER_FLAG) - _vm->_global->_soundFlags = SPEAKER_FLAG; - else - _vm->_global->_soundFlags = 0; + _vm->_global->_soundFlags = MIDI_FLAG | SPEAKER_FLAG | BLASTER_FLAG | ADLIB_FLAG; } void Init::cleanup(void) { diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp index 73a09dd34b..c6c7481e22 100644 --- a/engines/gob/init_v1.cpp +++ b/engines/gob/init_v1.cpp @@ -41,20 +41,13 @@ void Init_v1::soundVideo(int32 smallHeap, int16 flag) { error("soundVideo: Video mode 0x%x is not supported!", _vm->_global->_videoMode); - //if ((flag & 4) == 0) - // _vm->_video->findVideo(); - _vm->_global->_mousePresent = 1; _vm->_global->_inVM = 0; - _vm->_global->_presentSound = 0; // FIXME: sound is not supported yet - _vm->_global->_sprAllocated = 0; _vm->_gtimer->enableTimer(); - // _vm->_snd->setResetTimerFlag(debugFlag); // TODO - if (_vm->_global->_videoMode == 0x13) _vm->_global->_colorCount = 256; @@ -66,14 +59,6 @@ void Init_v1::soundVideo(int32 smallHeap, int16 flag) { if (_vm->_global->_videoMode != 0) _vm->_video->initSurfDesc(_vm->_global->_videoMode, 320, 200, PRIMARY_SURFACE); - - if (_vm->_global->_soundFlags & MIDI_FLAG) { - _vm->_global->_soundFlags &= _vm->_global->_presentSound; - if (_vm->_global->_presentSound & ADLIB_FLAG) - _vm->_global->_soundFlags |= MIDI_FLAG; - } else { - _vm->_global->_soundFlags &= _vm->_global->_presentSound; - } } } // End of namespace Gob diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp index 86cc7d7dbb..129f75ebd5 100644 --- a/engines/gob/init_v2.cpp +++ b/engines/gob/init_v2.cpp @@ -45,40 +45,24 @@ void Init_v2::soundVideo(int32 smallHeap, int16 flag) { _vm->_draw->_frontSurface = &_vm->_global->_primarySurfDesc; _vm->_video->initSurfDesc(_vm->_global->_videoMode, _vm->_video->_surfWidth, 200, 0x80); - //if ((flag & 4) == 0) - // _vm->_video->findVideo(); - _vm->_global->_mousePresent = 1; _vm->_global->_inVM = 0; - _vm->_global->_presentSound = 0; // FIXME: sound is not supported yet - _vm->_global->_sprAllocated = 0; _vm->_gtimer->enableTimer(); - // _vm->_snd->setResetTimerFlag(debugFlag); // TODO - - if (_vm->_global->_videoMode == 0x13) + if ((_vm->_global->_videoMode == 0x13) || (_vm->_global->_videoMode == 0x14)) _vm->_global->_colorCount = 256; _vm->_global->_pPaletteDesc = &_vm->_global->_paletteStruct; _vm->_global->_pPaletteDesc->vgaPal = _vm->_draw->_vgaPalette; _vm->_global->_pPaletteDesc->unused1 = _vm->_global->_unusedPalette1; _vm->_global->_pPaletteDesc->unused2 = _vm->_global->_unusedPalette2; -// _vm->_global->_pPrimarySurfDesc = &_vm->_global->_primarySurfDesc; if (_vm->_global->_videoMode != 0) _vm->_video->initSurfDesc(_vm->_global->_videoMode, _vm->_video->_surfWidth, 200, PRIMARY_SURFACE); - - if (_vm->_global->_soundFlags & MIDI_FLAG) { - _vm->_global->_soundFlags &= _vm->_global->_presentSound; - if (_vm->_global->_presentSound & ADLIB_FLAG) - _vm->_global->_soundFlags |= MIDI_FLAG; - } else { - _vm->_global->_soundFlags &= _vm->_global->_presentSound; - } } } // End of namespace Gob diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 408dcd481c..788f9a0f2a 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1205,7 +1205,7 @@ bool Inter_v1::o1_playComposition(char &cmdCount, int16 &counter, int16 &retFlag for (i = 0; i < 50; i++) composition[i] = (int16)VAR_OFFSET(dataVar + i * 4); - _vm->_snd->playComposition(_vm->_game->_soundSamples, composition, freqVal); + _vm->_snd->playComposition(composition, freqVal); return false; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index f605b11720..95e13ff43a 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -1401,7 +1401,16 @@ bool Inter_v2::o2_checkData(char &cmdCount, int16 &counter, int16 &retFlag) { } bool Inter_v2::o2_stopSound(char &cmdCount, int16 &counter, int16 &retFlag) { - _vm->_snd->stopSound(_vm->_parse->parseValExpr()); + int16 expr; + + expr = _vm->_parse->parseValExpr(); + + if (expr < 0) { + if (_vm->_adlib) + _vm->_adlib->stopPlay(); + } else + _vm->_snd->stopSound(expr); + _soundEndTimeKey = 0; return false; } diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 2d53f893f2..c082859204 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -522,7 +522,6 @@ void Mult_v2::playMult(int16 startFrame, int16 endFrame, char checkEscape, stop = doFadeAnim(stop); stop = doSoundAnim(stop, _frame); - _vm->_snd->loopSounds(); if (_frame >= endFrame) stopNoClear = 1; diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp index b074a15602..67608bcd67 100644 --- a/engines/gob/music.cpp +++ b/engines/gob/music.cpp @@ -82,7 +82,6 @@ Adlib::Adlib(GobEngine *vm) : _vm(vm) { _dataSize = 0; _rate = _vm->_mixer->getOutputRate(); _opl = makeAdlibOPL(_rate); - _vm->_mixer->setupPremix(this, Audio::Mixer::kMusicSoundType); _first = true; _ended = false; _playing = false; @@ -92,74 +91,71 @@ Adlib::Adlib(GobEngine *vm) : _vm(vm) { for (i = 0; i < 16; i ++) _pollNotes[i] = 0; - setFreqs(); + + _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle, + this, -1, 255, 0, false, true); } Adlib::~Adlib(void) { + Common::StackLock slock(_mutex); + + _vm->_mixer->stopHandle(_handle); OPLDestroy(_opl); if (_data && _needFree) delete[] _data; - _vm->_mixer->setupPremix(0); } -void Adlib::premixerCall(int16 *buf, uint len) { - _mutex.lock(); - if (!_playing) { - memset(buf, 0, 2 * len * sizeof(int16)); - _mutex.unlock(); - return; +int Adlib::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock slock(_mutex); + int samples; + int render; + + if (!_playing || (numSamples < 0)) { + memset(buffer, 0, numSamples * sizeof(int16)); + return numSamples; } - else { - if (_first) { - memset(buf, 0, 2 * len * sizeof(int16)); + if (_first) { + memset(buffer, 0, numSamples * sizeof(int16)); + pollMusic(); + return numSamples; + } + + samples = numSamples; + while (samples && _playing) { + if (_samplesTillPoll) { + render = (samples > _samplesTillPoll) ? (_samplesTillPoll) : (samples); + samples -= render; + _samplesTillPoll -= render; + YM3812UpdateOne(_opl, buffer, render); + buffer += render; + } else { pollMusic(); - _mutex.unlock(); - return; - } - else { - uint32 render; - int16 *data = buf; - uint datalen = len; - while (datalen && _playing) { - if (_samplesTillPoll) { - render = (datalen > _samplesTillPoll) ? - (_samplesTillPoll) : (datalen); - datalen -= render; - _samplesTillPoll -= render; - YM3812UpdateOne(_opl, data, render); - data += render; - } else { - pollMusic(); - if (_ended) { - memset(data, 0, datalen * sizeof(int16)); - datalen = 0; - } - } + if (_ended) { + memset(buffer, 0, samples * sizeof(int16)); + samples = 0; } } - if (_ended) { - _first = true; - _ended = false; - _playPos = _data + 3 + (_data[1] + 1) * 0x38; - _samplesTillPoll = 0; - if (_repCount == -1) { - reset(); - setVoices(); - } else if (_repCount > 0) { - _repCount--; - reset(); - setVoices(); - } - else - _playing = false; - } - // Convert mono data to stereo - for (int i = (len - 1); i >= 0; i--) { - buf[2 * i] = buf[2 * i + 1] = buf[i]; + } + + if (_ended) { + _first = true; + _ended = false; + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + _samplesTillPoll = 0; + if (_repCount == -1) { + reset(); + setVoices(); + } else if (_repCount > 0) { + _repCount--; + reset(); + setVoices(); } + else + _playing = false; } - _mutex.unlock(); + + return numSamples; } void Adlib::writeOPL(byte reg, byte val) { @@ -194,6 +190,7 @@ void Adlib::setFreqs(void) { } void Adlib::reset() { + _first = true; OPLResetChip(_opl); _samplesTillPoll = 0; @@ -356,21 +353,12 @@ void Adlib::pollMusic(void) { setVolume(channel, *(_playPos++)); setKey(channel, note, true, false); break; - case 0x10: - warning("GOB2 Stub! ADL command 0x10"); - break; - case 0x50: - warning("GOB2 Stub! ADL command 0x50"); - break; // Note on case 0x90: note = *(_playPos++); _pollNotes[channel] = note; setKey(channel, note, true, false); break; - case 0x60: - warning("GOB2 Stub! ADL command 0x60"); - break; // Last note off case 0x80: note = _pollNotes[channel]; diff --git a/engines/gob/music.h b/engines/gob/music.h index fdc2e1cbb8..89d3d7acf4 100644 --- a/engines/gob/music.h +++ b/engines/gob/music.h @@ -39,7 +39,7 @@ class GobEngine; class Adlib : public Audio::AudioStream { public: Adlib(GobEngine *vm); - virtual ~Adlib(); + ~Adlib(); void lock() { _mutex.lock(); } void unlock() { _mutex.unlock(); } @@ -50,9 +50,8 @@ public: virtual void startPlay(void) { if (_data) _playing = true; } virtual void stopPlay(void) { - _mutex.lock(); + Common::StackLock slock(_mutex); _playing = false; - _mutex.unlock(); } virtual void playTrack(const char *trackname); virtual void playBgMusic(void); @@ -61,12 +60,10 @@ public: virtual void unload(void); // AudioStream API - int readBuffer(int16 *buffer, const int numSamples) { - premixerCall(buffer, numSamples / 2); - return numSamples; - } - bool isStereo() const { return true; } - bool endOfData() const { return false; } + int readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return false; } + bool endOfData() const { return !_playing; } + bool endOfStream() const { return false; } int getRate() const { return _rate; } protected: @@ -74,6 +71,7 @@ protected: static const char *_trackFiles[]; static const unsigned char _operators[]; static const unsigned char _volRegNums []; + Audio::SoundHandle _handle; FM_OPL *_opl; int _index; byte *_data; @@ -86,7 +84,7 @@ protected: byte _notLin[11]; bool _notOn[11]; byte _pollNotes[16]; - uint32 _samplesTillPoll; + int _samplesTillPoll; int32 _repCount; bool _playing; bool _first; @@ -95,7 +93,6 @@ protected: Common::Mutex _mutex; GobEngine *_vm; - void premixerCall(int16 *buf, uint len); void writeOPL(byte reg, byte val); void setFreqs(void); void reset(void); @@ -106,24 +103,6 @@ protected: void pollMusic(void); }; -/** - * A dummy class for the "null" sound driver - */ -class Adlib_Dummy: public Adlib { -public: - Adlib_Dummy(GobEngine *vm) : Adlib(vm) {} - - virtual void startPlay(void) {}; - virtual void stopPlay(void) {}; - virtual void playTrack(const char *trackname) {}; - virtual void playBgAdlib(void) {}; - virtual bool load(const char *filename) { return true; } - virtual void load(byte *data, int index=-1) {} - virtual void unload(void) {}; - - virtual ~Adlib_Dummy() {}; -}; - } // End of namespace Gob #endif diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp index aa7724a294..500a2e5295 100644 --- a/engines/gob/sound.cpp +++ b/engines/gob/sound.cpp @@ -61,24 +61,21 @@ int Snd::SquareWaveStream::readBuffer(int16 *buffer, const int numSamples) { } Snd::Snd(GobEngine *vm) : _vm(vm) { - //CleanupFuncPtr cleanupFunc;// = &snd_cleanupFuncCallback(); _cleanupFunc = 0; - for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) - _loopingSounds[i] = NULL; _playingSound = 0; -} -void Snd::loopSounds(void) { - for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) { - SoundDesc *snd = _loopingSounds[i]; - if (snd && !_vm->_mixer->isSoundHandleActive(snd->handle)) { - if (snd->repCount-- > 0) { - _vm->_mixer->playRaw(&snd->handle, snd->data, snd->size, snd->frequency, 0); - } else { - _loopingSounds[i] = NULL; - } - } - } + _rate = _vm->_mixer->getOutputRate(); + _end = true; + _data = 0; + _length = 0; + _freq = 0; + _repCount = 0; + _offset = 0.0; + + _compositionPos = -1; + + _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, + this, -1, 255, 0, false, true); } void Snd::setBlasterPort(int16 port) {return;} @@ -94,28 +91,54 @@ void Snd::speakerOff(void) { _vm->_mixer->stopHandle(_speakerHandle); } -void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { - if (frequency <= 0) - frequency = sndDesc->frequency; +int8 Snd::getCompositionSlot(void) { + if (_compositionPos == -1) + return -1; - for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) - _loopingSounds[i] = 0; - _vm->_mixer->stopHandle(sndDesc->handle); + return _composition[_compositionPos]; +} - _vm->_mixer->playRaw(&sndDesc->handle, sndDesc->data, sndDesc->size, frequency, 0); +void Snd::stopSound(int16 arg) +{ + Common::StackLock slock(_mutex); - sndDesc->repCount = repCount - 1; - sndDesc->frequency = frequency; + _data = 0; + _end = true; +} + +void Snd::waitEndPlay(void) { + while (!_end) + _vm->_util->longDelay(200); + stopSound(0); +} + +void Snd::stopComposition(void) { + if (_compositionPos != -1) { + stopSound(0); + _compositionPos = -1; + } +} + +void Snd::nextCompositionPos(void) { + int8 slot; - if (repCount > 1) { - for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) { - if (!_loopingSounds[i]) { - _loopingSounds[i] = sndDesc; - return; - } + while ((++_compositionPos < 50) && ((slot = _composition[_compositionPos]) != -1)) { + if ((slot >= 0) && (slot <= 60) && (_vm->_game->_soundSamples[slot] != 0) + && !(_vm->_game->_soundTypes[slot] & 8)) { + setSample(_vm->_game->_soundSamples[slot], 1, 0); + return; } - warning("Looping sounds list is full"); } + _compositionPos = -1; +} + +void Snd::playComposition(int16 *composition, int16 freqVal) { + waitEndPlay(); + stopComposition(); + + for (int i = 0; i < 50; i++) + _composition[i] = composition[i]; + nextCompositionPos(); } void Snd::writeAdlib(int16 port, int16 data) { @@ -133,12 +156,8 @@ Snd::SoundDesc *Snd::loadSoundData(const char *path) { } void Snd::freeSoundDesc(Snd::SoundDesc *sndDesc, bool freedata) { - _vm->_mixer->stopHandle(sndDesc->handle); - - for (int i = 0; i < ARRAYSIZE(_loopingSounds); i++) { - if (_loopingSounds[i] == sndDesc) - _loopingSounds[i] = NULL; - } + if (sndDesc == _curSoundDesc) + stopSound(0); if (freedata) { delete[] sndDesc->data; @@ -146,7 +165,75 @@ void Snd::freeSoundDesc(Snd::SoundDesc *sndDesc, bool freedata) { delete sndDesc; } -} // End of namespace Gob +void Snd::setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { + if (frequency <= 0) + frequency = sndDesc->frequency; + _curSoundDesc = sndDesc; + sndDesc->repCount = repCount - 1; + sndDesc->frequency = frequency; + + _data = (int8 *) sndDesc->data; + _length = sndDesc->size; + _freq = frequency; + _ratio = ((double) _freq) / _rate; + _offset = 0.0; + _frac = 0; + _cur = 0; + _last = 0; + _repCount = repCount; + _end = false; + _playingSound = 0; +} + +void Snd::playSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency) { + Common::StackLock slock(_mutex); + if (!_end) + return; + + setSample(sndDesc, repCount, frequency); + if (!_vm->_mixer->isSoundHandleActive(_handle)) + _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, + this, -1, 255, 0, false, true); +} + +void Snd::checkEndSample(void) { + if (_compositionPos != -1) + nextCompositionPos(); + else if ((_repCount == -1) || (--_repCount > 0)) { + _offset = 0.0; + _end = false; + _playingSound = 0; + } else { + _end = true; + _playingSound = 0; + } +} + +int Snd::readBuffer(int16 *buffer, const int numSamples) { + memset(buffer, 0, numSamples); + + for (int i = 0; i < numSamples; i++) { + Common::StackLock slock(_mutex); + + if (!_data) + return i; + if (_end || (_offset >= _length)) + checkEndSample(); + if (_end) + return i; + + *buffer++ = (int) (_last + (_cur - _last) * _frac); + _frac += _ratio; + while (_frac > 1) { + _frac -= 1; + _last = _cur; + _cur = _data[(int) _offset] << 8; + } + _offset += _ratio; + } + return numSamples; +} +} // End of namespace Gob diff --git a/engines/gob/sound.h b/engines/gob/sound.h index 5b32569ac1..dd059b44ee 100644 --- a/engines/gob/sound.h +++ b/engines/gob/sound.h @@ -28,7 +28,7 @@ namespace Gob { -class Snd { +class Snd : public Audio::AudioStream { public: struct SoundDesc { Audio::SoundHandle handle; @@ -45,7 +45,6 @@ public: typedef void (*CleanupFuncPtr) (int16); - SoundDesc *_loopingSounds[10]; // Should be enough char _playingSound; CleanupFuncPtr _cleanupFunc; @@ -53,16 +52,23 @@ public: void speakerOn(int16 frequency, int32 length); void speakerOff(void); SoundDesc *loadSoundData(const char *path); - void stopSound(int16 arg){return;} - void loopSounds(void); + void stopSound(int16 arg); void playSample(SoundDesc *sndDesc, int16 repCount, int16 frequency); - void playComposition(Snd::SoundDesc ** samples, int16 *composit, int16 freqVal) {;} - void waitEndPlay(void) {;} + void playComposition(int16 *composition, int16 freqVal); + void stopComposition(void); + int8 getCompositionSlot(void); + void waitEndPlay(void); // This deletes sndDesc and stops playing the sample. // If freedata is set, it also delete[]s the sample data. void freeSoundDesc(SoundDesc *sndDesc, bool freedata=true); + int readBuffer(int16 *buffer, const int numSamples); + bool isStereo() const { return false; } + bool endOfData() const { return _end; } + bool endOfStream() const { return false; } + int getRate() const { return _rate; } + protected: // TODO: This is a very primitive square wave generator. The only thing is // has in common with the PC speaker is that it sounds terrible. @@ -91,6 +97,26 @@ protected: SquareWaveStream _speakerStream; Audio::SoundHandle _speakerHandle; + Audio::SoundHandle *_activeHandle; + Audio::SoundHandle _compositionHandle; + int16 _composition[50]; + int8 _compositionPos; + + Audio::SoundHandle _handle; + Common::Mutex _mutex; + SoundDesc *_curSoundDesc; + bool _end; + int8 *_data; + uint32 _length; + uint32 _rate; + int32 _freq; + int32 _repCount; + double _offset; + double _ratio; + double _frac; + int16 _cur; + int16 _last; + GobEngine *_vm; void cleanupFuncCallback() {;} @@ -101,6 +127,9 @@ protected: void writeAdlib(int16 port, int16 data); void setBlasterPort(int16 port); void setResetTimerFlag(char flag){return;} + void setSample(Snd::SoundDesc *sndDesc, int16 repCount, int16 frequency); + void checkEndSample(void); + void nextCompositionPos(void); }; } // End of namespace Gob -- cgit v1.2.3