From 220d6ce82f478966db6a4760b2288750212880b9 Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Thu, 8 May 2008 00:47:23 +0000 Subject: Restructured sound code svn-id: r31937 --- engines/gob/cdrom.cpp | 269 --------------------- engines/gob/cdrom.h | 64 ----- engines/gob/dataio.cpp | 1 - engines/gob/detection.cpp | 1 - engines/gob/draw.cpp | 1 - engines/gob/draw_v1.cpp | 5 +- engines/gob/draw_v2.cpp | 1 - engines/gob/driver_vga.cpp | 1 - engines/gob/game.cpp | 23 +- engines/gob/game.h | 10 - engines/gob/game_v1.cpp | 17 +- engines/gob/game_v2.cpp | 14 +- engines/gob/gob.cpp | 62 +++-- engines/gob/gob.h | 35 ++- engines/gob/goblin.cpp | 14 +- engines/gob/goblin.h | 2 +- engines/gob/goblin_v1.cpp | 13 +- engines/gob/goblin_v2.cpp | 1 - engines/gob/init.cpp | 16 +- engines/gob/init_v1.cpp | 1 - engines/gob/init_v2.cpp | 5 +- engines/gob/inter.cpp | 5 +- engines/gob/inter_bargon.cpp | 17 +- engines/gob/inter_v1.cpp | 78 +++--- engines/gob/inter_v2.cpp | 108 +++------ engines/gob/inter_v4.cpp | 15 +- engines/gob/map.cpp | 2 - engines/gob/map_v1.cpp | 7 +- engines/gob/map_v2.cpp | 1 - engines/gob/module.mk | 10 +- engines/gob/mult.cpp | 24 +- engines/gob/mult_v1.cpp | 1 - engines/gob/mult_v2.cpp | 1 - engines/gob/music.cpp | 483 ------------------------------------- engines/gob/music.h | 106 -------- engines/gob/parse.cpp | 1 - engines/gob/parse_v1.cpp | 1 - engines/gob/parse_v2.cpp | 1 - engines/gob/scenery.cpp | 1 - engines/gob/scenery_v1.cpp | 9 +- engines/gob/scenery_v2.cpp | 1 - engines/gob/sound.cpp | 374 ---------------------------- engines/gob/sound.h | 172 ------------- engines/gob/sound/adlib.cpp | 457 +++++++++++++++++++++++++++++++++++ engines/gob/sound/adlib.h | 108 +++++++++ engines/gob/sound/cdrom.cpp | 201 +++++++++++++++ engines/gob/sound/cdrom.h | 68 ++++++ engines/gob/sound/infogrames.cpp | 103 ++++++++ engines/gob/sound/infogrames.h | 60 +++++ engines/gob/sound/pcspeaker.cpp | 55 +++++ engines/gob/sound/pcspeaker.h | 52 ++++ engines/gob/sound/sound.cpp | 461 +++++++++++++++++++++++++++++++++++ engines/gob/sound/sound.h | 135 +++++++++++ engines/gob/sound/soundblaster.cpp | 260 ++++++++++++++++++++ engines/gob/sound/soundblaster.h | 116 +++++++++ engines/gob/sound/sounddesc.cpp | 116 +++++++++ engines/gob/sound/sounddesc.h | 85 +++++++ engines/gob/util.cpp | 5 +- engines/gob/video.cpp | 1 - engines/gob/video_v1.cpp | 1 - engines/gob/video_v2.cpp | 1 - 61 files changed, 2482 insertions(+), 1777 deletions(-) delete mode 100644 engines/gob/cdrom.cpp delete mode 100644 engines/gob/cdrom.h delete mode 100644 engines/gob/music.cpp delete mode 100644 engines/gob/music.h delete mode 100644 engines/gob/sound.cpp delete mode 100644 engines/gob/sound.h create mode 100644 engines/gob/sound/adlib.cpp create mode 100644 engines/gob/sound/adlib.h create mode 100644 engines/gob/sound/cdrom.cpp create mode 100644 engines/gob/sound/cdrom.h create mode 100644 engines/gob/sound/infogrames.cpp create mode 100644 engines/gob/sound/infogrames.h create mode 100644 engines/gob/sound/pcspeaker.cpp create mode 100644 engines/gob/sound/pcspeaker.h create mode 100644 engines/gob/sound/sound.cpp create mode 100644 engines/gob/sound/sound.h create mode 100644 engines/gob/sound/soundblaster.cpp create mode 100644 engines/gob/sound/soundblaster.h create mode 100644 engines/gob/sound/sounddesc.cpp create mode 100644 engines/gob/sound/sounddesc.h (limited to 'engines') diff --git a/engines/gob/cdrom.cpp b/engines/gob/cdrom.cpp deleted file mode 100644 index c037d24bbe..0000000000 --- a/engines/gob/cdrom.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* 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$ - * - */ - - -#include "common/endian.h" -#include "sound/audiocd.h" - -#include "gob/gob.h" -#include "gob/cdrom.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/game.h" - -namespace Gob { - -CDROM::CDROM(GobEngine *vm) : _vm(vm) { - _cdPlaying = false; - - _LICbuffer = 0; - for (int i = 0; i < 16; i++) - _curTrack[i] = 0; - _numTracks = 0; - _trackStop = 0; - _startTime = 0; -} - -void CDROM::readLIC(const char *fname) { - char tmp[80]; - int handle; - uint16 version, startChunk, pos; - - freeLICbuffer(); - - *_curTrack = 0; - - strncpy0(tmp, fname, 79); - - handle = _vm->_dataIO->openData(tmp); - - if (handle == -1) - return; - - _vm->_dataIO->closeData(handle); - - _vm->_dataIO->getUnpackedData(tmp); - - handle = _vm->_dataIO->openData(tmp); - DataStream *stream = _vm->_dataIO->openAsStream(handle, true); - - version = stream->readUint16LE(); - startChunk = stream->readUint16LE(); - _numTracks = stream->readUint16LE(); - - if (version != 3) - error("%s: Unknown version %d", fname, version); - - stream->seek(50); - - for (int i = 0; i < startChunk; i++) { - pos = stream->readUint16LE(); - - if (!pos) - break; - - stream->skip(pos); - } - - _LICbuffer = new byte[_numTracks * 22]; - stream->read(_LICbuffer, _numTracks * 22); - - delete stream; -} - -void CDROM::freeLICbuffer() { - delete[] _LICbuffer; - _LICbuffer = 0; -} - -void CDROM::playBgMusic() { - static const char *tracks[][2] = { - {"avt00.tot", "mine"}, - {"avt001.tot", "nuit"}, - {"avt002.tot", "campagne"}, - {"avt003.tot", "extsor1"}, - {"avt004.tot", "interieure"}, - {"avt005.tot", "zombie"}, - {"avt006.tot", "zombie"}, - {"avt007.tot", "campagne"}, - {"avt008.tot", "campagne"}, - {"avt009.tot", "extsor1"}, - {"avt010.tot", "extsor1"}, - {"avt011.tot", "interieure"}, - {"avt012.tot", "zombie"}, - {"avt014.tot", "nuit"}, - {"avt015.tot", "interieure"}, - {"avt016.tot", "statue"}, - {"avt017.tot", "zombie"}, - {"avt018.tot", "statue"}, - {"avt019.tot", "mine"}, - {"avt020.tot", "statue"}, - {"avt021.tot", "mine"}, - {"avt022.tot", "zombie"} - }; - - for (int i = 0; i < ARRAYSIZE(tracks); i++) - if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { - startTrack(tracks[i][1]); - break; - } -} - -void CDROM::playMultMusic() { - static const char *tracks[][6] = { - {"avt005.tot", "fra1", "all1", "ang1", "esp1", "ita1"}, - {"avt006.tot", "fra2", "all2", "ang2", "esp2", "ita2"}, - {"avt012.tot", "fra3", "all3", "ang3", "esp3", "ita3"}, - {"avt016.tot", "fra4", "all4", "ang4", "esp4", "ita4"}, - {"avt019.tot", "fra5", "all5", "ang5", "esp5", "ita5"}, - {"avt022.tot", "fra6", "all6", "ang6", "esp6", "ita6"} - }; - - // Default to "ang?" for other languages (including EN_USA) - int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2; - for (int i = 0; i < ARRAYSIZE(tracks); i++) - if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { - startTrack(tracks[i][language + 1]); - break; - } -} - -void CDROM::startTrack(const char *trackName) { - if (!_LICbuffer) - return; - - debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackName); - - byte *matchPtr = getTrackBuffer(trackName); - if (!matchPtr) { - warning("Track \"%s\" not found", trackName); - return; - } - - strncpy0(_curTrack, trackName, 15); - - stopPlaying(); - _curTrackBuffer = matchPtr; - - while (getTrackPos() >= 0); - - uint32 start = READ_LE_UINT32(matchPtr + 12); - uint32 end = READ_LE_UINT32(matchPtr + 16); - - play(start, end); - - _startTime = _vm->_util->getTimeKey(); - _trackStop = _startTime + (end - start + 1 + 150) * 40 / 3; -} - -void CDROM::play(uint32 from, uint32 to) { - // play from sector [from] to sector [to] - // - // format is HSG: - // HSG encodes frame information into a double word: - // minute multiplied by 4500, plus second multiplied by 75, - // plus frame, minus 150 - debugC(1, kDebugMusic, "CDROM::play(%d, %d)", from, to); - - AudioCD.play(1, 1, from, to - from + 1); - _cdPlaying = true; -} - -int32 CDROM::getTrackPos(const char *keyTrack) { - byte *keyBuffer = getTrackBuffer(keyTrack); - uint32 curPos = (_vm->_util->getTimeKey() - _startTime) * 3 / 40; - - if (_cdPlaying && (_vm->_util->getTimeKey() < _trackStop)) { - if (keyBuffer && _curTrackBuffer && (keyBuffer != _curTrackBuffer)) { - uint32 kStart = READ_LE_UINT32(keyBuffer + 12); - uint32 kEnd = READ_LE_UINT32(keyBuffer + 16); - uint32 cStart = READ_LE_UINT32(_curTrackBuffer + 12); - uint32 cEnd = READ_LE_UINT32(_curTrackBuffer + 16); - - if ((kStart >= cStart) && (kEnd <= cEnd)) { - if ((kStart - cStart) > curPos) - return -2; - if ((kEnd - cStart) < curPos) - return -1; - } - } - - return curPos; - } else - return -1; -} - -const char *CDROM::getCurTrack() { - return _curTrack; -} - -void CDROM::stopPlaying() { - stop(); - - while (getTrackPos() != -1); -} - -void CDROM::stop() { - debugC(1, kDebugMusic, "CDROM::stop()"); - - _curTrackBuffer = 0; - AudioCD.stop(); - _cdPlaying = false; -} - -void CDROM::testCD(int trySubst, const char *label) { - if (!trySubst) { - error("CDROM track substitution is not supported"); - return; - } - - _LICbuffer = 0; - _cdPlaying = false; - - // Original checked CD label here - // but will skip it as it will require OSystem extensions of direct - // CD secor reading -} - -byte *CDROM::getTrackBuffer(const char *trackName) { - if (!_LICbuffer || !trackName) - return 0; - - byte *matchPtr = 0; - byte *curPtr = _LICbuffer; - - for (int i = 0; i < _numTracks; i++) { - if (!scumm_stricmp((char *) curPtr, trackName)) { - matchPtr = curPtr; - break; - } - curPtr += 22; - } - - return matchPtr; -} - -} // End of namespace Gob diff --git a/engines/gob/cdrom.h b/engines/gob/cdrom.h deleted file mode 100644 index 25490de5dc..0000000000 --- a/engines/gob/cdrom.h +++ /dev/null @@ -1,64 +0,0 @@ -/* 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 GOB_CDROM_H -#define GOB_CDROM_H - -namespace Gob { - -class CDROM { -public: - bool _cdPlaying; - - void readLIC(const char *fname); - void freeLICbuffer(); - - void startTrack(const char *trackName); - void playBgMusic(); - void playMultMusic(); - void play(uint32 from, uint32 to); - int32 getTrackPos(const char *keyTrack = 0); - const char *getCurTrack(); - void stopPlaying(); - void stop(); - void testCD(int trySubst, const char *label); - - CDROM(GobEngine *vm); - -protected: - byte *_LICbuffer; - byte *_curTrackBuffer; - char _curTrack[16]; - uint16 _numTracks; - uint32 _trackStop; - uint32 _startTime; - GobEngine *_vm; - - byte *getTrackBuffer(const char *trackName); -}; - -} // End of namespace Gob - -#endif // GOB_CDROM_H diff --git a/engines/gob/dataio.cpp b/engines/gob/dataio.cpp index 1fb43e96bb..dd5d30bd39 100644 --- a/engines/gob/dataio.cpp +++ b/engines/gob/dataio.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 7637605dcd..cbc9272e80 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -23,7 +23,6 @@ * */ - #include "base/plugins.h" #include "common/advancedDetector.h" diff --git a/engines/gob/draw.cpp b/engines/gob/draw.cpp index 2a4732954c..8a7de9bdaa 100644 --- a/engines/gob/draw.cpp +++ b/engines/gob/draw.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/draw_v1.cpp b/engines/gob/draw_v1.cpp index 959a064b7d..9a78769d41 100644 --- a/engines/gob/draw_v1.cpp +++ b/engines/gob/draw_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/cursorman.h" @@ -31,9 +30,9 @@ #include "gob/draw.h" #include "gob/global.h" #include "gob/util.h" -#include "gob/cdrom.h" #include "gob/game.h" #include "gob/scenery.h" +#include "gob/sound/sound.h" namespace Gob { @@ -170,7 +169,7 @@ void Draw_v1::printTotText(int16 id) { int16 spriteRight, spriteBottom; char buf[20]; - _vm->_cdrom->playMultMusic(); + _vm->_sound->cdPlayMultMusic(); if (!_vm->_game->_totTextData || !_vm->_game->_totTextData->dataPtr) return; diff --git a/engines/gob/draw_v2.cpp b/engines/gob/draw_v2.cpp index 88d30b8e8a..8c429b1c1e 100644 --- a/engines/gob/draw_v2.cpp +++ b/engines/gob/draw_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/cursorman.h" diff --git a/engines/gob/driver_vga.cpp b/engines/gob/driver_vga.cpp index 08235f16e2..c4861ca146 100644 --- a/engines/gob/driver_vga.cpp +++ b/engines/gob/driver_vga.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/primitives.h" diff --git a/engines/gob/game.cpp b/engines/gob/game.cpp index 666f46fde1..9bdcae567d 100644 --- a/engines/gob/game.cpp +++ b/engines/gob/game.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -35,7 +34,7 @@ #include "gob/parse.h" #include "gob/draw.h" #include "gob/mult.h" -#include "gob/music.h" +#include "gob/sound/sound.h" namespace Gob { @@ -60,9 +59,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { _collStackElemSizes[i] = 0; } - _infIns = 0; - _infogrames = 0; - _curTotFile[0] = 0; _curExtFile[0] = 0; _totToLoad[0] = 0; @@ -105,10 +101,6 @@ Game::Game(GobEngine *vm) : _vm(vm) { } Game::~Game() { - delete _infIns; - - for (int i = 0; i < 60; i++) - _soundSamples[i].free(); } byte *Game::loadExtData(int16 itemId, int16 *pResWidth, @@ -295,16 +287,7 @@ void Game::freeSoundSlot(int16 slot) { if (slot == -1) slot = _vm->_parse->parseValExpr(); - if ((slot < 0) || (slot >= 60) || _soundSamples[slot].empty()) - return; - - SoundDesc &sample = _soundSamples[slot]; - - if (sample.getType() == SOUND_ADL) - if (_vm->_adlib && (_vm->_adlib->getIndex() == slot)) - _vm->_adlib->stopPlay(); - - _vm->_snd->freeSample(sample); + _vm->_sound->sampleFree(_vm->_sound->sampleGetBySlot(slot)); } void Game::evaluateScroll(int16 x, int16 y) { @@ -380,7 +363,7 @@ int16 Game::checkKeys(int16 *pMouseX, int16 *pMouseY, if ((_vm->_inter->_soundEndTimeKey != 0) && (_vm->_util->getTimeKey() >= _vm->_inter->_soundEndTimeKey)) { - _vm->_snd->stopSound(_vm->_inter->_soundStopVal); + _vm->_sound->blasterStop(_vm->_inter->_soundStopVal); _vm->_inter->_soundEndTimeKey = 0; } diff --git a/engines/gob/game.h b/engines/gob/game.h index 5cf5e1bea6..bca55cd4dc 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -26,10 +26,6 @@ #ifndef GOB_GAME_H #define GOB_GAME_H -#include "sound/mods/infogrames.h" - -#include "gob/sound.h" - namespace Gob { class Game { @@ -119,12 +115,6 @@ public: int16 _extHandle; - SoundDesc _soundSamples[60]; - - Audio::Infogrames::Instruments *_infIns; - Audio::Infogrames *_infogrames; - Audio::SoundHandle _infHandle; - char _totToLoad[20]; int32 _startTimeKey; diff --git a/engines/gob/game_v1.cpp b/engines/gob/game_v1.cpp index e9e37a027b..435decd9f2 100644 --- a/engines/gob/game_v1.cpp +++ b/engines/gob/game_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" @@ -32,15 +31,13 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/music.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/inter.h" #include "gob/mult.h" #include "gob/video.h" #include "gob/parse.h" -#include "gob/sound.h" #include "gob/scenery.h" +#include "gob/sound/sound.h" namespace Gob { @@ -74,11 +71,11 @@ void Game_v1::playTot(int16 skipPlay) { _vm->_draw->_fontToSprite[i].height = -1; } - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); - } else - _vm->_cdrom->stopPlaying(); + if (_vm->getPlatform() == Common::kPlatformMacintosh) + _vm->_sound->adlibStop(); + else + _vm->_sound->cdStop(); + _vm->_draw->animateCursor(4); _vm->_inter->initControlVars(1); _vm->_mult->initAll(); @@ -229,7 +226,7 @@ void Game_v1::playTot(int16 skipPlay) { for (int i = 0; i < SPRITES_COUNT; i++) _vm->_draw->freeSprite(i); - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); for (int i = 0; i < 20; i++) freeSoundSlot(i); diff --git a/engines/gob/game_v2.cpp b/engines/gob/game_v2.cpp index 45542541e3..ff444f4a69 100644 --- a/engines/gob/game_v2.cpp +++ b/engines/gob/game_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" @@ -38,9 +37,9 @@ #include "gob/mult.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -265,11 +264,14 @@ void Game_v2::playTot(int16 skipPlay) { if (skipPlay != -1) { _vm->_goblin->freeObjects(); - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); + + for (int i = 0; i < Sound::kSoundsCount; i++) { + SoundDesc *sound = _vm->_sound->sampleGetBySlot(i); - for (int i = 0; i < 60; i++) - if (_soundSamples[i].getType() == SOUND_SND) - _vm->_snd->freeSample(_soundSamples[i]); + if (sound && (sound->getType() == SOUND_SND)) + _vm->_sound->sampleFree(sound); + } } _vm->_vidPlayer->primaryClose(); diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index 863665357b..951f331cbe 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/events.h" @@ -37,18 +36,16 @@ #include "gob/util.h" #include "gob/dataio.h" #include "gob/game.h" -#include "gob/sound.h" +#include "gob/sound/sound.h" #include "gob/init.h" #include "gob/inter.h" #include "gob/draw.h" -#include "gob/cdrom.h" #include "gob/goblin.h" #include "gob/map.h" #include "gob/mult.h" #include "gob/palanim.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/music.h" #include "gob/videoplayer.h" #include "gob/saveload.h" @@ -71,13 +68,12 @@ const Common::Language GobEngine::_gobToScummVMLang[] = { GobEngine::GobEngine(OSystem *syst) : Engine(syst) { _vm = this; - _snd = 0; _adlib = 0; _mult = 0; - _game = 0; _global = 0; _cdrom = 0; - _dataIO = 0; _goblin = 0; _vidPlayer = 0; - _init = 0; _inter = 0; _map = 0; - _palAnim = 0; _parse = 0; _scenery = 0; - _draw = 0; _util = 0; _video = 0; - _saveLoad = 0; + _sound = 0; _mult = 0; _game = 0; + _global = 0; _dataIO = 0; _goblin = 0; + _vidPlayer = 0; _init = 0; _inter = 0; + _map = 0; _palAnim = 0; _parse = 0; + _scenery = 0; _draw = 0; _util = 0; + _video = 0; _saveLoad = 0; // Setup mixer _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); @@ -118,6 +114,12 @@ void GobEngine::shutdown() { _quitRequested = true; } +const char *GobEngine::getLangDesc(int16 language) const { + if ((language < 0) || (language > 8)) + language = 2; + return Common::getLanguageDescription(_gobToScummVMLang[language]); +} + void GobEngine::validateLanguage() { if (_vm->_global->_languageWanted != _vm->_global->_language) { warning("Your game version doesn't support the requested language %s", @@ -140,6 +142,30 @@ void GobEngine::validateVideoMode(int16 videoMode) { error("Video mode 0x%X is not supported!", videoMode); } +Common::Platform GobEngine::getPlatform() const { + return _platform; +} + +GameType GobEngine::getGameType() const { + return _gameType; +} + +bool GobEngine::isCD() const { + return (_features & kFeaturesCD) != 0; +} + +bool GobEngine::isEGA() const { + return (_features & kFeaturesEGA) != 0; +} + +bool GobEngine::is640() const { + return (_features & kFeatures640) != 0; +} + +bool GobEngine::hasAdlib() const { + return (_features & kFeaturesAdlib) != 0; +} + int GobEngine::init() { if (!initGameParts()) { GUIErrorMessage("GobEngine::init(): Unknown version of game engine"); @@ -220,7 +246,8 @@ int GobEngine::init() { } bool GobEngine::initGameParts() { - _adlib = 0; + _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; + _saveLoad = 0; _global = new Global(this); @@ -228,8 +255,7 @@ bool GobEngine::initGameParts() { _dataIO = new DataIO(this); _palAnim = new PalAnim(this); _vidPlayer = new VideoPlayer(this); - _cdrom = new CDROM(this); - _snd = new Snd(this); + _sound = new Sound(this); switch (_gameType) { case kGameTypeGob1: @@ -336,10 +362,6 @@ bool GobEngine::initGameParts() { break; } - _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; - if (!_noMusic && hasAdlib()) - _adlib = new Adlib(this); - if (is640()) { _video->_surfWidth = _width = 640; _video->_surfHeight = _video->_splitHeight1 = _height = 480; @@ -360,12 +382,9 @@ bool GobEngine::initGameParts() { } void GobEngine::deinitGameParts() { - delete _snd; _snd = 0; - delete _adlib; _adlib = 0; delete _mult; _mult = 0; delete _game; _game = 0; delete _global; _global = 0; - delete _cdrom; _cdrom = 0; delete _dataIO; _dataIO = 0; delete _goblin; _goblin = 0; delete _vidPlayer; _vidPlayer = 0; @@ -379,6 +398,7 @@ void GobEngine::deinitGameParts() { delete _util; _util = 0; delete _video; _video = 0; delete _saveLoad; _saveLoad = 0; + delete _sound; _sound = 0; } } // End of namespace Gob diff --git a/engines/gob/gob.h b/engines/gob/gob.h index e23e917a7c..e1d75bd2a4 100644 --- a/engines/gob/gob.h +++ b/engines/gob/gob.h @@ -35,11 +35,10 @@ namespace Gob { class Game; -class Snd; +class Sound; class Video; class Global; class Draw; -class CDROM; class DataIO; class Goblin; class VideoPlayer; @@ -52,7 +51,6 @@ class Parse; class Scenery; class Util; class SaveLoad; -class Adlib; #define VARP(offs) (_vm->_global->_inter_variables + (offs)) #define WRITE_VARO_UINT32(offs, val) _vm->_global->writeVar(offs, (uint32) (val)) @@ -171,9 +169,13 @@ private: struct GOBGameDescription; class GobEngine : public Engine { -protected: +private: GobEngine *_vm; + GameType _gameType; + int32 _features; + Common::Platform _platform; + int go(); int init(); @@ -185,11 +187,7 @@ public: Common::RandomSource _rnd; - GameType _gameType; - int32 _features; Common::Language _language; - Common::Platform _platform; - uint16 _width; uint16 _height; uint8 _mode; @@ -204,10 +202,9 @@ public: Util *_util; DataIO *_dataIO; Game *_game; - Snd *_snd; + Sound *_sound; Video *_video; Draw *_draw; - CDROM *_cdrom; Goblin *_goblin; Init *_init; Map *_map; @@ -217,24 +214,20 @@ public: Scenery *_scenery; Inter *_inter; SaveLoad *_saveLoad; - Adlib *_adlib; VideoPlayer *_vidPlayer; void shutdown(); - const char *getLangDesc(int16 language) { - if ((language < 0) || (language > 8)) - language = 2; - return Common::getLanguageDescription(_gobToScummVMLang[language]); - } + const char *getLangDesc(int16 language) const; void validateLanguage(); void validateVideoMode(int16 videoMode); - GameType getGameType() { return _gameType; } - bool isCD() { return (_features & kFeaturesCD) != 0; } - bool isEGA() { return (_features & kFeaturesEGA) != 0; } - bool is640() { return (_features & kFeatures640) != 0; } - bool hasAdlib() { return (_features & kFeaturesAdlib) != 0; } + Common::Platform getPlatform() const; + GameType getGameType() const; + bool isCD() const; + bool isEGA() const; + bool is640() const; + bool hasAdlib() const; GobEngine(OSystem *syst); virtual ~GobEngine(); diff --git a/engines/gob/goblin.cpp b/engines/gob/goblin.cpp index f97bd14fed..d3857e2066 100644 --- a/engines/gob/goblin.cpp +++ b/engines/gob/goblin.cpp @@ -32,7 +32,7 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/scenery.h" -#include "gob/sound.h" +#include "gob/sound/sound.h" namespace Gob { @@ -255,8 +255,8 @@ void Goblin::sortByOrder(Util::List *list) { void Goblin::playSound(SoundDesc &snd, int16 repCount, int16 freq) { if (!snd.empty()) { - _vm->_snd->stopSound(0); - _vm->_snd->playSample(snd, repCount, freq); + _vm->_sound->blasterStop(0); + _vm->_sound->blasterPlay(&snd, repCount, freq); } } @@ -1216,7 +1216,7 @@ void Goblin::zeroObjects(void) { _objects[i] = 0; for (int i = 0; i < 16; i++) - _vm->_snd->freeSample(_soundData[i]); + _vm->_sound->sampleFree(&_soundData[i]); } void Goblin::freeAllObjects(void) { @@ -1717,12 +1717,12 @@ void Goblin::playSounds(Mult::Mult_Object *obj) { if (!speaker) { sndSlot = obj->goblinStates[animData->state][i].sndItem; - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); if (sndSlot < _soundSlotsCount) - _vm->_snd->playSample(_vm->_game->_soundSamples[_soundSlots[sndSlot] & 0x7FFF], + _vm->_sound->blasterPlay(_vm->_sound->sampleGetBySlot(_soundSlots[sndSlot] & 0x7FFF), repCount, frequency); } else - _vm->_snd->speakerOn(frequency, repCount * 10); + _vm->_sound->speakerOn(frequency, repCount * 10); } } diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index f7ac4aa549..3fd8a9f93b 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -27,8 +27,8 @@ #define GOB_GOBLIN_H #include "gob/util.h" -#include "gob/sound.h" #include "gob/mult.h" +#include "gob/sound/sounddesc.h" namespace Gob { diff --git a/engines/gob/goblin_v1.cpp b/engines/gob/goblin_v1.cpp index f7bdbf10a5..6ac086767b 100644 --- a/engines/gob/goblin_v1.cpp +++ b/engines/gob/goblin_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -32,7 +31,7 @@ #include "gob/map.h" #include "gob/mult.h" #include "gob/scenery.h" -#include "gob/sound.h" +#include "gob/sound/sound.h" namespace Gob { @@ -48,7 +47,7 @@ void Goblin_v1::freeObjects(void) { int16 col; for (int i = 0; i < 16; i++) - _vm->_snd->freeSample(_soundData[i]); + _vm->_sound->sampleFree(&_soundData[i]); for (int i = 0; i < 4; i++) { if (_goblins[i] == 0) @@ -488,19 +487,19 @@ void Goblin_v1::moveAdvance(Mult::Mult_Object *obj, Gob_Object *gobDesc, if ((gobDesc->state >= 0) && (gobDesc->state < 10) && (gobDesc->stateMach == gobDesc->realStateMach) && ((gobDesc->curFrame == 3) || (gobDesc->curFrame == 6))) { - _vm->_snd->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5); + _vm->_sound->speakerOn(10 * _vm->_util->getRandom(3) + 50, 5); } if ((_currentGoblin == 0) && (gobDesc->stateMach == gobDesc->realStateMach) && ((gobDesc->state == 10) || (gobDesc->state == 11)) && (gobDesc->curFrame == 9)) { - _vm->_snd->stopSound(0); + _vm->_sound->blasterStop(0); if (_itemIndInPocket != -1) - _vm->_snd->playSample(_soundData[14], 1, 9000); + _vm->_sound->blasterPlay(&_soundData[14], 1, 9000); else - _vm->_snd->playSample(_soundData[14], 1, 5000); + _vm->_sound->blasterPlay(&_soundData[14], 1, 5000); } if (_boreCounter++ == 120) { diff --git a/engines/gob/goblin_v2.cpp b/engines/gob/goblin_v2.cpp index c9e155ad08..93c4c74ecc 100644 --- a/engines/gob/goblin_v2.cpp +++ b/engines/gob/goblin_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/init.cpp b/engines/gob/init.cpp index 4d184c53d3..b1e31b34c2 100644 --- a/engines/gob/init.cpp +++ b/engines/gob/init.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -31,13 +30,12 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/palanim.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -51,8 +49,8 @@ void Init::cleanup(void) { _vm->_video->freeDriver(); _vm->_global->_primarySurfDesc = 0; - _vm->_snd->speakerOff(); - _vm->_snd->stopSound(0); + _vm->_sound->speakerOff(); + _vm->_sound->blasterStop(0); _vm->_dataIO->closeDataFile(); } @@ -169,8 +167,8 @@ void Init::initGame(const char *totName) { strcpy(_vm->_game->_curTotFile, buffer); - _vm->_cdrom->testCD(1, "GOB"); - _vm->_cdrom->readLIC("gob.lic"); + _vm->_sound->cdTest(1, "GOB"); + _vm->_sound->cdLoadLIC("gob.lic"); // Search for a Coktel logo animation or image to display imdHandle = _vm->_dataIO->openData("coktel.imd"); @@ -213,8 +211,8 @@ void Init::initGame(const char *totName) { _vm->_game->start(); - _vm->_cdrom->stopPlaying(); - _vm->_cdrom->freeLICbuffer(); + _vm->_sound->cdStop(); + _vm->_sound->cdUnloadLIC(); delete[] _vm->_global->_inter_variables; delete[] _vm->_global->_inter_variablesSizes; diff --git a/engines/gob/init_v1.cpp b/engines/gob/init_v1.cpp index 8065c4dc8c..90456f927c 100644 --- a/engines/gob/init_v1.cpp +++ b/engines/gob/init_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/init_v2.cpp b/engines/gob/init_v2.cpp index bb29f4e8fd..b468c15c25 100644 --- a/engines/gob/init_v2.cpp +++ b/engines/gob/init_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -50,8 +49,8 @@ void Init_v2::initVideo() { _vm->_global->_inVM = 0; _vm->_global->_colorCount = 16; - if (((_vm->_platform == Common::kPlatformPC) || - (_vm->_platform == Common::kPlatformMacintosh)) && + if (((_vm->getPlatform() == Common::kPlatformPC) || + (_vm->getPlatform() == Common::kPlatformMacintosh)) && ((_vm->_global->_videoMode == 0x13) || (_vm->_global->_videoMode == 0x14))) _vm->_global->_colorCount = 256; diff --git a/engines/gob/inter.cpp b/engines/gob/inter.cpp index de3ac4b1f5..dd3fdf3684 100644 --- a/engines/gob/inter.cpp +++ b/engines/gob/inter.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -34,7 +33,7 @@ #include "gob/game.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" +#include "gob/sound/sound.h" #include // FIXME: for Inter::renewTimeInVars() @@ -154,7 +153,7 @@ void Inter::storeKey(int16 key) { WRITE_VAR(12, _vm->_util->getTimeKey() - _vm->_game->_startTimeKey); storeMouse(); - WRITE_VAR(1, _vm->_snd->_playingSound); + WRITE_VAR(1, _vm->_sound->blasterPlayingSound()); if (key == 0x4800) key = 0x0B; diff --git a/engines/gob/inter_bargon.cpp b/engines/gob/inter_bargon.cpp index 702950d539..d493fb00d3 100644 --- a/engines/gob/inter_bargon.cpp +++ b/engines/gob/inter_bargon.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -34,9 +33,9 @@ #include "gob/draw.h" #include "gob/game.h" #include "gob/palanim.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -768,9 +767,9 @@ void Inter_Bargon::oBargon_intro2(OpGobParams ¶ms) { return; for (i = 0; i < 4; i++) - _vm->_snd->loadSample(samples[i], sndFiles[i]); - _vm->_snd->playComposition(comp, 0, samples, 4); - _vm->_snd->waitEndPlay(true, false); + _vm->_sound->sampleLoad(&samples[i], sndFiles[i]); + _vm->_sound->blasterPlayComposition(comp, 0, samples, 4); + _vm->_sound->blasterWaitEndPlay(true, false); _vm->_palAnim->fade(0, 0, 0); _vm->_video->clearSurf(_vm->_draw->_frontSurface); } @@ -787,12 +786,12 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { static const char *palFiles[] = {"2ou2.clt", "2ou3.clt", "2ou4.clt", "2ou5.clt"}; for (int i = 0; i < 2; i++) - _vm->_snd->loadSample(samples[i], sndFiles[i]); + _vm->_sound->sampleLoad(&samples[i], sndFiles[i]); for (int i = 0; i < 4; i++) palettes[i] = _vm->_dataIO->getData(palFiles[i]); palBak = _vm->_global->_pPaletteDesc->vgaPal; - _vm->_snd->playComposition(comp, 0, samples, 2); + _vm->_sound->blasterPlayComposition(comp, 0, samples, 2); for (int i = 0; i < 20; i++) { for (int j = 0; j < 4; j++) { _vm->_global->_pPaletteDesc->vgaPal = (Video::Color *) palettes[j]; @@ -801,7 +800,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { } if ((_vm->_game->checkKeys(&mouseX, &mouseY, &buttons, 0) == 0x11B) || _vm->_quitRequested) { - _vm->_snd->stopSound(10); + _vm->_sound->blasterStop(10); _vm->_palAnim->fade(0, -2, 0); _vm->_video->clearSurf(_vm->_draw->_frontSurface); memset((char *) _vm->_draw->_vgaPalette, 0, 768); @@ -811,7 +810,7 @@ void Inter_Bargon::oBargon_intro3(OpGobParams ¶ms) { break; } } - _vm->_snd->waitEndPlay(false, false); + _vm->_sound->blasterWaitEndPlay(false, false); _vm->_global->_pPaletteDesc->vgaPal = palBak; for (int i = 0; i < 4; i++) diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 9707a628b4..a809a44b40 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/file.h" @@ -32,8 +31,6 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/music.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/goblin.h" @@ -43,8 +40,8 @@ #include "gob/palanim.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" +#include "gob/sound/sound.h" namespace Gob { @@ -1071,12 +1068,8 @@ void Inter_v1::o1_loadCurLayer() { void Inter_v1::o1_playCDTrack() { evalExpr(0); - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->playTrack(_vm->_global->_inter_resStr); - } else - // Used in gob1 CD - _vm->_cdrom->startTrack(_vm->_global->_inter_resStr); + _vm->_sound->adlibPlayBgMusic(); // Mac version + _vm->_sound->cdPlay(_vm->_global->_inter_resStr); // PC CD version } void Inter_v1::o1_getCDTrackPos() { @@ -1088,19 +1081,15 @@ void Inter_v1::o1_getCDTrackPos() { _vm->_util->longDelay(1); - int pos = _vm->_cdrom->getTrackPos(); + int pos = _vm->_sound->cdGetTrackPos(); if (pos == -1) pos = 32767; WRITE_VAR(5, pos); } void Inter_v1::o1_stopCD() { - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); - } else - // Used in gob1 CD - _vm->_cdrom->stopPlaying(); + _vm->_sound->adlibStop(); // Mac version + _vm->_sound->cdStop(); // PC CD version } void Inter_v1::o1_loadFontToSprite() { @@ -1685,7 +1674,7 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { break; default: - _vm->_snd->speakerOnUpdate(cmd); + _vm->_sound->speakerOnUpdate(cmd); if (cmd < 20) { _vm->_util->delay(cmd); _noBusyWait = true; @@ -1759,12 +1748,12 @@ bool Inter_v1::o1_renewTimeInVars(OpFuncParams ¶ms) { } bool Inter_v1::o1_speakerOn(OpFuncParams ¶ms) { - _vm->_snd->speakerOn(_vm->_parse->parseValExpr(), -1); + _vm->_sound->speakerOn(_vm->_parse->parseValExpr(), -1); return false; } bool Inter_v1::o1_speakerOff(OpFuncParams ¶ms) { - _vm->_snd->speakerOff(); + _vm->_sound->speakerOff(); return false; } @@ -1978,10 +1967,10 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { repCount = _vm->_parse->parseValExpr(); frequency = _vm->_parse->parseValExpr(); - SoundDesc &sample = _vm->_game->_soundSamples[index]; + SoundDesc *sample = _vm->_sound->sampleGetBySlot(index); _soundEndTimeKey = 0; - if (sample.empty()) + if (!sample || sample->empty()) return false; if (repCount < 0) { @@ -1991,31 +1980,28 @@ bool Inter_v1::o1_playSound(OpFuncParams ¶ms) { repCount = -repCount; _soundEndTimeKey = _vm->_util->getTimeKey(); - freq2 = frequency ? frequency : sample._frequency; + freq2 = frequency ? frequency : sample->_frequency; endRep = MAX(repCount - 1, 1); - _soundStopVal = sample.calcFadeOutLength(freq2); - _soundEndTimeKey += sample.calcLength(endRep, freq2, true); + _soundStopVal = sample->calcFadeOutLength(freq2); + _soundEndTimeKey += sample->calcLength(endRep, freq2, true); } - if (sample.getType() == SOUND_ADL) { - if (_vm->_adlib) { - _vm->_adlib->load(sample.getData(), sample.size(), index); - _vm->_adlib->setRepeating(repCount - 1); - _vm->_adlib->startPlay(); - } + if (sample->getType() == SOUND_ADL) { + _vm->_sound->adlibLoad(sample->getData(), sample->size(), index); + _vm->_sound->adlibSetRepeating(repCount - 1); + _vm->_sound->adlibPlay(); } else { - _vm->_snd->stopSound(0); - _vm->_snd->playSample(sample, repCount - 1, frequency); + _vm->_sound->blasterStop(0); + _vm->_sound->blasterPlay(sample, repCount - 1, frequency); } return false; } bool Inter_v1::o1_stopSound(OpFuncParams ¶ms) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); - _vm->_snd->stopSound(_vm->_parse->parseValExpr()); + _vm->_sound->adlibStop(); + _vm->_sound->blasterStop(_vm->_parse->parseValExpr()); _soundEndTimeKey = 0; return false; @@ -2032,7 +2018,7 @@ bool Inter_v1::o1_freeSoundSlot(OpFuncParams ¶ms) { } bool Inter_v1::o1_waitEndPlay(OpFuncParams ¶ms) { - _vm->_snd->waitEndPlay(); + _vm->_sound->blasterWaitEndPlay(); return false; } @@ -2046,7 +2032,7 @@ bool Inter_v1::o1_playComposition(OpFuncParams ¶ms) { for (int i = 0; i < 50; i++) composition[i] = (int16) VAR_OFFSET(dataVar + i * 4); - _vm->_snd->playComposition(composition, freqVal); + _vm->_sound->blasterPlayComposition(composition, freqVal); return false; } @@ -2803,11 +2789,9 @@ void Inter_v1::o1_animateObjects(OpGobParams ¶ms) { void Inter_v1::o1_drawObjects(OpGobParams ¶ms) { _vm->_goblin->drawObjects(); - if (_vm->_platform == Common::kPlatformMacintosh) { - if (_vm->_adlib) - _vm->_adlib->playBgMusic(); - } else if (_vm->_cdrom->getTrackPos() == -1) - _vm->_cdrom->playBgMusic(); + _vm->_sound->adlibPlayBgMusic(); // Mac version + if (_vm->_sound->cdGetTrackPos() == -1) + _vm->_sound->cdPlayBgMusic(); // PC CD version } void Inter_v1::o1_loadMap(OpGobParams ¶ms) { @@ -2993,9 +2977,11 @@ int16 Inter_v1::loadSound(int16 slot) { dataSize = (uint32) ((int32) totSize); } - if (dataPtr) - _vm->_game->_soundSamples[slot].load(SOUND_SND, source, - dataPtr, dataSize); + if (dataPtr) { + SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); + if (sample) + sample->load(SOUND_SND, source, dataPtr, dataSize); + } return 0; } diff --git a/engines/gob/inter_v2.cpp b/engines/gob/inter_v2.cpp index 2442e4dcf2..36f33e6553 100644 --- a/engines/gob/inter_v2.cpp +++ b/engines/gob/inter_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "sound/mixer.h" #include "sound/mods/infogrames.h" @@ -33,8 +32,6 @@ #include "gob/global.h" #include "gob/util.h" #include "gob/dataio.h" -#include "gob/music.h" -#include "gob/cdrom.h" #include "gob/draw.h" #include "gob/game.h" #include "gob/goblin.h" @@ -42,10 +39,10 @@ #include "gob/mult.h" #include "gob/parse.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/saveload.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -1086,16 +1083,16 @@ void Inter_v2::o2_playCDTrack() { _vm->_draw->blitInvalidated(); evalExpr(0); - _vm->_cdrom->startTrack(_vm->_global->_inter_resStr); + _vm->_sound->cdPlay(_vm->_global->_inter_resStr); } void Inter_v2::o2_waitCDTrackEnd() { - while (_vm->_cdrom->getTrackPos() >= 0) + while (_vm->_sound->cdGetTrackPos() >= 0) _vm->_util->longDelay(1); } void Inter_v2::o2_stopCD() { - _vm->_cdrom->stopPlaying(); + _vm->_sound->cdStop(); } void Inter_v2::o2_readLIC() { @@ -1105,11 +1102,11 @@ void Inter_v2::o2_readLIC() { strncpy0(path, _vm->_global->_inter_resStr, 35); strcat(path, ".LIC"); - _vm->_cdrom->readLIC(path); + _vm->_sound->cdLoadLIC(path); } void Inter_v2::o2_freeLIC() { - _vm->_cdrom->freeLICbuffer(); + _vm->_sound->cdUnloadLIC(); } void Inter_v2::o2_getCDTrackPos() { @@ -1121,8 +1118,8 @@ void Inter_v2::o2_getCDTrackPos() { varPos = _vm->_parse->parseVarIndex(); varName = _vm->_parse->parseVarIndex(); - WRITE_VAR_OFFSET(varPos, _vm->_cdrom->getTrackPos(GET_VARO_STR(varName))); - WRITE_VARO_STR(varName, _vm->_cdrom->getCurTrack()); + WRITE_VAR_OFFSET(varPos, _vm->_sound->cdGetTrackPos(GET_VARO_STR(varName))); + WRITE_VARO_STR(varName, _vm->_sound->cdGetCurrentTrack()); } void Inter_v2::o2_loadFontToSprite() { @@ -1883,10 +1880,9 @@ bool Inter_v2::o2_stopSound(OpFuncParams ¶ms) { expr = _vm->_parse->parseValExpr(); if (expr < 0) { - if (_vm->_adlib) - _vm->_adlib->stopPlay(); + _vm->_sound->adlibStop(); } else - _vm->_snd->stopSound(expr); + _vm->_sound->blasterStop(expr); _soundEndTimeKey = 0; return false; @@ -2009,7 +2005,7 @@ bool Inter_v2::o2_readData(OpFuncParams ¶ms) { WRITE_VAR(59, stream->readUint32LE()); // The scripts in some versions divide through 256^3 then, // effectively doing a LE->BE conversion - if ((_vm->_platform != Common::kPlatformPC) && (VAR(59) < 256)) + if ((_vm->getPlatform() != Common::kPlatformPC) && (VAR(59) < 256)) WRITE_VAR(59, SWAP_BYTES_32(VAR(59))); } else retSize = stream->read(buf, size); @@ -2054,29 +2050,11 @@ void Inter_v2::o2_loadInfogramesIns(OpGobParams ¶ms) { varName = load16(); - if (_vm->_noMusic) - return; - strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".INS"); - debugC(1, kDebugMusic, "Loading Infogrames instrument file \"%s\"", - fileName); - - if (_vm->_game->_infogrames) { - _vm->_mixer->stopHandle(_vm->_game->_infHandle); - delete _vm->_game->_infogrames; - _vm->_game->_infogrames = 0; - } + debugC(1, kDebugMusic, "Loading Infogrames instrument file \"%s\"", fileName); - if (_vm->_game->_infIns) - delete _vm->_game->_infIns; - - _vm->_game->_infIns = new Audio::Infogrames::Instruments; - if (!_vm->_game->_infIns->load(fileName)) { - warning("Couldn't load instruments file"); - delete _vm->_game->_infIns; - _vm->_game->_infIns = 0; - } + _vm->_sound->infogramesLoadInstruments(fileName); } void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { @@ -2085,58 +2063,24 @@ void Inter_v2::o2_playInfogrames(OpGobParams ¶ms) { varName = load16(); - if (_vm->_noMusic) - return; - strncpy0(fileName, GET_VAR_STR(varName), 15); strcat(fileName, ".DUM"); debugC(1, kDebugMusic, "Playing Infogrames music file \"%s\"", fileName); - if (!_vm->_game->_infIns) { - _vm->_game->_infIns = new Audio::Infogrames::Instruments; - - if (!_vm->_game->_infIns->load("i1.ins")) { - warning("Couldn't load instruments file"); - delete _vm->_game->_infIns; - _vm->_game->_infIns = 0; - } - } - - if (_vm->_game->_infIns) { - _vm->_mixer->stopHandle(_vm->_game->_infHandle); - delete _vm->_game->_infogrames; - _vm->_game->_infogrames = - new Audio::Infogrames(*_vm->_game->_infIns, true, - _vm->_mixer->getOutputRate(), - _vm->_mixer->getOutputRate() / 75); - - if (!_vm->_game->_infogrames->load(fileName)) { - warning("Couldn't load infogrames music"); - delete _vm->_game->_infogrames; - _vm->_game->_infogrames = 0; - } else - _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_vm->_game->_infHandle, _vm->_game->_infogrames, - -1, 255, 0, false); - } + _vm->_sound->infogramesLoadSong(fileName); + _vm->_sound->infogramesPlay(); } void Inter_v2::o2_startInfogrames(OpGobParams ¶ms) { load16(); - if (_vm->_game->_infogrames && - !_vm->_mixer->isSoundHandleActive(_vm->_game->_infHandle)) { - _vm->_game->_infogrames->restart(); - _vm->_mixer->playInputStream(Audio::Mixer::kMusicSoundType, - &_vm->_game->_infHandle, _vm->_game->_infogrames, - -1, 255, 0, false); - } + _vm->_sound->infogramesPlay(); } void Inter_v2::o2_stopInfogrames(OpGobParams ¶ms) { load16(); - _vm->_mixer->stopHandle(_vm->_game->_infHandle); + _vm->_sound->infogramesStop(); } void Inter_v2::o2_handleGoblins(OpGobParams ¶ms) { @@ -2172,15 +2116,15 @@ int16 Inter_v2::loadSound(int16 search) { } else { id = load16(); - for (slot = 0; slot < 60; slot++) - if (_vm->_game->_soundSamples[slot].isId(id)) { + for (slot = 0; slot < Sound::kSoundsCount; slot++) + if (_vm->_sound->sampleGetBySlot(slot)->isId(id)) { slotIdMask = 0x8000; break; } - if (slot == 60) { - for (slot = 59; slot >= 0; slot--) { - if (_vm->_game->_soundSamples[slot].empty()) + if (slot == Sound::kSoundsCount) { + for (slot = (Sound::kSoundsCount - 1); slot >= 0; slot--) { + if (_vm->_sound->sampleGetBySlot(slot)->empty()) break; } @@ -2192,7 +2136,9 @@ int16 Inter_v2::loadSound(int16 search) { } } - _vm->_game->freeSoundSlot(slot); + SoundDesc *sample = _vm->_sound->sampleGetBySlot(slot); + + _vm->_sound->sampleFree(sample, true, slot); if (id == -1) { char sndfile[14]; @@ -2224,8 +2170,8 @@ int16 Inter_v2::loadSound(int16 search) { } if (dataPtr) { - _vm->_game->_soundSamples[slot].load(type, source, dataPtr, dataSize); - _vm->_game->_soundSamples[slot]._id = id; + sample->load(type, source, dataPtr, dataSize); + sample->_id = id; } return slot | slotIdMask; diff --git a/engines/gob/inter_v4.cpp b/engines/gob/inter_v4.cpp index b24e54ffbd..6ed05af690 100644 --- a/engines/gob/inter_v4.cpp +++ b/engines/gob/inter_v4.cpp @@ -640,8 +640,9 @@ void Inter_v4::setupOpcodes() { } void Inter_v4::executeDrawOpcode(byte i) { - debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s)", - i, i, getOpcodeDrawDesc(i)); + debugC(1, kDebugDrawOp, "opcodeDraw %d [0x%X] (%s) - %s, %ld", + i, i, getOpcodeDrawDesc(i), + _vm->_game->_curTotFile, _vm->_global->_inter_execPtr - _vm->_game->_totFileData); OpcodeDrawProcV4 op = _opcodesDrawV4[i].proc; @@ -652,8 +653,9 @@ void Inter_v4::executeDrawOpcode(byte i) { } bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { - debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s)", - i, j, i, j, getOpcodeFuncDesc(i, j)); + debugC(1, kDebugFuncOp, "opcodeFunc %d.%d [0x%X.0x%X] (%s) - %s, %ld", + i, j, i, j, getOpcodeFuncDesc(i, j), + _vm->_game->_curTotFile, _vm->_global->_inter_execPtr - _vm->_game->_totFileData); if ((i > 4) || (j > 15)) { warning("unimplemented opcodeFunc: %d.%d", i, j); @@ -671,8 +673,9 @@ bool Inter_v4::executeFuncOpcode(byte i, byte j, OpFuncParams ¶ms) { } void Inter_v4::executeGoblinOpcode(int i, OpGobParams ¶ms) { - debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s)", - i, i, getOpcodeGoblinDesc(i)); + debugC(1, kDebugGobOp, "opcodeGoblin %d [0x%X] (%s) - %s, %ld", + i, i, getOpcodeGoblinDesc(i), + _vm->_game->_curTotFile, _vm->_global->_inter_execPtr - _vm->_game->_totFileData); OpcodeGoblinProcV4 op = NULL; diff --git a/engines/gob/map.cpp b/engines/gob/map.cpp index cd8f9e3758..75867aaa6c 100644 --- a/engines/gob/map.cpp +++ b/engines/gob/map.cpp @@ -23,8 +23,6 @@ * */ - - #include "gob/gob.h" #include "gob/map.h" #include "gob/goblin.h" diff --git a/engines/gob/map_v1.cpp b/engines/gob/map_v1.cpp index c4b68fad85..4ac99d2465 100644 --- a/engines/gob/map_v1.cpp +++ b/engines/gob/map_v1.cpp @@ -23,15 +23,14 @@ * */ - #include "common/stream.h" #include "gob/gob.h" #include "gob/map.h" #include "gob/dataio.h" #include "gob/goblin.h" -#include "gob/sound.h" #include "gob/mult.h" +#include "gob/sound/sound.h" namespace Gob { @@ -160,7 +159,7 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) { strcpy(sndNames[i], buf); } - _vm->_snd->loadSample(_vm->_goblin->_soundData[14], "diamant1.snd"); + _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[14], "diamant1.snd"); for (int i = 0; i < count; i++) { handle = _vm->_dataIO->openData(sndNames[i]); @@ -168,7 +167,7 @@ void Map_v1::loadSounds(Common::SeekableReadStream &data) { continue; _vm->_dataIO->closeData(handle); - _vm->_snd->loadSample(_vm->_goblin->_soundData[i], sndNames[i]); + _vm->_sound->sampleLoad(&_vm->_goblin->_soundData[i], sndNames[i]); } } diff --git a/engines/gob/map_v2.cpp b/engines/gob/map_v2.cpp index 2c383f5bb2..668b4d2e97 100644 --- a/engines/gob/map_v2.cpp +++ b/engines/gob/map_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/stream.h" #include "gob/gob.h" diff --git a/engines/gob/module.mk b/engines/gob/module.mk index aa2a235327..4ff9bdf920 100644 --- a/engines/gob/module.mk +++ b/engines/gob/module.mk @@ -1,7 +1,13 @@ MODULE := engines/gob MODULE_OBJS := \ - cdrom.o \ + sound/sound.o \ + sound/sounddesc.o \ + sound/pcspeaker.o \ + sound/adlib.o \ + sound/infogrames.o \ + sound/soundblaster.o \ + sound/cdrom.o \ dataio.o \ detection.o \ draw.o \ @@ -38,7 +44,6 @@ MODULE_OBJS := \ mult.o \ mult_v1.o \ mult_v2.o \ - music.o \ palanim.o \ parse.o \ parse_v1.o \ @@ -49,7 +54,6 @@ MODULE_OBJS := \ scenery.o \ scenery_v1.o \ scenery_v2.o \ - sound.o \ util.o \ video.o \ video_v1.o \ diff --git a/engines/gob/mult.cpp b/engines/gob/mult.cpp index 70b6d33136..bc9fe4dc11 100644 --- a/engines/gob/mult.cpp +++ b/engines/gob/mult.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" @@ -34,9 +33,9 @@ #include "gob/game.h" #include "gob/palanim.h" #include "gob/scenery.h" -#include "gob/sound.h" #include "gob/video.h" #include "gob/videoplayer.h" +#include "gob/sound/sound.h" namespace Gob { @@ -188,7 +187,7 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, if (_frame >= endFrame) stopNoClear = true; - if (_vm->_snd->_playingSound) + if (_vm->_sound->blasterPlayingSound()) stop = false; _vm->_util->processInput(); @@ -225,8 +224,8 @@ void Mult::playMult(int16 startFrame, int16 endFrame, char checkEscape, _animDataAllocated = false; } - if (_vm->_snd->_playingSound) - _vm->_snd->stopSound(10); + if (_vm->_sound->blasterPlayingSound()) + _vm->_sound->blasterStop(10); WRITE_VAR(57, (uint32) -1); } else @@ -415,21 +414,24 @@ void Mult::doSoundAnim(bool &stop, int16 frame) { if (sndKey->cmd != -1) { if ((sndKey->cmd == 1) || (sndKey->cmd == 4)) { - SoundDesc &sample = _vm->_game->_soundSamples[sndKey->soundIndex]; + SoundDesc *sample = _vm->_sound->sampleGetBySlot(sndKey->soundIndex); - _vm->_snd->stopSound(0); - if (!sample.empty()) - _vm->_snd->playSample(sample, sndKey->repCount, + _vm->_sound->blasterStop(0); + if (sample && !sample->empty()) + _vm->_sound->blasterPlay(sample, sndKey->repCount, sndKey->freq, sndKey->fadeLength); } } else { - if (_vm->_snd->_playingSound) - _vm->_snd->stopSound(sndKey->fadeLength); + if (_vm->_sound->blasterPlayingSound()) + _vm->_sound->blasterStop(sndKey->fadeLength); } } } void Mult::clearObjectVideos() { + if (!_objects) + return; + for (int i = 0; i < _objCount; i++) if (_objects[i].videoSlot > 0) _vm->_vidPlayer->slotClose(_objects[i].videoSlot - 1); diff --git a/engines/gob/mult_v1.cpp b/engines/gob/mult_v1.cpp index 78071f1dd8..22683437e7 100644 --- a/engines/gob/mult_v1.cpp +++ b/engines/gob/mult_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" diff --git a/engines/gob/mult_v2.cpp b/engines/gob/mult_v2.cpp index 5ff0612497..3b561837ee 100644 --- a/engines/gob/mult_v2.cpp +++ b/engines/gob/mult_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp deleted file mode 100644 index 7be046c02a..0000000000 --- a/engines/gob/music.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/* 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$ - * - */ - -#include "common/file.h" - -#include "common/endian.h" - -#include "gob/gob.h" -#include "gob/music.h" -#include "gob/game.h" -#include "gob/util.h" - -namespace Gob { - -const char *Adlib::_tracks[][2] = { - {"avt00.tot", "mine"}, - {"avt001.tot", "nuit"}, - {"avt002.tot", "campagne"}, - {"avt003.tot", "extsor1"}, - {"avt004.tot", "interieure"}, - {"avt005.tot", "zombie"}, - {"avt006.tot", "zombie"}, - {"avt007.tot", "campagne"}, - {"avt008.tot", "campagne"}, - {"avt009.tot", "extsor1"}, - {"avt010.tot", "extsor1"}, - {"avt011.tot", "interieure"}, - {"avt012.tot", "zombie"}, - {"avt014.tot", "nuit"}, - {"avt015.tot", "interieure"}, - {"avt016.tot", "statue"}, - {"avt017.tot", "zombie"}, - {"avt018.tot", "statue"}, - {"avt019.tot", "mine"}, - {"avt020.tot", "statue"}, - {"avt021.tot", "mine"}, - {"avt022.tot", "zombie"} -}; - -const char *Adlib::_trackFiles[] = { -// "musmac1.adl", // TODO: This track isn't played correctly at all yet - "musmac2.adl", - "musmac3.adl", - "musmac4.adl", - "musmac5.adl", - "musmac6.adl" -}; - -const unsigned char Adlib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18}; -const unsigned char Adlib::_volRegNums[] = { - 3, 4, 5, - 11, 12, 13, - 19, 20, 21 -}; - -Adlib::Adlib(GobEngine *vm) : _vm(vm) { - int i; - - _index = -1; - _data = 0; - _playPos = 0; - _dataSize = 0; - _rate = _vm->_mixer->getOutputRate(); - _opl = makeAdlibOPL(_rate); - _first = true; - _ended = false; - _playing = false; - _needFree = false; - _repCount = -1; - _samplesTillPoll = 0; - - 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() { - Common::StackLock slock(_mutex); - - _vm->_mixer->stopHandle(_handle); - OPLDestroy(_opl); - if (_data && _needFree) - delete[] _data; -} - -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; - } - 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(); - 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; - } - - return numSamples; -} - -void Adlib::writeOPL(byte reg, byte val) { - debugC(6, kDebugMusic, "writeOPL(%02X, %02X)", reg, val); - OPLWriteReg(_opl, reg, val); -} - -void Adlib::setFreqs() { - byte lin; - byte col; - long val = 0; - - // Run through the 11 channels - for (lin = 0; lin < 11; lin ++) { - _notes[lin] = 0; - _notCol[lin] = 0; - _notLin[lin] = 0; - _notOn[lin] = false; - } - - // Run through the 25 lines - for (lin = 0; lin < 25; lin ++) { - // Run through the 12 columns - for (col = 0; col < 12; col ++) { - if (!col) - val = (((0x2710L + lin * 0x18) * 0xCB78 / 0x3D090) << 0xE) * - 9 / 0x1B503; - _freqs[lin][col] = (short)((val + 4) >> 3); - val = val * 0x6A / 0x64; - } - } -} - -void Adlib::reset() { - _first = true; - OPLResetChip(_opl); - _samplesTillPoll = 0; - - setFreqs(); - // Set frequencies and octave to 0; notes off - for (int i = 0; i < 9; i++) { - writeOPL(0xA0 | i, 0); - writeOPL(0xB0 | i, 0); - writeOPL(0xE0 | _operators[i] , 0); - writeOPL(0xE0 | _operators[i] + 3, 0); - } - - // Authorize the control of the waveformes - writeOPL(0x01, 0x20); -} - -void Adlib::setVoices() { - // Definitions of the 9 instruments - for (int i = 0; i < 9; i++) - setVoice(i, i, true); -} - -void Adlib::setVoice(byte voice, byte instr, bool set) { - int i; - int j; - uint16 strct[27]; - byte channel; - byte *dataPtr; - - // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 - // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 - for (i = 0; i < 2; i++) { - dataPtr = _data + 3 + instr * 0x38 + i * 0x1A; - for (j = 0; j < 27; j++) { - strct[j] = READ_LE_UINT16(dataPtr); - dataPtr += 2; - } - channel = _operators[voice] + i * 3; - writeOPL(0xBD, 0x00); - writeOPL(0x08, 0x00); - writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); - if (!i) - writeOPL(0xC0 | voice, - ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); - writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); - writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); - writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | - ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | - ((strct[11] & 1) << 4) | (strct[1] & 0xF)); - if (!i) - writeOPL(0xE0 | channel, (strct[26] & 3)); - else - writeOPL(0xE0 | channel, (strct[14] & 3)); - if (i && set) - writeOPL(0x40 | channel, 0); - } -} - -void Adlib::setKey(byte voice, byte note, bool on, bool spec) { - short freq = 0; - short octa = 0; - - // Instruction AX - if (spec) { - // 0x7F donne 0x16B; - // 7F - // << 7 = 3F80 - // + E000 = 11F80 - // & FFFF = 1F80 - // * 19 = 31380 - // / 2000 = 18 => Ligne 18h, colonne 0 => freq 16B - - // 0x3A donne 0x2AF; - // 3A - // << 7 = 1D00 - // + E000 = FD00 negatif - // * 19 = xB500 - // / 2000 = -2 => Ligne 17h, colonne -1 - - // 2E - // << 7 = 1700 - // + E000 = F700 negatif - // * 19 = x1F00 - // / 2000 = - short a; - short lin; - short col; - - a = (note << 7) + 0xE000; // Volontairement tronque - a = (short)((long)a * 25 / 0x2000); - if (a < 0) { - col = - ((24 - a) / 25); - lin = (-a % 25); - if (lin) - lin = 25 - lin; - } - else { - col = a / 25; - lin = a % 25; - } - - _notCol[voice] = col; - _notLin[voice] = lin; - note = _notes[voice]; - } - // Instructions 0X 9X 8X - else { - note -= 12; - _notOn[voice] = on; - } - - _notes[voice] = note; - note += _notCol[voice]; - note = MIN((byte) 0x5F, note); - octa = note / 12; - freq = _freqs[_notLin[voice]][note - octa * 12]; - - writeOPL(0xA0 + voice, freq & 0xFF); - writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | 0x20 * on); - - if (!freq) - warning("Voice %d, note %02X unknown\n", voice, note); -} - -void Adlib::setVolume(byte voice, byte volume) { - volume = 0x3F - (volume * 0x7E + 0x7F) / 0xFE; - writeOPL(0x40 + _volRegNums[voice], volume); -} - -void Adlib::pollMusic() { - unsigned char instr; - byte channel; - byte note; - byte volume; - uint16 tempo; - - if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) { - _ended = true; - return; - } - - // First tempo, we'll ignore it... - if (_first) { - tempo = *(_playPos++); - // Tempo on 2 bytes - if (tempo & 0x80) - tempo = ((tempo & 3) << 8) | *(_playPos++); - } - _first = false; - - // Instruction - instr = *(_playPos++); - channel = instr & 0x0F; - - switch (instr & 0xF0) { - // Note on + Volume - case 0x00: - note = *(_playPos++); - _pollNotes[channel] = note; - setVolume(channel, *(_playPos++)); - setKey(channel, note, true, false); - break; - // Note on - case 0x90: - note = *(_playPos++); - _pollNotes[channel] = note; - setKey(channel, note, true, false); - break; - // Last note off - case 0x80: - note = _pollNotes[channel]; - setKey(channel, note, false, false); - break; - // Frequency on/off - case 0xA0: - note = *(_playPos++); - setKey(channel, note, _notOn[channel], true); - break; - // Volume - case 0xB0: - volume = *(_playPos++); - setVolume(channel, volume); - break; - // Program change - case 0xC0: - setVoice(channel, *(_playPos++), false); - break; - // Special - case 0xF0: - switch (instr & 0x0F) { - case 0xF: // End instruction - _ended = true; - _samplesTillPoll = 0; - return; - default: - warning("Unknown special command in ADL, stopping playback: %X", - instr & 0x0F); - _repCount = 0; - _ended = true; - break; - } - break; - default: - warning("Unknown command in ADL, stopping playback: %X", - instr & 0xF0); - _repCount = 0; - _ended = true; - break; - } - - // Temporization - tempo = *(_playPos++); - // End tempo - if (tempo == 0xFF) { - _ended = true; - return; - } - // Tempo on 2 bytes - if (tempo & 0x80) - tempo = ((tempo & 3) << 8) | *(_playPos++); - if (!tempo) - tempo ++; - - _samplesTillPoll = tempo * (_rate / 1000); -} - -void Adlib::playBgMusic() { - for (int i = 0; i < ARRAYSIZE(_tracks); i++) - if (!scumm_stricmp(_vm->_game->_curTotFile, _tracks[i][0])) { - playTrack(_tracks[i][1]); - break; - } -} - -void Adlib::playTrack(const char *trackname) { - if (_playing) return; - - debugC(1, kDebugMusic, "Adlib::playTrack(%s)", trackname); - unload(); - load(_trackFiles[_vm->_util->getRandom(ARRAYSIZE(_trackFiles))]); - startPlay(); -} - -bool Adlib::load(const char *fileName) { - Common::File song; - - unload(); - song.open(fileName); - if (!song.isOpen()) - return false; - - _needFree = true; - _dataSize = song.size(); - _data = new byte[_dataSize]; - song.read(_data, _dataSize); - song.close(); - - reset(); - setVoices(); - _playPos = _data + 3 + (_data[1] + 1) * 0x38; - - return true; -} - -void Adlib::load(byte *data, uint32 size, int index) { - unload(); - _repCount = 0; - - _dataSize = size; - _data = data; - _index = index; - - reset(); - setVoices(); - _playPos = _data + 3 + (_data[1] + 1) * 0x38; -} - -void Adlib::unload() { - _playing = false; - _index = -1; - - if (_data && _needFree) - delete[] _data; - - _needFree = false; -} - -} // End of namespace Gob diff --git a/engines/gob/music.h b/engines/gob/music.h deleted file mode 100644 index 199ea515b0..0000000000 --- a/engines/gob/music.h +++ /dev/null @@ -1,106 +0,0 @@ -/* 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 GOB_MUSIC_H -#define GOB_MUSIC_H - -#include "common/mutex.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" -#include "sound/fmopl.h" - -namespace Gob { - -class GobEngine; - -class Adlib : public Audio::AudioStream { -public: - Adlib(GobEngine *vm); - ~Adlib(); - - void lock() { _mutex.lock(); } - void unlock() { _mutex.unlock(); } - bool playing() const { return _playing; } - bool getRepeating() const { return _repCount != 0; } - void setRepeating (int32 repCount) { _repCount = repCount; } - int getIndex() const { return _index; } - void startPlay() { if (_data) _playing = true; } - void stopPlay() { - Common::StackLock slock(_mutex); - _playing = false; - } - void playTrack(const char *trackname); - void playBgMusic(); - bool load(const char *fileName); - void load(byte *data, uint32 size, int index = -1); - void unload(); - -// AudioStream API - 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: - static const char *_tracks[][2]; - static const char *_trackFiles[]; - static const unsigned char _operators[]; - static const unsigned char _volRegNums []; - Audio::SoundHandle _handle; - FM_OPL *_opl; - int _index; - byte *_data; - byte *_playPos; - uint32 _dataSize; - uint32 _rate; - short _freqs[25][12]; - byte _notes[11]; - byte _notCol[11]; - byte _notLin[11]; - bool _notOn[11]; - byte _pollNotes[16]; - int _samplesTillPoll; - int32 _repCount; - bool _playing; - bool _first; - bool _ended; - bool _needFree; - Common::Mutex _mutex; - GobEngine *_vm; - - void writeOPL(byte reg, byte val); - void setFreqs(); - void reset(); - void setVoices(); - void setVoice(byte voice, byte instr, bool set); - void setKey(byte voice, byte note, bool on, bool spec); - void setVolume(byte voice, byte volume); - void pollMusic(); -}; - -} // End of namespace Gob - -#endif // GOB_MUSIC_H diff --git a/engines/gob/parse.cpp b/engines/gob/parse.cpp index af12626c83..5d7cef0341 100644 --- a/engines/gob/parse.cpp +++ b/engines/gob/parse.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/parse_v1.cpp b/engines/gob/parse_v1.cpp index 2b84ac5cee..f18f63de4f 100644 --- a/engines/gob/parse_v1.cpp +++ b/engines/gob/parse_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/parse_v2.cpp b/engines/gob/parse_v2.cpp index 65315c083a..463a3870ee 100644 --- a/engines/gob/parse_v2.cpp +++ b/engines/gob/parse_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/scenery.cpp b/engines/gob/scenery.cpp index 62a4dbad2f..4dc1236ad6 100644 --- a/engines/gob/scenery.cpp +++ b/engines/gob/scenery.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "common/stream.h" diff --git a/engines/gob/scenery_v1.cpp b/engines/gob/scenery_v1.cpp index 5d3eb15a95..605b098693 100644 --- a/engines/gob/scenery_v1.cpp +++ b/engines/gob/scenery_v1.cpp @@ -23,13 +23,12 @@ * */ - #include "common/endian.h" #include "gob/gob.h" #include "gob/scenery.h" #include "gob/util.h" -#include "gob/cdrom.h" +#include "gob/sound/sound.h" namespace Gob { @@ -37,11 +36,11 @@ Scenery_v1::Scenery_v1(GobEngine *vm) : Scenery(vm) { } int16 Scenery_v1::loadAnim(char search) { - if (_vm->_cdrom->_cdPlaying) { - while (_vm->_cdrom->getTrackPos() != -1) + if (_vm->_sound->cdIsPlaying()) { + while (_vm->_sound->cdGetTrackPos() != -1) _vm->_util->longDelay(50); - _vm->_cdrom->_cdPlaying = false; + _vm->_sound->cdStop(); } return Scenery::loadAnim(search); diff --git a/engines/gob/scenery_v2.cpp b/engines/gob/scenery_v2.cpp index 6ed377af64..1a0de6f291 100644 --- a/engines/gob/scenery_v2.cpp +++ b/engines/gob/scenery_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp deleted file mode 100644 index 6b227cfb0e..0000000000 --- a/engines/gob/sound.cpp +++ /dev/null @@ -1,374 +0,0 @@ -/* 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$ - * - */ - - -#include "common/endian.h" - -#include "gob/gob.h" -#include "gob/sound.h" -#include "gob/global.h" -#include "gob/util.h" -#include "gob/dataio.h" -#include "gob/game.h" - -namespace Gob { - -void SoundDesc::set(SoundType type, SoundSource src, - byte *data, uint32 dSize) { - - free(); - - _type = type; - _source = src; - _data = _dataPtr = data; - _size = dSize; -} - -void SoundDesc::load(SoundType type, SoundSource src, - byte *data, uint32 dSize) { - - free(); - - _source = src; - switch (type) { - case SOUND_ADL: - loadADL(data, dSize); - break; - case SOUND_SND: - loadSND(data, dSize); - break; - } -} - -void SoundDesc::free() { - if (_source != SOUND_TOT) - delete[] _data; - _data = _dataPtr = 0; - _id = 0; -} - -void SoundDesc::convToSigned() { - if ((_type == SOUND_SND) && _data && _dataPtr) - for (uint32 i = 0; i < _size; i++) - _dataPtr[i] ^= 0x80; -} - -void SoundDesc::loadSND(byte *data, uint32 dSize) { - assert(dSize > 6); - - _type = SOUND_SND; - _data = data; - _dataPtr = data + 6; - _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700); - _flag = data[0] ? (data[0] & 0x7F) : 8; - data[0] = 0; - _size = MIN(READ_BE_UINT32(data), dSize - 6); -} - -void SoundDesc::loadADL(byte *data, uint32 dSize) { - _type = SOUND_ADL; - _data = _dataPtr = data; - _size = dSize; -} - -Snd::Snd(GobEngine *vm) : _vm(vm) { - _playingSound = 0; - _curSoundDesc = 0; - - _rate = _vm->_mixer->getOutputRate(); - _end = true; - _data = 0; - _length = 0; - _freq = 0; - _repCount = 0; - - _offset = 0; - _offsetFrac = 0; - _offsetInc = 0; - - _cur = 0; - _last = 0; - - _fade = false; - _fadeVol = 65536; - _fadeVolStep = 0; - _fadeSamples = 0; - _curFadeSamples = 0; - - _compositionSamples = 0; - _compositionSampleCount = 0; - _compositionPos = -1; - - _speakerStream = new Audio::PCSpeaker(_vm->_mixer->getOutputRate()); - - _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, - this, -1, 255, 0, false, true); - _vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_speakerHandle, - _speakerStream, -1, 50, 0, false, true); -} - -Snd::~Snd() { - // stop permanent streams manually: - - // First the speaker stream - _vm->_mixer->stopHandle(_speakerHandle); - delete _speakerStream; - - // Next, this stream (class Snd is an AudioStream, too) - _vm->_mixer->stopHandle(_handle); -} - -void Snd::speakerOn(int16 frequency, int32 length) { - _speakerStream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length); -} - -void Snd::speakerOff() { - _speakerStream->stop(); -} - -void Snd::speakerOnUpdate(uint32 milis) { - if (_speakerStream->isPlaying()) - _speakerStream->stop(milis); -} - -void Snd::stopSound(int16 fadeLength, SoundDesc *sndDesc) { - Common::StackLock slock(_mutex); - - if (sndDesc && (sndDesc != _curSoundDesc)) - return; - - if (fadeLength <= 0) { - _data = 0; - _end = true; - _playingSound = 0; - _curSoundDesc = 0; - return; - } - - _fade = true; - _fadeVol = 65536; - _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); - _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples)); - _curFadeSamples = 0; -} - -void Snd::setRepeating(int32 repCount) { - Common::StackLock slock(_mutex); - - _repCount = repCount; -} - -void Snd::waitEndPlay(bool interruptible, bool stopComp) { - if (stopComp) - _compositionPos = -1; - while (!_end && !_vm->_quitRequested) { - if (interruptible && (_vm->_util->checkKey() == 0x11B)) { - WRITE_VAR(57, -1); - return; - } - _vm->_util->longDelay(200); - } - stopSound(0); -} - -void Snd::stopComposition() { - if (_compositionPos != -1) { - stopSound(0); - _compositionPos = -1; - } -} - -void Snd::nextCompositionPos() { - int8 slot; - - while ((++_compositionPos < 50) && - ((slot = _composition[_compositionPos]) != -1)) { - if ((slot >= 0) && (slot < _compositionSampleCount)) { - SoundDesc &sample = _compositionSamples[slot]; - if (!sample.empty() && (sample.getType() == SOUND_SND)) { - setSample(sample, 1, 0, 0); - return; - } - } - if (_compositionPos == 49) - _compositionPos = -1; - } - _compositionPos = -1; -} - -void Snd::playComposition(int16 *composition, int16 freqVal, - SoundDesc *sndDescs, int8 sndCount) { - int i; - - waitEndPlay(); - stopComposition(); - - _compositionSamples = sndDescs ? sndDescs : _vm->_game->_soundSamples; - _compositionSampleCount = sndCount; - - i = -1; - do { - i++; - _composition[i] = composition[i]; - } while ((i < 50) && (composition[i] != -1)); - - _compositionPos = -1; - nextCompositionPos(); -} - -void Snd::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, - int16 fadeLength) { - - if (frequency <= 0) - frequency = sndDesc._frequency; - - _curSoundDesc = &sndDesc; - sndDesc._repCount = repCount - 1; - sndDesc._frequency = frequency; - - _data = (int8 *) sndDesc.getData(); - _length = sndDesc.size(); - _freq = frequency; - - _repCount = repCount; - _end = false; - _playingSound = 1; - - _offset = 0; - _offsetFrac = 0; - _offsetInc = (_freq << FRAC_BITS) / _rate; - - _last = _cur; - _cur = _data[0]; - - _curFadeSamples = 0; - if (fadeLength == 0) { - _fade = false; - _fadeVol = 65536; - _fadeSamples = 0; - _fadeVolStep = 0; - } else { - _fade = true; - _fadeVol = 0; - _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); - _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples)); - } -} - -bool Snd::loadSample(SoundDesc &sndDesc, const char *fileName) { - byte *data; - uint32 size; - - data = (byte *) _vm->_dataIO->getData(fileName); - if (!data) - return false; - - size = _vm->_dataIO->getDataSize(fileName); - sndDesc.load(SOUND_SND, SOUND_FILE, data, size); - - return true; -} - -void Snd::freeSample(SoundDesc &sndDesc) { - stopSound(0, &sndDesc); - sndDesc.free(); -} - -void Snd::playSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, - int16 fadeLength) { - Common::StackLock slock(_mutex); - - if (!_end) - return; - - setSample(sndDesc, repCount, frequency, fadeLength); -} - -void Snd::checkEndSample() { - if (_compositionPos != -1) - nextCompositionPos(); - else if ((_repCount == -1) || (--_repCount > 0)) { - _offset = 0; - _offsetFrac = 0; - _end = false; - _playingSound = 1; - } else { - _end = true; - _playingSound = 0; - } -} - -int Snd::readBuffer(int16 *buffer, const int numSamples) { - Common::StackLock slock(_mutex); - - for (int i = 0; i < numSamples; i++) { - if (!_data) - return i; - if (_end || (_offset >= _length)) - checkEndSample(); - if (_end) - return i; - - // Linear interpolation. See sound/rate.cpp - - int16 val = (_last + (((_cur - _last) * _offsetFrac + - FRAC_HALF) >> FRAC_BITS)) << 8; - *buffer++ = (val * _fadeVol) >> 16; - - _offsetFrac += _offsetInc; - - // Was there an integral change? - if (fracToInt(_offsetFrac) > 0) { - _last = _cur; - _cur = _data[_offset]; - _offset += fracToInt(_offsetFrac); - _offsetFrac &= FRAC_LO_MASK; - } - - if (_fade) { - - if (++_curFadeSamples >= _fadeSamples) { - if (_fadeVolStep > 0) { - _data = 0; - _end = true; - _playingSound = 0; - _compositionPos = -1; - _curSoundDesc = 0; - } else { - _fadeVol = 65536; - _fade = false; - } - } else - _fadeVol -= _fadeVolStep; - - if (_fadeVol < 0) - _fadeVol = 0; - - } - } - return numSamples; -} - -} // End of namespace Gob diff --git a/engines/gob/sound.h b/engines/gob/sound.h deleted file mode 100644 index 6780c201b5..0000000000 --- a/engines/gob/sound.h +++ /dev/null @@ -1,172 +0,0 @@ -/* 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 GOB_SOUND_H -#define GOB_SOUND_H - -#include "common/mutex.h" -#include "common/frac.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" -#include "sound/softsynth/pcspk.h" - -namespace Gob { - -enum SoundType { - SOUND_SND, - SOUND_ADL -}; - -enum SoundSource { - SOUND_FILE, - SOUND_TOT, - SOUND_EXT -}; - -class SoundDesc { -public: - int16 _repCount; - int16 _frequency; - int16 _flag; - int16 _id; - - byte *getData() { return _dataPtr; } - uint32 size() { return _size; } - bool empty() { return !_dataPtr; } - bool isId(int16 id) { return _dataPtr && _id == id; } - SoundType getType() { return _type; } - - void set(SoundType type, SoundSource src, byte *data, uint32 dSize); - void load(SoundType type, SoundSource src, byte *data, uint32 dSize); - void free(); - void convToSigned(); - - // Which fade out length to use when the fade starts half-way through? - int16 calcFadeOutLength(int16 frequency) { - return (10 * (_size / 2)) / frequency; - } - uint32 calcLength(int16 repCount, int16 frequency, bool fade) { - uint32 fadeSize = fade ? _size / 2 : 0; - return ((_size * repCount - fadeSize) * 1000) / frequency; - } - - SoundDesc() : _data(0), _dataPtr(0), _size(0), _type(SOUND_SND), - _source(SOUND_FILE), _repCount(0), _frequency(0), - _flag(0), _id(0) {} - ~SoundDesc() { free(); } - -private: - byte *_data; - byte *_dataPtr; - uint32 _size; - - SoundType _type; - SoundSource _source; - - void loadSND(byte *data, uint32 dSize); - void loadADL(byte *data, uint32 dSize); -}; - -class Snd : public Audio::AudioStream { -public: - char _playingSound; - - Snd(GobEngine *vm); - ~Snd(); - - void speakerOn(int16 frequency, int32 length); - void speakerOff(); - void speakerOnUpdate(uint32 milis); - void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0); - - bool loadSample(SoundDesc &sndDesc, const char *fileName); - void freeSample(SoundDesc &sndDesc); - void playSample(SoundDesc &sndDesc, int16 repCount, - int16 frequency, int16 fadeLength = 0); - - void playComposition(int16 *composition, int16 freqVal, - SoundDesc *sndDescs = 0, int8 sndCount = 60); - void stopComposition(); - void setRepeating(int32 repCount); - void waitEndPlay(bool interruptible = false, bool stopComp = true); - - static void convToSigned(byte *buffer, int length) { - while (length-- > 0) - *buffer++ ^= 0x80; - } - - 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: - Audio::PCSpeaker *_speakerStream; - Audio::SoundHandle _speakerHandle; - - Audio::SoundHandle *_activeHandle; - Audio::SoundHandle _compositionHandle; - - SoundDesc *_compositionSamples; - int8 _compositionSampleCount; - 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; - - uint32 _offset; - frac_t _offsetFrac; - frac_t _offsetInc; - - int16 _cur; - int16 _last; - - bool _fade; - int32 _fadeVol; - int32 _fadeVolStep; - uint8 _fadeLength; - uint32 _fadeSamples; - uint32 _curFadeSamples; - - GobEngine *_vm; - - void setSample(SoundDesc &sndDesc, int16 repCount, - int16 frequency, int16 fadeLength); - void checkEndSample(); - void nextCompositionPos(); -}; - -} // End of namespace Gob - -#endif // GOB_SOUND_H diff --git a/engines/gob/sound/adlib.cpp b/engines/gob/sound/adlib.cpp new file mode 100644 index 0000000000..fb0d9d58c1 --- /dev/null +++ b/engines/gob/sound/adlib.cpp @@ -0,0 +1,457 @@ +/* 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$ + * + */ + +#include "common/file.h" +#include "common/endian.h" + +#include "gob/gob.h" +#include "gob/sound/adlib.h" + +namespace Gob { + +const unsigned char AdLib::_operators[] = {0, 1, 2, 8, 9, 10, 16, 17, 18}; +const unsigned char AdLib::_volRegNums[] = { + 3, 4, 5, + 11, 12, 13, + 19, 20, 21 +}; + +AdLib::AdLib(Audio::Mixer &mixer) : _mixer(&mixer) { + _index = -1; + _data = 0; + _playPos = 0; + _dataSize = 0; + + _rate = _mixer->getOutputRate(); + _opl = makeAdlibOPL(_rate); + + _first = true; + _ended = false; + _playing = false; + _needFree = false; + + _repCount = -1; + _samplesTillPoll = 0; + + for (int i = 0; i < 16; i ++) + _pollNotes[i] = 0; + setFreqs(); + + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_handle, + this, -1, 255, 0, false, true); +} + +AdLib::~AdLib() { + Common::StackLock slock(_mutex); + + _mixer->stopHandle(_handle); + OPLDestroy(_opl); + if (_data && _needFree) + delete[] _data; +} + +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; + } + 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(); + 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; + } + + return numSamples; +} + +void AdLib::writeOPL(byte reg, byte val) { + debugC(6, kDebugMusic, "writeOPL(%02X, %02X)", reg, val); + OPLWriteReg(_opl, reg, val); +} + +void AdLib::setFreqs() { + byte lin; + byte col; + long val = 0; + + // Run through the 11 channels + for (lin = 0; lin < 11; lin ++) { + _notes[lin] = 0; + _notCol[lin] = 0; + _notLin[lin] = 0; + _notOn[lin] = false; + } + + // Run through the 25 lines + for (lin = 0; lin < 25; lin ++) { + // Run through the 12 columns + for (col = 0; col < 12; col ++) { + if (!col) + val = (((0x2710L + lin * 0x18) * 0xCB78 / 0x3D090) << 0xE) * + 9 / 0x1B503; + _freqs[lin][col] = (short)((val + 4) >> 3); + val = val * 0x6A / 0x64; + } + } +} + +void AdLib::reset() { + _first = true; + OPLResetChip(_opl); + _samplesTillPoll = 0; + + setFreqs(); + // Set frequencies and octave to 0; notes off + for (int i = 0; i < 9; i++) { + writeOPL(0xA0 | i, 0); + writeOPL(0xB0 | i, 0); + writeOPL(0xE0 | _operators[i] , 0); + writeOPL(0xE0 | _operators[i] + 3, 0); + } + + // Authorize the control of the waveformes + writeOPL(0x01, 0x20); +} + +void AdLib::setVoices() { + // Definitions of the 9 instruments + for (int i = 0; i < 9; i++) + setVoice(i, i, true); +} + +void AdLib::setVoice(byte voice, byte instr, bool set) { + int i; + int j; + uint16 strct[27]; + byte channel; + byte *dataPtr; + + // i = 0 : 0 1 2 3 4 5 6 7 8 9 10 11 12 26 + // i = 1 : 13 14 15 16 17 18 19 20 21 22 23 24 25 27 + for (i = 0; i < 2; i++) { + dataPtr = _data + 3 + instr * 0x38 + i * 0x1A; + for (j = 0; j < 27; j++) { + strct[j] = READ_LE_UINT16(dataPtr); + dataPtr += 2; + } + channel = _operators[voice] + i * 3; + writeOPL(0xBD, 0x00); + writeOPL(0x08, 0x00); + writeOPL(0x40 | channel, ((strct[0] & 3) << 6) | (strct[8] & 0x3F)); + if (!i) + writeOPL(0xC0 | voice, + ((strct[2] & 7) << 1) | (1 - (strct[12] & 1))); + writeOPL(0x60 | channel, ((strct[3] & 0xF) << 4) | (strct[6] & 0xF)); + writeOPL(0x80 | channel, ((strct[4] & 0xF) << 4) | (strct[7] & 0xF)); + writeOPL(0x20 | channel, ((strct[9] & 1) << 7) | + ((strct[10] & 1) << 6) | ((strct[5] & 1) << 5) | + ((strct[11] & 1) << 4) | (strct[1] & 0xF)); + if (!i) + writeOPL(0xE0 | channel, (strct[26] & 3)); + else + writeOPL(0xE0 | channel, (strct[14] & 3)); + if (i && set) + writeOPL(0x40 | channel, 0); + } +} + +void AdLib::setKey(byte voice, byte note, bool on, bool spec) { + short freq = 0; + short octa = 0; + + // Instruction AX + if (spec) { + // 0x7F donne 0x16B; + // 7F + // << 7 = 3F80 + // + E000 = 11F80 + // & FFFF = 1F80 + // * 19 = 31380 + // / 2000 = 18 => Ligne 18h, colonne 0 => freq 16B + + // 0x3A donne 0x2AF; + // 3A + // << 7 = 1D00 + // + E000 = FD00 negatif + // * 19 = xB500 + // / 2000 = -2 => Ligne 17h, colonne -1 + + // 2E + // << 7 = 1700 + // + E000 = F700 negatif + // * 19 = x1F00 + // / 2000 = + short a; + short lin; + short col; + + a = (note << 7) + 0xE000; // Volontairement tronque + a = (short)((long)a * 25 / 0x2000); + if (a < 0) { + col = - ((24 - a) / 25); + lin = (-a % 25); + if (lin) + lin = 25 - lin; + } + else { + col = a / 25; + lin = a % 25; + } + + _notCol[voice] = col; + _notLin[voice] = lin; + note = _notes[voice]; + } + // Instructions 0X 9X 8X + else { + note -= 12; + _notOn[voice] = on; + } + + _notes[voice] = note; + note += _notCol[voice]; + note = MIN((byte) 0x5F, note); + octa = note / 12; + freq = _freqs[_notLin[voice]][note - octa * 12]; + + writeOPL(0xA0 + voice, freq & 0xFF); + writeOPL(0xB0 + voice, (freq >> 8) | (octa << 2) | 0x20 * on); + + if (!freq) + warning("Voice %d, note %02X unknown\n", voice, note); +} + +void AdLib::setVolume(byte voice, byte volume) { + volume = 0x3F - (volume * 0x7E + 0x7F) / 0xFE; + writeOPL(0x40 + _volRegNums[voice], volume); +} + +void AdLib::pollMusic() { + unsigned char instr; + byte channel; + byte note; + byte volume; + uint16 tempo; + + if ((_playPos > (_data + _dataSize)) && (_dataSize != 0xFFFFFFFF)) { + _ended = true; + return; + } + + // First tempo, we'll ignore it... + if (_first) { + tempo = *(_playPos++); + // Tempo on 2 bytes + if (tempo & 0x80) + tempo = ((tempo & 3) << 8) | *(_playPos++); + } + _first = false; + + // Instruction + instr = *(_playPos++); + channel = instr & 0x0F; + + switch (instr & 0xF0) { + // Note on + Volume + case 0x00: + note = *(_playPos++); + _pollNotes[channel] = note; + setVolume(channel, *(_playPos++)); + setKey(channel, note, true, false); + break; + // Note on + case 0x90: + note = *(_playPos++); + _pollNotes[channel] = note; + setKey(channel, note, true, false); + break; + // Last note off + case 0x80: + note = _pollNotes[channel]; + setKey(channel, note, false, false); + break; + // Frequency on/off + case 0xA0: + note = *(_playPos++); + setKey(channel, note, _notOn[channel], true); + break; + // Volume + case 0xB0: + volume = *(_playPos++); + setVolume(channel, volume); + break; + // Program change + case 0xC0: + setVoice(channel, *(_playPos++), false); + break; + // Special + case 0xF0: + switch (instr & 0x0F) { + case 0xF: // End instruction + _ended = true; + _samplesTillPoll = 0; + return; + default: + warning("Unknown special command in ADL, stopping playback: %X", + instr & 0x0F); + _repCount = 0; + _ended = true; + break; + } + break; + default: + warning("Unknown command in ADL, stopping playback: %X", + instr & 0xF0); + _repCount = 0; + _ended = true; + break; + } + + // Temporization + tempo = *(_playPos++); + // End tempo + if (tempo == 0xFF) { + _ended = true; + return; + } + // Tempo on 2 bytes + if (tempo & 0x80) + tempo = ((tempo & 3) << 8) | *(_playPos++); + if (!tempo) + tempo ++; + + _samplesTillPoll = tempo * (_rate / 1000); +} + +bool AdLib::load(const char *fileName) { + Common::File song; + + unload(); + song.open(fileName); + if (!song.isOpen()) + return false; + + _needFree = true; + _dataSize = song.size(); + _data = new byte[_dataSize]; + song.read(_data, _dataSize); + song.close(); + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; +} + +bool AdLib::load(byte *data, uint32 size, int index) { + unload(); + _repCount = 0; + + _dataSize = size; + _data = data; + _index = index; + + reset(); + setVoices(); + _playPos = _data + 3 + (_data[1] + 1) * 0x38; + + return true; +} + +void AdLib::unload() { + _playing = false; + _index = -1; + + if (_data && _needFree) + delete[] _data; + + _needFree = false; +} + +bool AdLib::isPlaying() const { + return _playing; +} + +bool AdLib::getRepeating() const { + return _repCount != 0; +} + +void AdLib::setRepeating(int32 repCount) { + _repCount = repCount; +} + +int AdLib::getIndex() const { + return _index; +} + +void AdLib::startPlay() { + if (_data) _playing = true; +} + +void AdLib::stopPlay() { + Common::StackLock slock(_mutex); + _playing = false; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/adlib.h b/engines/gob/sound/adlib.h new file mode 100644 index 0000000000..4cd83d5883 --- /dev/null +++ b/engines/gob/sound/adlib.h @@ -0,0 +1,108 @@ +/* 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 GOB_SOUND_ADLIB_H +#define GOB_SOUND_ADLIB_H + +#include "common/mutex.h" +#include "sound/audiostream.h" +#include "sound/mixer.h" +#include "sound/fmopl.h" + +namespace Gob { + +class GobEngine; + +class AdLib : public Audio::AudioStream { +public: + AdLib(Audio::Mixer &mixer); + ~AdLib(); + + bool isPlaying() const; + int getIndex() const; + bool getRepeating() const; + + void setRepeating(int32 repCount); + + void startPlay(); + void stopPlay(); + + bool load(const char *fileName); + bool load(byte *data, uint32 size, int index = -1); + void unload(); + +// AudioStream API + 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: + static const unsigned char _operators[]; + static const unsigned char _volRegNums []; + + Audio::Mixer *_mixer; + Audio::SoundHandle _handle; + FM_OPL *_opl; + + Common::Mutex _mutex; + + uint32 _rate; + + byte *_data; + byte *_playPos; + uint32 _dataSize; + + short _freqs[25][12]; + byte _notes[11]; + byte _notCol[11]; + byte _notLin[11]; + bool _notOn[11]; + byte _pollNotes[16]; + + int _samplesTillPoll; + int32 _repCount; + + bool _playing; + bool _first; + bool _ended; + bool _needFree; + + int _index; + + void writeOPL(byte reg, byte val); + void setFreqs(); + void reset(); + void setVoices(); + void setVoice(byte voice, byte instr, bool set); + void setKey(byte voice, byte note, bool on, bool spec); + void setVolume(byte voice, byte volume); + void pollMusic(); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_ADLIB_H diff --git a/engines/gob/sound/cdrom.cpp b/engines/gob/sound/cdrom.cpp new file mode 100644 index 0000000000..f3bc70807e --- /dev/null +++ b/engines/gob/sound/cdrom.cpp @@ -0,0 +1,201 @@ +/* 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$ + * + */ + +#include "common/endian.h" +#include "common/util.h" +#include "sound/audiocd.h" + +#include "gob/gob.h" +#include "gob/sound/cdrom.h" + +namespace Gob { + +CDROM::CDROM() { + _cdPlaying = false; + + _LICbuffer = 0; + for (int i = 0; i < 16; i++) + _curTrack[i] = 0; + _numTracks = 0; + _trackStop = 0; + _startTime = 0; +} + +CDROM::~CDROM() { +} + +void CDROM::readLIC(DataStream &stream) { + uint16 version, startChunk, pos; + + freeLICBuffer(); + *_curTrack = 0; + + version = stream.readUint16LE(); + startChunk = stream.readUint16LE(); + _numTracks = stream.readUint16LE(); + + if (version != 3) + error("Unknown version %d while reading LIC", version); + + stream.seek(50); + + for (int i = 0; i < startChunk; i++) { + pos = stream.readUint16LE(); + + if (!pos) + break; + + stream.skip(pos); + } + + _LICbuffer = new byte[_numTracks * 22]; + stream.read(_LICbuffer, _numTracks * 22); +} + +void CDROM::freeLICBuffer() { + delete[] _LICbuffer; + _LICbuffer = 0; +} + +void CDROM::startTrack(const char *trackName) { + if (!_LICbuffer) + return; + + debugC(1, kDebugMusic, "CDROM::startTrack(%s)", trackName); + + byte *matchPtr = getTrackBuffer(trackName); + if (!matchPtr) { + warning("Track \"%s\" not found", trackName); + return; + } + + strncpy0(_curTrack, trackName, 15); + + stopPlaying(); + _curTrackBuffer = matchPtr; + + while (getTrackPos() >= 0); + + uint32 start = READ_LE_UINT32(matchPtr + 12); + uint32 end = READ_LE_UINT32(matchPtr + 16); + + play(start, end); + + _startTime = g_system->getMillis(); + _trackStop = _startTime + (end - start + 1 + 150) * 40 / 3; +} + +void CDROM::play(uint32 from, uint32 to) { + // play from sector [from] to sector [to] + // + // format is HSG: + // HSG encodes frame information into a double word: + // minute multiplied by 4500, plus second multiplied by 75, + // plus frame, minus 150 + debugC(1, kDebugMusic, "CDROM::play(%d, %d)", from, to); + + AudioCD.play(1, 1, from, to - from + 1); + _cdPlaying = true; +} + +bool CDROM::isPlaying() const { + return _cdPlaying; +} + +int32 CDROM::getTrackPos(const char *keyTrack) const { + byte *keyBuffer = getTrackBuffer(keyTrack); + uint32 curPos = (g_system->getMillis() - _startTime) * 3 / 40; + + if (_cdPlaying && (g_system->getMillis() < _trackStop)) { + if (keyBuffer && _curTrackBuffer && (keyBuffer != _curTrackBuffer)) { + uint32 kStart = READ_LE_UINT32(keyBuffer + 12); + uint32 kEnd = READ_LE_UINT32(keyBuffer + 16); + uint32 cStart = READ_LE_UINT32(_curTrackBuffer + 12); + uint32 cEnd = READ_LE_UINT32(_curTrackBuffer + 16); + + if ((kStart >= cStart) && (kEnd <= cEnd)) { + if ((kStart - cStart) > curPos) + return -2; + if ((kEnd - cStart) < curPos) + return -1; + } + } + + return curPos; + } else + return -1; +} + +const char *CDROM::getCurTrack() const { + return _curTrack; +} + +void CDROM::stopPlaying() { + stop(); + + while (getTrackPos() != -1); +} + +void CDROM::stop() { + debugC(1, kDebugMusic, "CDROM::stop()"); + + _curTrackBuffer = 0; + AudioCD.stop(); + _cdPlaying = false; +} + +void CDROM::testCD(int trySubst, const char *label) { + if (!trySubst) { + error("CDROM track substitution is not supported"); + return; + } + + _LICbuffer = 0; + _cdPlaying = false; + + // Original checked CD label here + // but will skip it as it will require OSystem extensions of direct + // CD secor reading +} + +byte *CDROM::getTrackBuffer(const char *trackName) const { + if (!_LICbuffer || !trackName) + return 0; + + byte *matchPtr = 0; + byte *curPtr = _LICbuffer; + + for (int i = 0; i < _numTracks; i++) { + if (!scumm_stricmp((char *) curPtr, trackName)) { + matchPtr = curPtr; + break; + } + curPtr += 22; + } + + return matchPtr; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/cdrom.h b/engines/gob/sound/cdrom.h new file mode 100644 index 0000000000..201f7adb75 --- /dev/null +++ b/engines/gob/sound/cdrom.h @@ -0,0 +1,68 @@ +/* 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 GOB_SOUND_CDROM_H +#define GOB_SOUND_CDROM_H + +#include "gob/dataio.h" + +namespace Gob { + +class CDROM { +public: + CDROM(); + ~CDROM(); + + void readLIC(DataStream &stream); + void freeLICBuffer(); + + void startTrack(const char *trackName); + void stopPlaying(); + + bool isPlaying() const; + + int32 getTrackPos(const char *keyTrack = 0) const; + const char *getCurTrack() const; + + void testCD(int trySubst, const char *label); + +protected: + byte *_LICbuffer; + byte *_curTrackBuffer; + char _curTrack[16]; + uint16 _numTracks; + uint32 _trackStop; + uint32 _startTime; + bool _cdPlaying; + + void play(uint32 from, uint32 to); + void stop(); + + byte *getTrackBuffer(const char *trackName) const; +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_CDROM_H diff --git a/engines/gob/sound/infogrames.cpp b/engines/gob/sound/infogrames.cpp new file mode 100644 index 0000000000..0b46f3485c --- /dev/null +++ b/engines/gob/sound/infogrames.cpp @@ -0,0 +1,103 @@ +/* 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$ + * + */ + +#include "gob/sound/infogrames.h" + +namespace Gob { + +Infogrames::Infogrames(Audio::Mixer &mixer) : _mixer(&mixer) { + _instruments = 0; + _song = 0; +} + +Infogrames::~Infogrames() { + clearSong(); + clearInstruments(); +} + +bool Infogrames::loadInstruments(const char *fileName) { + clearSong(); + clearInstruments(); + + return loadInst(fileName); +} + +bool Infogrames::loadSong(const char *fileName) { + clearSong(); + + if (!_instruments) + if (!loadInst("i1.ins")) + return false; + + _song = new Audio::Infogrames(*_instruments, true, + _mixer->getOutputRate(), _mixer->getOutputRate() / 75); + + if (!_song->load(fileName)) { + warning("Couldn't load infogrames music"); + clearSong(); + return false; + } + + return true; +} + +void Infogrames::play() { + if (_song && !_mixer->isSoundHandleActive(_handle)) { + _song->restart(); + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, + &_handle, _song, -1, 255, 0, false); + } +} + +void Infogrames::stop() { + _mixer->stopHandle(_handle); +} + +void Infogrames::clearInstruments() { + delete _instruments; + _instruments = 0; +} + +void Infogrames::clearSong() { + if (_song) { + _mixer->stopHandle(_handle); + + delete _song; + _song = 0; + } +} + +bool Infogrames::loadInst(const char *fileName) { + _instruments = new Audio::Infogrames::Instruments; + if (!_instruments->load(fileName)) { + warning("Couldn't load instruments file"); + clearInstruments(); + return false; + } + + return true; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/infogrames.h b/engines/gob/sound/infogrames.h new file mode 100644 index 0000000000..4a20dceb22 --- /dev/null +++ b/engines/gob/sound/infogrames.h @@ -0,0 +1,60 @@ +/* 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 GOB_SOUND_INFOGRAMES_H +#define GOB_SOUND_INFOGRAMES_H + +#include "sound/mixer.h" +#include "sound/mods/infogrames.h" + +namespace Gob { + +class Infogrames { +public: + Infogrames(Audio::Mixer &mixer); + ~Infogrames(); + + bool loadInstruments(const char *fileName); + bool loadSong(const char *fileName); + + void play(); + void stop(); + +private: + Audio::Mixer *_mixer; + + Audio::Infogrames::Instruments *_instruments; + Audio::Infogrames *_song; + Audio::SoundHandle _handle; + + void clearInstruments(); + void clearSong(); + + bool loadInst(const char *fileName); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_INFOGRAMES_H diff --git a/engines/gob/sound/pcspeaker.cpp b/engines/gob/sound/pcspeaker.cpp new file mode 100644 index 0000000000..0d1fc0a6db --- /dev/null +++ b/engines/gob/sound/pcspeaker.cpp @@ -0,0 +1,55 @@ +/* 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$ + * + */ + +#include "gob/sound/pcspeaker.h" + +namespace Gob { + +PCSpeaker::PCSpeaker(Audio::Mixer &mixer) : _mixer(&mixer) { + + _stream = new Audio::PCSpeaker(_mixer->getOutputRate()); + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, + &_handle, _stream, -1, 50, 0, false, true); +} + +PCSpeaker::~PCSpeaker() { + _mixer->stopHandle(_handle); + delete _stream; +} + +void PCSpeaker::speakerOn(int16 frequency, int32 length) { + _stream->play(Audio::PCSpeaker::kWaveFormSquare, frequency, length); +} + +void PCSpeaker::speakerOff() { + _stream->stop(); +} + +void PCSpeaker::onUpdate(uint32 millis) { + if (_stream->isPlaying()) + _stream->stop(millis); +} + +} // End of namespace Gob diff --git a/engines/gob/sound/pcspeaker.h b/engines/gob/sound/pcspeaker.h new file mode 100644 index 0000000000..8c4fb08021 --- /dev/null +++ b/engines/gob/sound/pcspeaker.h @@ -0,0 +1,52 @@ +/* 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 GOB_SOUND_PCSPEAKER_H +#define GOB_SOUND_PCSPEAKER_H + +#include "sound/mixer.h" +#include "sound/softsynth/pcspk.h" + +namespace Gob { + +class PCSpeaker { +public: + PCSpeaker(Audio::Mixer &mixer); + ~PCSpeaker(); + + void speakerOn(int16 frequency, int32 length = -1); + void speakerOff(); + void onUpdate(uint32 millis); + +private: + Audio::Mixer *_mixer; + + Audio::PCSpeaker *_stream; + Audio::SoundHandle _handle; +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_PCSPEAKER_H diff --git a/engines/gob/sound/sound.cpp b/engines/gob/sound/sound.cpp new file mode 100644 index 0000000000..5c375c260a --- /dev/null +++ b/engines/gob/sound/sound.cpp @@ -0,0 +1,461 @@ +/* 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$ + * + */ + +#include "gob/gob.h" +#include "gob/sound/sound.h" +#include "gob/global.h" +#include "gob/util.h" +#include "gob/dataio.h" +#include "gob/game.h" + +namespace Gob { + +Sound::Sound(GobEngine *vm) : _vm(vm) { + _pcspeaker = new PCSpeaker(*_vm->_mixer); + _blaster = new SoundBlaster(*_vm->_mixer); + + _adlib = 0; + _infogrames = 0; + _cdrom = 0; + + if (!_vm->_noMusic && _vm->hasAdlib()) + _adlib = new AdLib(*_vm->_mixer); + if (!_vm->_noMusic && (_vm->getPlatform() == Common::kPlatformAmiga)) + _infogrames = new Infogrames(*_vm->_mixer); + if (_vm->isCD()) + _cdrom = new CDROM; +} + +Sound::~Sound() { + delete _pcspeaker; + delete _blaster; + delete _adlib; + delete _infogrames; + + for (int i = 0; i < kSoundsCount; i++) + _sounds[i].free(); +} + +void Sound::convToSigned(byte *buffer, int length) { + while (length-- > 0) + *buffer++ ^= 0x80; +} + +SoundDesc *Sound::sampleGetBySlot(int slot) { + if ((slot < 0) || (slot >= kSoundsCount)) + return 0; + + return &_sounds[slot]; +} + +const SoundDesc *Sound::sampleGetBySlot(int slot) const { + if ((slot < 0) || (slot >= kSoundsCount)) + return 0; + + return &_sounds[slot]; +} + +int Sound::sampleGetNextFreeSlot() const { + for (int i = 0; i < kSoundsCount; i++) + if (_sounds[i].empty()) + return i; + + return -1; +} + +bool Sound::sampleLoad(SoundDesc *sndDesc, const char *fileName) { + if (!sndDesc) + return false; + + byte *data; + uint32 size; + + data = (byte *) _vm->_dataIO->getData(fileName); + if (!data) + return false; + + size = _vm->_dataIO->getDataSize(fileName); + sndDesc->load(SOUND_SND, SOUND_FILE, data, size); + + return true; +} + +void Sound::sampleFree(SoundDesc *sndDesc, bool noteAdlib, int index) { + if (!sndDesc || sndDesc->empty()) + return; + + if (sndDesc->getType() == SOUND_ADL) { + + if (_adlib && noteAdlib) + if ((index == -1) || (_adlib->getIndex() == index)) + _adlib->stopPlay(); + + } else { + + if (_blaster) + _blaster->stopSound(0, sndDesc); + + } + + sndDesc->free(); +} + +void Sound::speakerOn(int16 frequency, int32 length) { + if (!_pcspeaker) + return; + + _pcspeaker->speakerOn(frequency, length); +} + +void Sound::speakerOff() { + if (!_pcspeaker) + return; + + _pcspeaker->speakerOff(); +} + +void Sound::speakerOnUpdate(uint32 millis) { + if (!_pcspeaker) + return; + + _pcspeaker->onUpdate(millis); +} + +bool Sound::infogramesLoadInstruments(const char *fileName) { + if (!_infogrames) + return false; + + return _infogrames->loadInstruments(fileName); +} + +bool Sound::infogramesLoadSong(const char *fileName) { + if (!_infogrames) + return false; + + return _infogrames->loadSong(fileName); +} + +void Sound::infogramesPlay() { + if (!_infogrames) + return; + + _infogrames->play(); +} + +void Sound::infogramesStop() { + if (!_infogrames) + return; + + _infogrames->stop(); +} + +bool Sound::adlibLoad(const char *fileName) { + if (!_adlib) + return false; + + return _adlib->load(fileName); +} + +bool Sound::adlibLoad(byte *data, uint32 size, int index) { + if (!_adlib) + return false; + + return _adlib->load(data, size, index); +} + +void Sound::adlibUnload() { + if (!_adlib) + return; + + _adlib->unload(); +} + +void Sound::adlibPlayTrack(const char *trackname) { + if (!_adlib || _adlib->isPlaying()) + return; + + debugC(1, kDebugMusic, "Adlib::playTrack(%s)", trackname); + + _adlib->unload(); + _adlib->load(trackname); + _adlib->startPlay(); +} + +void Sound::adlibPlayBgMusic() { + if (!_adlib) + return; + + static const char *tracks[] = { +// "musmac1.adl", // TODO: This track isn't played correctly at all yet + "musmac2.adl", + "musmac3.adl", + "musmac4.adl", + "musmac5.adl", + "musmac6.adl" + }; + + int track = _vm->_util->getRandom(ARRAYSIZE(tracks)); + adlibPlayTrack(tracks[track]); +} + +void Sound::adlibPlay() { + if (!_adlib) + return; + + _adlib->startPlay(); +} + +void Sound::adlibStop() { + if (!_adlib) + return; + + _adlib->stopPlay(); +} + +bool Sound::adlibIsPlaying() const { + if (!_adlib) + return false; + + return _adlib->isPlaying(); +} + +int Sound::adlibGetIndex() const { + if (!_adlib) + return -1; + + return _adlib->getIndex(); +} + +bool Sound::adlibGetRepeating() const { + if (!_adlib) + return false; + + return _adlib->getRepeating(); +} + +void Sound::adlibSetRepeating(int32 repCount) { + if (!_adlib) + return; + + _adlib->setRepeating(repCount); +} + +void Sound::blasterPlay(SoundDesc *sndDesc, int16 repCount, + int16 frequency, int16 fadeLength) { + if (!_blaster || !sndDesc) + return; + + _blaster->playSample(*sndDesc, repCount, frequency, fadeLength); +} + +void Sound::blasterStop(int16 fadeLength, SoundDesc *sndDesc) { + if (!_blaster) + return; + + _blaster->stopSound(fadeLength, sndDesc); +} + +void Sound::blasterPlayComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs, int8 sndCount) { + if (!_blaster) + return; + + blasterWaitEndPlay(); + _blaster->stopComposition(); + + if (!sndDescs) + sndDescs = _sounds; + + _blaster->playComposition(composition, freqVal, sndDescs, sndCount); +} + +void Sound::blasterStopComposition() { + if (!_blaster) + return; + + _blaster->stopComposition(); +} + +char Sound::blasterPlayingSound() const { + if (!_blaster) + return 0; + + return _blaster->getPlayingSound(); +} + +void Sound::blasterSetRepeating(int32 repCount) { + if (!_blaster) + return; + + _blaster->setRepeating(repCount); +} + +void Sound::blasterWaitEndPlay(bool interruptible, bool stopComp) { + if (!_blaster) + return; + + if (stopComp) + _blaster->endComposition(); + + while (_blaster->isPlaying() && !_vm->_quitRequested) { + if (interruptible && (_vm->_util->checkKey() == 0x11B)) { + WRITE_VAR(57, -1); + return; + } + _vm->_util->longDelay(200); + } + + _blaster->stopSound(0); +} + +void Sound::cdLoadLIC(const char *fname) { + if (!_cdrom) + return; + + int handle = _vm->_dataIO->openData(fname); + + if (handle == -1) + return; + + _vm->_dataIO->closeData(handle); + + _vm->_dataIO->getUnpackedData(fname); + + handle = _vm->_dataIO->openData(fname); + DataStream *stream = _vm->_dataIO->openAsStream(handle, true); + + _cdrom->readLIC(*stream); + + delete stream; +} + +void Sound::cdUnloadLIC() { + if (!_cdrom) + return; + + _cdrom->freeLICBuffer(); +} + +void Sound::cdPlayBgMusic() { + if (!_cdrom) + return; + + static const char *tracks[][2] = { + {"avt00.tot", "mine"}, + {"avt001.tot", "nuit"}, + {"avt002.tot", "campagne"}, + {"avt003.tot", "extsor1"}, + {"avt004.tot", "interieure"}, + {"avt005.tot", "zombie"}, + {"avt006.tot", "zombie"}, + {"avt007.tot", "campagne"}, + {"avt008.tot", "campagne"}, + {"avt009.tot", "extsor1"}, + {"avt010.tot", "extsor1"}, + {"avt011.tot", "interieure"}, + {"avt012.tot", "zombie"}, + {"avt014.tot", "nuit"}, + {"avt015.tot", "interieure"}, + {"avt016.tot", "statue"}, + {"avt017.tot", "zombie"}, + {"avt018.tot", "statue"}, + {"avt019.tot", "mine"}, + {"avt020.tot", "statue"}, + {"avt021.tot", "mine"}, + {"avt022.tot", "zombie"} + }; + + for (int i = 0; i < ARRAYSIZE(tracks); i++) + if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { + _cdrom->startTrack(tracks[i][1]); + break; + } +} + +void Sound::cdPlayMultMusic() { + if (!_cdrom) + return; + + static const char *tracks[][6] = { + {"avt005.tot", "fra1", "all1", "ang1", "esp1", "ita1"}, + {"avt006.tot", "fra2", "all2", "ang2", "esp2", "ita2"}, + {"avt012.tot", "fra3", "all3", "ang3", "esp3", "ita3"}, + {"avt016.tot", "fra4", "all4", "ang4", "esp4", "ita4"}, + {"avt019.tot", "fra5", "all5", "ang5", "esp5", "ita5"}, + {"avt022.tot", "fra6", "all6", "ang6", "esp6", "ita6"} + }; + + // Default to "ang?" for other languages (including EN_USA) + int language = _vm->_global->_language <= 4 ? _vm->_global->_language : 2; + for (int i = 0; i < ARRAYSIZE(tracks); i++) + if (!scumm_stricmp(_vm->_game->_curTotFile, tracks[i][0])) { + _cdrom->startTrack(tracks[i][language + 1]); + break; + } +} + +void Sound::cdPlay(const char *trackName) { + if (!_cdrom) + return; + + _cdrom->startTrack(trackName); +} + +void Sound::cdStop() { + if (!_cdrom) + return; + + _cdrom->stopPlaying(); +} + +bool Sound::cdIsPlaying() const { + if (!_cdrom) + return false; + + return _cdrom->isPlaying(); +} + +int32 Sound::cdGetTrackPos(const char *keyTrack) const { + if (!_cdrom) + return -1; + + return _cdrom->getTrackPos(keyTrack); +} + +const char *Sound::cdGetCurrentTrack() const { + if (!_cdrom) + return ""; + + return _cdrom->getCurTrack(); +} + +void Sound::cdTest(int trySubst, const char *label) { + if (!_cdrom) + return; + + _cdrom->testCD(trySubst, label); +} + +} // End of namespace Gob diff --git a/engines/gob/sound/sound.h b/engines/gob/sound/sound.h new file mode 100644 index 0000000000..81b48688c4 --- /dev/null +++ b/engines/gob/sound/sound.h @@ -0,0 +1,135 @@ +/* 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 GOB_SOUND_SOUND_H +#define GOB_SOUND_SOUND_H + +#include "gob/sound/sounddesc.h" +#include "gob/sound/pcspeaker.h" +#include "gob/sound/soundblaster.h" +#include "gob/sound/adlib.h" +#include "gob/sound/infogrames.h" +#include "gob/sound/cdrom.h" + +namespace Gob { + +class Sound { +public: + static const int kSoundsCount = 60; + + Sound(GobEngine *vm); + ~Sound(); + + static void convToSigned(byte *buffer, int length); + + // Samples + SoundDesc *sampleGetBySlot(int slot); + const SoundDesc *sampleGetBySlot(int slot) const; + int sampleGetNextFreeSlot() const; + + bool sampleLoad(SoundDesc *sndDesc, const char *fileName); + void sampleFree(SoundDesc *sndDesc, bool noteAdlib = false, int index = -1); + + + // SoundBlaster + void blasterPlay(SoundDesc *sndDesc, int16 repCount, + int16 frequency, int16 fadeLength = 0); + void blasterStop(int16 fadeLength, SoundDesc *sndDesc = 0); + + void blasterPlayComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs = 0, int8 sndCount = kSoundsCount); + void blasterStopComposition(); + + char blasterPlayingSound() const; + + void blasterSetRepeating(int32 repCount); + void blasterWaitEndPlay(bool interruptible = false, bool stopComp = true); + + + // PCSpeaker + void speakerOn(int16 frequency, int32 length = -1); + void speakerOff(); + void speakerOnUpdate(uint32 millis); + + + // AdLib + bool adlibLoad(const char *fileName); + bool adlibLoad(byte *data, uint32 size, int index = -1); + void adlibUnload(); + + void adlibPlayTrack(const char *trackname); + void adlibPlayBgMusic(); + + void adlibPlay(); + void adlibStop(); + + bool adlibIsPlaying() const; + + int adlibGetIndex() const; + bool adlibGetRepeating() const; + + void adlibSetRepeating(int32 repCount); + + + // Infogrames + bool infogramesLoadInstruments(const char *fileName); + bool infogramesLoadSong(const char *fileName); + + void infogramesPlay(); + void infogramesStop(); + + + // CD-ROM + void cdLoadLIC(const char *fname); + void cdUnloadLIC(); + + void cdPlayBgMusic(); + void cdPlayMultMusic(); + + void cdPlay(const char *trackName); + void cdStop(); + + bool cdIsPlaying() const; + + int32 cdGetTrackPos(const char *keyTrack = 0) const; + const char *cdGetCurrentTrack() const; + + void cdTest(int trySubst, const char *label); + +private: + GobEngine *_vm; + + SoundDesc _sounds[kSoundsCount]; + + PCSpeaker *_pcspeaker; + SoundBlaster *_blaster; + AdLib *_adlib; + Infogrames *_infogrames; + CDROM *_cdrom; +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_H diff --git a/engines/gob/sound/soundblaster.cpp b/engines/gob/sound/soundblaster.cpp new file mode 100644 index 0000000000..f5339404b4 --- /dev/null +++ b/engines/gob/sound/soundblaster.cpp @@ -0,0 +1,260 @@ +/* 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$ + * + */ + +#include "gob/sound/sound.h" + +namespace Gob { + +SoundBlaster::SoundBlaster(Audio::Mixer &mixer) : _mixer(&mixer) { + _playingSound = 0; + _curSoundDesc = 0; + + _rate = _mixer->getOutputRate(); + _end = true; + _data = 0; + _length = 0; + _freq = 0; + _repCount = 0; + + _offset = 0; + _offsetFrac = 0; + _offsetInc = 0; + + _cur = 0; + _last = 0; + + _fade = false; + _fadeVol = 65536; + _fadeVolStep = 0; + _fadeSamples = 0; + _curFadeSamples = 0; + + _compositionSamples = 0; + _compositionSampleCount = 0; + _compositionPos = -1; + + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_handle, + this, -1, 255, 0, false, true); +} + +SoundBlaster::~SoundBlaster() { + _mixer->stopHandle(_handle); +} + +bool SoundBlaster::isPlaying() const { + return !_end; +} + +char SoundBlaster::getPlayingSound() const { + return _playingSound; +} + +void SoundBlaster::stopSound(int16 fadeLength, SoundDesc *sndDesc) { + Common::StackLock slock(_mutex); + + if (sndDesc && (sndDesc != _curSoundDesc)) + return; + + if (fadeLength <= 0) { + _data = 0; + _end = true; + _playingSound = 0; + _curSoundDesc = 0; + return; + } + + _fade = true; + _fadeVol = 65536; + _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); + _fadeVolStep = MAX((int32) 1, (int32) (65536 / _fadeSamples)); + _curFadeSamples = 0; +} + +void SoundBlaster::setRepeating(int32 repCount) { + Common::StackLock slock(_mutex); + + _repCount = repCount; +} + +void SoundBlaster::stopComposition() { + if (_compositionPos != -1) { + stopSound(0); + _compositionPos = -1; + } +} + +void SoundBlaster::endComposition() { + _compositionPos = -1; +} + +void SoundBlaster::nextCompositionPos() { + int8 slot; + + while ((++_compositionPos < 50) && + ((slot = _composition[_compositionPos]) != -1)) { + if ((slot >= 0) && (slot < _compositionSampleCount)) { + SoundDesc &sample = _compositionSamples[slot]; + if (!sample.empty() && (sample.getType() == SOUND_SND)) { + setSample(sample, 1, 0, 0); + return; + } + } + if (_compositionPos == 49) + _compositionPos = -1; + } + _compositionPos = -1; +} + +void SoundBlaster::playComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs, int8 sndCount) { + + _compositionSamples = sndDescs; + _compositionSampleCount = sndCount; + + int i = -1; + do { + i++; + _composition[i] = composition[i]; + } while ((i < 50) && (composition[i] != -1)); + + _compositionPos = -1; + nextCompositionPos(); +} + +void SoundBlaster::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, + int16 fadeLength) { + + if (frequency <= 0) + frequency = sndDesc._frequency; + + _curSoundDesc = &sndDesc; + sndDesc._repCount = repCount - 1; + sndDesc._frequency = frequency; + + _data = (int8 *) sndDesc.getData(); + _length = sndDesc.size(); + _freq = frequency; + + _repCount = repCount; + _end = false; + _playingSound = 1; + + _offset = 0; + _offsetFrac = 0; + _offsetInc = (_freq << FRAC_BITS) / _rate; + + _last = _cur; + _cur = _data[0]; + + _curFadeSamples = 0; + if (fadeLength == 0) { + _fade = false; + _fadeVol = 65536; + _fadeSamples = 0; + _fadeVolStep = 0; + } else { + _fade = true; + _fadeVol = 0; + _fadeSamples = (int) (fadeLength * (((double) _rate) / 10.0)); + _fadeVolStep = - MAX((int32) 1, (int32) (65536 / _fadeSamples)); + } +} + +void SoundBlaster::playSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, + int16 fadeLength) { + Common::StackLock slock(_mutex); + + if (!_end) + return; + + setSample(sndDesc, repCount, frequency, fadeLength); +} + +void SoundBlaster::checkEndSample() { + if (_compositionPos != -1) + nextCompositionPos(); + else if ((_repCount == -1) || (--_repCount > 0)) { + _offset = 0; + _offsetFrac = 0; + _end = false; + _playingSound = 1; + } else { + _end = true; + _playingSound = 0; + } +} + +int SoundBlaster::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock slock(_mutex); + + for (int i = 0; i < numSamples; i++) { + if (!_data) + return i; + if (_end || (_offset >= _length)) + checkEndSample(); + if (_end) + return i; + + // Linear interpolation. See sound/rate.cpp + + int16 val = (_last + (((_cur - _last) * _offsetFrac + + FRAC_HALF) >> FRAC_BITS)) << 8; + *buffer++ = (val * _fadeVol) >> 16; + + _offsetFrac += _offsetInc; + + // Was there an integral change? + if (fracToInt(_offsetFrac) > 0) { + _last = _cur; + _cur = _data[_offset]; + _offset += fracToInt(_offsetFrac); + _offsetFrac &= FRAC_LO_MASK; + } + + if (_fade) { + + if (++_curFadeSamples >= _fadeSamples) { + if (_fadeVolStep > 0) { + _data = 0; + _end = true; + _playingSound = 0; + _compositionPos = -1; + _curSoundDesc = 0; + } else { + _fadeVol = 65536; + _fade = false; + } + } else + _fadeVol -= _fadeVolStep; + + if (_fadeVol < 0) + _fadeVol = 0; + + } + } + return numSamples; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/soundblaster.h b/engines/gob/sound/soundblaster.h new file mode 100644 index 0000000000..575d4994be --- /dev/null +++ b/engines/gob/sound/soundblaster.h @@ -0,0 +1,116 @@ +/* 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 GOB_SOUND_SOUNDBLASTER_H +#define GOB_SOUND_SOUNDBLASTER_H + +#include "common/mutex.h" +#include "common/frac.h" +#include "sound/audiostream.h" +#include "sound/mixer.h" +#include "sound/softsynth/pcspk.h" + +namespace Gob { + +class SoundBlaster : public Audio::AudioStream { +public: + char _playingSound; + + SoundBlaster(Audio::Mixer &mixer); + ~SoundBlaster(); + + bool loadSample(SoundDesc &sndDesc, const char *fileName); + void freeSample(SoundDesc &sndDesc); + + void playSample(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength = 0); + void stopSound(int16 fadeLength, SoundDesc *sndDesc = 0); + + void playComposition(int16 *composition, int16 freqVal, + SoundDesc *sndDescs = 0, int8 sndCount = 60); + void stopComposition(); + void endComposition(); + + bool isPlaying() const; + char getPlayingSound() const; + + void setRepeating(int32 repCount); + void waitEndPlay(bool interruptible = false, bool stopComp = true); + + static void convToSigned(byte *buffer, int length) { + while (length-- > 0) + *buffer++ ^= 0x80; + } + + 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: + Audio::Mixer *_mixer; + + Audio::SoundHandle *_activeHandle; + Audio::SoundHandle _compositionHandle; + + SoundDesc *_compositionSamples; + int8 _compositionSampleCount; + 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; + + uint32 _offset; + frac_t _offsetFrac; + frac_t _offsetInc; + + int16 _cur; + int16 _last; + + bool _fade; + int32 _fadeVol; + int32 _fadeVolStep; + uint8 _fadeLength; + uint32 _fadeSamples; + uint32 _curFadeSamples; + + void setSample(SoundDesc &sndDesc, int16 repCount, + int16 frequency, int16 fadeLength); + void checkEndSample(); + void nextCompositionPos(); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_SOUNDBLASTER_H diff --git a/engines/gob/sound/sounddesc.cpp b/engines/gob/sound/sounddesc.cpp new file mode 100644 index 0000000000..e0885d9faa --- /dev/null +++ b/engines/gob/sound/sounddesc.cpp @@ -0,0 +1,116 @@ +/* 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$ + * + */ + +#include "common/util.h" + +#include "gob/sound/sounddesc.h" + +namespace Gob { + +SoundDesc::SoundDesc() { + _data = _dataPtr = 0; + _size = 0; + + _type = SOUND_SND; + _source = SOUND_FILE; + + _repCount = 0; + _frequency = 0; + _flag = 0; + _id = 0; +} + +SoundDesc::~SoundDesc() { + free(); +} + +void SoundDesc::set(SoundType type, SoundSource src, + byte *data, uint32 dSize) { + + free(); + + _type = type; + _source = src; + _data = _dataPtr = data; + _size = dSize; +} + +void SoundDesc::load(SoundType type, SoundSource src, + byte *data, uint32 dSize) { + + free(); + + _source = src; + switch (type) { + case SOUND_ADL: + loadADL(data, dSize); + break; + case SOUND_SND: + loadSND(data, dSize); + break; + } +} + +void SoundDesc::free() { + if (_source != SOUND_TOT) + delete[] _data; + _data = _dataPtr = 0; + _id = 0; +} + +void SoundDesc::convToSigned() { + if ((_type == SOUND_SND) && _data && _dataPtr) + for (uint32 i = 0; i < _size; i++) + _dataPtr[i] ^= 0x80; +} + +int16 SoundDesc::calcFadeOutLength(int16 frequency) { + return (10 * (_size / 2)) / frequency; +} + +uint32 SoundDesc::calcLength(int16 repCount, int16 frequency, bool fade) { + uint32 fadeSize = fade ? _size / 2 : 0; + return ((_size * repCount - fadeSize) * 1000) / frequency; +} + +void SoundDesc::loadSND(byte *data, uint32 dSize) { + assert(dSize > 6); + + _type = SOUND_SND; + _data = data; + _dataPtr = data + 6; + _frequency = MAX((int16) READ_BE_UINT16(data + 4), (int16) 4700); + _flag = data[0] ? (data[0] & 0x7F) : 8; + data[0] = 0; + _size = MIN(READ_BE_UINT32(data), dSize - 6); +} + +void SoundDesc::loadADL(byte *data, uint32 dSize) { + _type = SOUND_ADL; + _data = _dataPtr = data; + _size = dSize; +} + +} // End of namespace Gob diff --git a/engines/gob/sound/sounddesc.h b/engines/gob/sound/sounddesc.h new file mode 100644 index 0000000000..ed4447254c --- /dev/null +++ b/engines/gob/sound/sounddesc.h @@ -0,0 +1,85 @@ +/* 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 GOB_SOUND_SOUNDDESC_H +#define GOB_SOUND_SOUNDDESC_H + +#include "common/endian.h" + +namespace Gob { + +enum SoundType { + SOUND_SND, + SOUND_ADL +}; + +enum SoundSource { + SOUND_FILE, + SOUND_TOT, + SOUND_EXT +}; + +class SoundDesc { +public: + int16 _repCount; + int16 _frequency; + int16 _flag; + int16 _id; + + byte *getData() { return _dataPtr; } + + uint32 size() const { return _size; } + bool empty() const { return !_dataPtr; } + SoundType getType() const { return _type; } + + bool isId(int16 id) const { return _dataPtr && (_id == id); } + + void set(SoundType type, SoundSource src, byte *data, uint32 dSize); + void load(SoundType type, SoundSource src, byte *data, uint32 dSize); + void free(); + void convToSigned(); + + // Which fade out length to use when the fade starts half-way through? + int16 calcFadeOutLength(int16 frequency); + uint32 calcLength(int16 repCount, int16 frequency, bool fade); + + SoundDesc(); + ~SoundDesc(); + +private: + byte *_data; + byte *_dataPtr; + uint32 _size; + + SoundType _type; + SoundSource _source; + + void loadSND(byte *data, uint32 dSize); + void loadADL(byte *data, uint32 dSize); +}; + +} // End of namespace Gob + +#endif // GOB_SOUND_SOUNDDESC_H diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp index 8e573ddb1a..4987426fe0 100644 --- a/engines/gob/util.cpp +++ b/engines/gob/util.cpp @@ -23,7 +23,6 @@ * */ - #include "common/events.h" #include "gob/gob.h" @@ -32,8 +31,8 @@ #include "gob/dataio.h" #include "gob/draw.h" #include "gob/game.h" -#include "gob/sound.h" #include "gob/video.h" +#include "gob/sound/sound.h" namespace Gob { @@ -60,7 +59,7 @@ void Util::beep(int16 freq) { if (_vm->_global->_soundFlags == 0) return; - _vm->_snd->speakerOn(freq, 50); + _vm->_sound->speakerOn(freq, 50); } void Util::delay(uint16 msecs) { diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index 9a004318b8..e1777681df 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "graphics/cursorman.h" diff --git a/engines/gob/video_v1.cpp b/engines/gob/video_v1.cpp index 4ed3b04bad..3c9627c041 100644 --- a/engines/gob/video_v1.cpp +++ b/engines/gob/video_v1.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" diff --git a/engines/gob/video_v2.cpp b/engines/gob/video_v2.cpp index 52b349ca67..ab0c7e52db 100644 --- a/engines/gob/video_v2.cpp +++ b/engines/gob/video_v2.cpp @@ -23,7 +23,6 @@ * */ - #include "common/endian.h" #include "gob/gob.h" -- cgit v1.2.3