diff options
author | Gregory Montoir | 2007-05-19 12:08:41 +0000 |
---|---|---|
committer | Gregory Montoir | 2007-05-19 12:08:41 +0000 |
commit | bde5404a4eb773fccf4a2d43b56342773c698606 (patch) | |
tree | 6a71ab3227edf56a2b4f6dad5c47633573975071 /engines/cine | |
parent | 620c8a5647d1c51a4ca1803acf5924e3099e1d56 (diff) | |
download | scummvm-rg350-bde5404a4eb773fccf4a2d43b56342773c698606.tar.gz scummvm-rg350-bde5404a4eb773fccf4a2d43b56342773c698606.tar.bz2 scummvm-rg350-bde5404a4eb773fccf4a2d43b56342773c698606.zip |
added basic support for Amiga music playback
svn-id: r26870
Diffstat (limited to 'engines/cine')
-rw-r--r-- | engines/cine/cine.cpp | 18 | ||||
-rw-r--r-- | engines/cine/main_loop.cpp | 9 | ||||
-rw-r--r-- | engines/cine/module.mk | 3 | ||||
-rw-r--r-- | engines/cine/script.cpp | 131 | ||||
-rw-r--r-- | engines/cine/sfx_player.cpp | 196 | ||||
-rw-r--r-- | engines/cine/sfx_player.h | 74 | ||||
-rw-r--r-- | engines/cine/sound.cpp (renamed from engines/cine/sound_driver.cpp) | 524 | ||||
-rw-r--r-- | engines/cine/sound.h | 129 | ||||
-rw-r--r-- | engines/cine/sound_driver.h | 182 | ||||
-rw-r--r-- | engines/cine/various.cpp | 4 |
10 files changed, 626 insertions, 644 deletions
diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp index c6fde9cbba..224721b096 100644 --- a/engines/cine/cine.cpp +++ b/engines/cine/cine.cpp @@ -39,15 +39,13 @@ #include "cine/main_loop.h" #include "cine/object.h" #include "cine/texte.h" -#include "cine/sfx_player.h" -#include "cine/sound_driver.h" +#include "cine/sound.h" #include "cine/various.h" namespace Cine { -SoundDriver *g_soundDriver; -SfxPlayer *g_sfxPlayer; +Sound *g_sound; Common::SaveFileManager *g_saveFileMan; CineEngine *g_cine; @@ -96,16 +94,11 @@ int CineEngine::init() { _system->endGFXTransaction(); if (g_cine->getPlatform() == Common::kPlatformPC) { - if (g_cine->getGameType() == GType_FW) { - g_soundDriver = new AdlibSoundDriverINS(_mixer); - } else { - g_soundDriver = new AdlibSoundDriverADL(_mixer); - } + g_sound = new PCSound(_mixer, this); } else { // Paula chipset for Amiga and Atari versions - g_soundDriver = new PaulaSoundDriver(_mixer); + g_sound = new PaulaSound(_mixer, this); } - g_sfxPlayer = new SfxPlayer(g_soundDriver); g_saveFileMan = _saveFileMan; initialize(); @@ -118,8 +111,7 @@ int CineEngine::go() { mainLoop(1); - delete g_sfxPlayer; - delete g_soundDriver; + delete g_sound; return 0; } diff --git a/engines/cine/main_loop.cpp b/engines/cine/main_loop.cpp index 33f25a43e4..face2628dd 100644 --- a/engines/cine/main_loop.cpp +++ b/engines/cine/main_loop.cpp @@ -29,10 +29,9 @@ #include "cine/main_loop.h" #include "cine/object.h" -#include "cine/sfx_player.h" #include "cine/various.h" #include "cine/bg_list.h" -#include "cine/sound_driver.h" +#include "cine/sound.h" namespace Cine { @@ -157,7 +156,7 @@ void manageEvents(int count) { if (i % 2) g_system->updateScreen(); g_system->delayMillis(10); - g_soundDriver->update(); + g_sound->update(); manageEvents(0); } } @@ -246,7 +245,7 @@ void CineEngine::mainLoop(int bootScriptIdx) { strcpy(currentCtName, ""); strcpy(currentPartName, ""); - g_sfxPlayer->stop(); + g_sound->stopMusic(); } do { @@ -335,7 +334,7 @@ void CineEngine::mainLoop(int bootScriptIdx) { } while (!exitEngine && !quitFlag && var21 != 7); hideMouse(); - g_sfxPlayer->stop(); + g_sound->stopMusic(); freeAnimDataTable(); unloadAllMasks(); freePrcLinkedList(); diff --git a/engines/cine/module.mk b/engines/cine/module.mk index f427415e0c..07e267289f 100644 --- a/engines/cine/module.mk +++ b/engines/cine/module.mk @@ -15,8 +15,7 @@ MODULE_OBJS = \ prc.o \ rel.o \ script.o \ - sfx_player.o \ - sound_driver.o \ + sound.o \ texte.o \ unpack.o \ various.o diff --git a/engines/cine/script.cpp b/engines/cine/script.cpp index fb4a681e16..3b2510c2e7 100644 --- a/engines/cine/script.cpp +++ b/engines/cine/script.cpp @@ -28,8 +28,7 @@ #include "cine/cine.h" #include "cine/bg_list.h" #include "cine/object.h" -#include "cine/sfx_player.h" -#include "cine/sound_driver.h" +#include "cine/sound.h" #include "cine/various.h" namespace Cine { @@ -1509,44 +1508,22 @@ void o1_loadMusic() { const char *param = getNextString(); debugC(5, kCineDebugScript, "Line: %d: loadMusic(%s)", _currentLine, param); - - if (g_cine->getPlatform() == Common::kPlatformAmiga || - g_cine->getPlatform() == Common::kPlatformAtariST) { - warning("STUB: o1_loadMusic"); - return; - } - - g_sfxPlayer->load(param); + g_sound->loadMusic(param); } void o1_playMusic() { debugC(5, kCineDebugScript, "Line: %d: playMusic()", _currentLine); - if (g_cine->getPlatform() == Common::kPlatformAmiga || - g_cine->getPlatform() == Common::kPlatformAtariST) { - warning("STUB: o1_playMusic"); - return; - } - g_sfxPlayer->play(); + g_sound->playMusic(); } void o1_fadeOutMusic() { debugC(5, kCineDebugScript, "Line: %d: fadeOutMusic()", _currentLine); - if (g_cine->getPlatform() == Common::kPlatformAmiga || - g_cine->getPlatform() == Common::kPlatformAtariST) { - warning("STUB: o1_fadeOutMusic"); - return; - } - g_sfxPlayer->fadeOut(); + g_sound->fadeOutMusic(); } void o1_stopSample() { debugC(5, kCineDebugScript, "Line: %d: stopSample()", _currentLine); - if (g_cine->getPlatform() == Common::kPlatformAmiga || - g_cine->getPlatform() == Common::kPlatformAtariST) { - warning("STUB: o1_stopSample"); - return; - } - g_sfxPlayer->stop(); + g_sound->stopMusic(); } void o1_op71() { @@ -1571,74 +1548,59 @@ void o1_op73() { getNextWord(); } -void o1_playSampleAmiga() { - int num = getNextByte(); - int channel = getNextByte(); - int freq = getNextWord(); - int repeat = getNextByte(); - int volume = getNextWord(); - int size = getNextWord(); - - if (size == 0xFFFF) { - size = animDataTable[num].width * animDataTable[num].height; - } - - if (channel < 10) { // || _currentOpcode == 0x78 - int channel1, channel2; - if (channel == 0) { - channel1 = 0; - channel2 = 1; - } else { - channel1 = 2; - channel2 = 3; - } - ((PaulaSoundDriver *)g_soundDriver)->queueSound(channel1, freq, animDataTable[num].ptr1, size, -1, volume, 63, repeat); - ((PaulaSoundDriver *)g_soundDriver)->queueSound(channel2, freq, animDataTable[num].ptr1, size, 1, volume, 0, repeat); - } else { - channel -= 10; - if (volume > 63) { - volume = 63; - } - ((PaulaSoundDriver *)g_soundDriver)->queueSound(channel, freq, animDataTable[num].ptr1, size, 0, 0, volume, repeat); - } -} - void o1_playSample() { debugC(5, kCineDebugScript, "Line: %d: playSample()", _currentLine); - if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) { - o1_playSampleAmiga(); - return; - } - byte anim = getNextByte(); byte channel = getNextByte(); - getNextWord(); - getNextByte(); + uint16 freq = getNextWord(); + byte repeat = getNextByte(); int16 volume = getNextWord(); - uint16 flag = getNextWord(); + uint16 size = getNextWord(); - if (volume > 63) - volume = 63; - if (volume < 0) - volume = 63; + if (!animDataTable[anim].ptr1) { + return; + } - if (animDataTable[anim].ptr1) { + if (g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) { + if (size == 0xFFFF) { + size = animDataTable[anim].width * animDataTable[anim].height; + } + if (channel < 10) { // || _currentOpcode == 0x78 + int channel1, channel2; + if (channel == 0) { + channel1 = 0; + channel2 = 1; + } else { + channel1 = 2; + channel2 = 3; + } + g_sound->playSound(channel1, freq, animDataTable[anim].ptr1, size, -1, volume, 63, repeat); + g_sound->playSound(channel2, freq, animDataTable[anim].ptr1, size, 1, volume, 0, repeat); + } else { + channel -= 10; + if (volume > 63) { + volume = 63; + } + g_sound->playSound(channel, freq, animDataTable[anim].ptr1, size, 0, 0, volume, repeat); + } + } else { + if (volume > 63 || volume < 0) { + volume = 63; + } if (channel >= 10) { channel -= 10; } if (volume < 50) { volume = 50; } - - g_sfxPlayer->stop(); - - if (flag == 0xFFFF) { - g_soundDriver->playSound(animDataTable[anim].ptr1, 0, channel, volume); + g_sound->stopMusic(); + if (size == 0xFFFF) { + g_sound->playSound(channel, 0, animDataTable[anim].ptr1, 0, 0, 0, volume, 0); } else { - g_soundDriver->resetChannel(channel); + g_sound->stopSound(channel); } } } @@ -1689,12 +1651,12 @@ void o2_playSample() { } void o2_playSampleAlt() { - int num = getNextByte(); - int channel = getNextByte(); - int freq = getNextWord(); + byte num = getNextByte(); + byte channel = getNextByte(); + uint16 frequency = getNextWord(); getNextByte(); getNextWord(); - int size = getNextWord(); + uint16 size = getNextWord(); if (size == 0xFFFF) { size = animDataTable[num].width * animDataTable[num].height; @@ -1704,8 +1666,7 @@ void o2_playSampleAlt() { // if speaker output is enabled, play sound on it // if it's another device, don't play anything } else { - g_soundDriver->setChannelFrequency(channel, freq); - g_soundDriver->playSound(animDataTable[num].ptr1, size, channel, 63); + g_sound->playSound(channel, frequency, animDataTable[num].ptr1, size, 0, 0, 63, 0); } } } diff --git a/engines/cine/sfx_player.cpp b/engines/cine/sfx_player.cpp deleted file mode 100644 index 86ca2754a8..0000000000 --- a/engines/cine/sfx_player.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2006 The ScummVM project - * - * cinE Engine is (C) 2004-2005 by CinE Team - * - * 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/stdafx.h" -#include "common/endian.h" -#include "common/system.h" - -#include "cine/cine.h" -#include "cine/sfx_player.h" -#include "cine/sound_driver.h" -#include "cine/unpack.h" -#include "cine/various.h" - -namespace Cine { - -SfxPlayer::SfxPlayer(SoundDriver *driver) - : _playing(false), _driver(driver) { - memset(_instrumentsData, 0, sizeof(_instrumentsData)); - _sfxData = NULL; - _fadeOutCounter = 0; - _driver->setUpdateCallback(updateCallback, this); -} - -SfxPlayer::~SfxPlayer() { - _driver->setUpdateCallback(NULL, NULL); - if (_playing) { - stop(); - } -} - -bool SfxPlayer::load(const char *song) { - debug(9, "SfxPlayer::load('%s')", song); - - /* stop (w/ fade out) the previous song */ - while (_fadeOutCounter != 0 && _fadeOutCounter < 100) { - g_system->delayMillis(50); - } - _fadeOutCounter = 0; - - if (_playing) { - stop(); - } - - /* like the original PC version, skip introduction song (file doesn't exist) */ - if (g_cine->getGameType() == Cine::GType_OS && strncmp(song, "INTRO", 5) == 0) { - return 0; - } - - _sfxData = readBundleSoundFile(song); - if (!_sfxData) { - warning("Unable to load soundfx module '%s'", song); - return 0; - } - - for (int i = 0; i < NUM_INSTRUMENTS; ++i) { - _instrumentsData[i] = NULL; - - char instrument[13]; - memcpy(instrument, _sfxData + 20 + i * 30, 12); - instrument[12] = '\0'; - - if (strlen(instrument) != 0) { - char *dot = strrchr(instrument, '.'); - if (dot) { - *dot = '\0'; - } - strcat(instrument, _driver->getInstrumentExtension()); - _instrumentsData[i] = readBundleSoundFile(instrument); - if (!_instrumentsData[i]) { - warning("Unable to load soundfx instrument '%s'", instrument); - } - } - } - return 1; -} - -void SfxPlayer::play() { - debug(9, "SfxPlayer::play()"); - if (_sfxData) { - for (int i = 0; i < NUM_CHANNELS; ++i) { - _instrumentsChannelTable[i] = -1; - } - _currentPos = 0; - _currentOrder = 0; - _numOrders = _sfxData[470]; - _eventsDelay = (252 - _sfxData[471]) * 50 / 1060; - _updateTicksCounter = 0; - _playing = true; - } -} - -void SfxPlayer::stop() { - if (_playing || _fadeOutCounter != 0) { - _fadeOutCounter = 0; - _playing = false; - for (int i = 0; i < NUM_CHANNELS; ++i) { - _driver->stopChannel(i); - } - _driver->stopSound(); - unload(); - } -} - -void SfxPlayer::fadeOut() { - if (_playing) { - _fadeOutCounter = 1; - _playing = false; - } -} - -void SfxPlayer::updateCallback(void *ref) { - ((SfxPlayer *)ref)->update(); -} - -void SfxPlayer::update() { - if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) { - ++_updateTicksCounter; - if (_updateTicksCounter > _eventsDelay) { - handleEvents(); - _updateTicksCounter = 0; - } - } -} - -void SfxPlayer::handleEvents() { - const byte *patternData = _sfxData + 600; - const byte *orderTable = _sfxData + 472; - uint16 patternNum = orderTable[_currentOrder] * 1024; - - for (int i = 0; i < 4; ++i) { - handlePattern(i, patternData + patternNum + _currentPos); - patternData += 4; - } - - if (_fadeOutCounter != 0 && _fadeOutCounter < 100) { - _fadeOutCounter += 2; - } - _currentPos += 16; - if (_currentPos >= 1024) { - _currentPos = 0; - ++_currentOrder; - if (_currentOrder == _numOrders) { - _currentOrder = 0; - } - } - debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos); -} - -void SfxPlayer::handlePattern(int channel, const byte *patternData) { - int instrument = patternData[2] >> 4; - if (instrument != 0) { - --instrument; - if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) { - _instrumentsChannelTable[channel] = instrument; - const int volume = _sfxData[instrument] - _fadeOutCounter; - _driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume); - } - } - int16 freq = (int16)READ_BE_UINT16(patternData); - if (freq > 0) { - _driver->stopChannel(channel); - _driver->setChannelFrequency(channel, freq); - } -} - -void SfxPlayer::unload() { - for (int i = 0; i < NUM_INSTRUMENTS; ++i) { - free(_instrumentsData[i]); - _instrumentsData[i] = NULL; - } - free(_sfxData); - _sfxData = NULL; -} - -} // End of namespace Cine diff --git a/engines/cine/sfx_player.h b/engines/cine/sfx_player.h deleted file mode 100644 index 373b2d30cc..0000000000 --- a/engines/cine/sfx_player.h +++ /dev/null @@ -1,74 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2006 The ScummVM project - * - * cinE Engine is (C) 2004-2005 by CinE Team - * - * 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 CINE_SFXPLAYER_H -#define CINE_SFXPLAYER_H - -namespace Cine { - -class SoundDriver; - -class SfxPlayer { -public: - - enum { - NUM_INSTRUMENTS = 15, - NUM_CHANNELS = 4 - }; - - SfxPlayer(SoundDriver *driver); - ~SfxPlayer(); - - bool load(const char *song); - void play(); - void stop(); - void fadeOut(); - - static void updateCallback(void *ref); - -private: - - void update(); - void handleEvents(); - void handlePattern(int channel, const byte *patternData); - void unload(); - - bool _playing; - int _currentPos; - int _currentOrder; - int _numOrders; - int _eventsDelay; - int _fadeOutCounter; - int _updateTicksCounter; - int _instrumentsChannelTable[NUM_CHANNELS]; - byte *_sfxData; - byte *_instrumentsData[NUM_INSTRUMENTS]; - SoundDriver *_driver; -}; - -extern SfxPlayer *g_sfxPlayer; // TEMP - -} // End of namespace Cine - -#endif /* _SFXPLAYER_H_ */ diff --git a/engines/cine/sound_driver.cpp b/engines/cine/sound.cpp index dfc5de125f..9a8d073c51 100644 --- a/engines/cine/sound_driver.cpp +++ b/engines/cine/sound.cpp @@ -24,20 +24,204 @@ #include "common/stdafx.h" #include "common/endian.h" +#include "common/file.h" +#include "common/system.h" #include "cine/cine.h" -#include "cine/sound_driver.h" +#include "cine/sound.h" -#include "sound/mixer.h" +#include "sound/audiostream.h" +#include "sound/fmopl.h" +#include "sound/mods/soundfx.h" namespace Cine { -void SoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) { +class PCSoundDriver { +public: + typedef void (*UpdateCallback)(void *); + + virtual ~PCSoundDriver() {} + + virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0; + virtual void setChannelFrequency(int channel, int frequency) = 0; + virtual void stopChannel(int channel) = 0; + virtual void playSample(const byte *data, int size, int channel, int volume) = 0; + virtual void stopAll() = 0; + virtual const char *getInstrumentExtension() const { return ""; } + + void setUpdateCallback(UpdateCallback upCb, void *ref); + void resetChannel(int channel); + void findNote(int freq, int *note, int *oct) const; + +protected: + UpdateCallback _upCb; + void *_upRef; + + static const int _noteTable[]; + static const int _noteTableCount; +}; + +const int PCSoundDriver::_noteTable[] = { + 0xEEE, 0xE17, 0xD4D, 0xC8C, 0xBD9, 0xB2F, 0xA8E, 0x9F7, + 0x967, 0x8E0, 0x861, 0x7E8, 0x777, 0x70B, 0x6A6, 0x647, + 0x5EC, 0x597, 0x547, 0x4FB, 0x4B3, 0x470, 0x430, 0x3F4, + 0x3BB, 0x385, 0x353, 0x323, 0x2F6, 0x2CB, 0x2A3, 0x27D, + 0x259, 0x238, 0x218, 0x1FA, 0x1DD, 0x1C2, 0x1A9, 0x191, + 0x17B, 0x165, 0x151, 0x13E, 0x12C, 0x11C, 0x10C, 0x0FD, + 0x0EE, 0x0E1, 0x0D4, 0x0C8, 0x0BD, 0x0B2, 0x0A8, 0x09F, + 0x096, 0x08E, 0x086, 0x07E, 0x077, 0x070, 0x06A, 0x064, + 0x05E, 0x059, 0x054, 0x04F, 0x04B, 0x047, 0x043, 0x03F, + 0x03B, 0x038, 0x035, 0x032, 0x02F, 0x02C, 0x02A, 0x027, + 0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0x01A, 0x019, + 0x017, 0x016, 0x015, 0x013, 0x012, 0x011, 0x010, 0x00F +}; + +const int PCSoundDriver::_noteTableCount = ARRAYSIZE(_noteTable); + +struct AdlibRegisterSoundInstrument { + uint16 vibrato; + uint16 attackDecay; + uint16 sustainRelease; + uint16 feedbackStrength; + uint16 keyScaling; + uint16 outputLevel; + uint16 freqMod; +}; + +struct AdlibSoundInstrument { + byte mode; + byte channel; + AdlibRegisterSoundInstrument regMod; + AdlibRegisterSoundInstrument regCar; + byte waveSelectMod; + byte waveSelectCar; + byte amDepth; +}; + +class AdlibSoundDriver : public PCSoundDriver, Audio::AudioStream { +public: + AdlibSoundDriver(Audio::Mixer *mixer); + virtual ~AdlibSoundDriver(); + + // PCSoundDriver interface + virtual void setupChannel(int channel, const byte *data, int instrument, int volume); + virtual void stopChannel(int channel); + virtual void stopAll(); + + // AudioStream interface + virtual int readBuffer(int16 *buffer, const int numSamples); + virtual bool isStereo() const { return false; } + virtual bool endOfData() const { return false; } + virtual int getRate() const { return _sampleRate; } + + void initCard(); + void update(int16 *buf, int len); + void setupInstrument(const byte *data, int channel); + void loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg); + virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi) = 0; + +protected: + FM_OPL *_opl; + int _sampleRate; + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + + byte _vibrato; + int _channelsVolumeTable[4]; + AdlibSoundInstrument _instrumentsTable[4]; + + static const int _freqTable[]; + static const int _freqTableCount; + static const int _operatorsTable[]; + static const int _operatorsTableCount; + static const int _voiceOperatorsTable[]; + static const int _voiceOperatorsTableCount; +}; + +const int AdlibSoundDriver::_freqTable[] = { + 0x157, 0x16C, 0x181, 0x198, 0x1B1, 0x1CB, + 0x1E6, 0x203, 0x222, 0x243, 0x266, 0x28A +}; + +const int AdlibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable); + +const int AdlibSoundDriver::_operatorsTable[] = { + 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 +}; + +const int AdlibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable); + +const int AdlibSoundDriver::_voiceOperatorsTable[] = { + 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 16, 14, 14, 17, 17, 13, 13 +}; + +const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable); + +// Future Wars Adlib driver +class AdlibSoundDriverINS : public AdlibSoundDriver { +public: + AdlibSoundDriverINS(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {} + virtual const char *getInstrumentExtension() const { return ".INS"; } + virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi); + virtual void setChannelFrequency(int channel, int frequency); + virtual void playSample(const byte *data, int size, int channel, int volume); +}; + +// Operation Stealth Adlib driver +class AdlibSoundDriverADL : public AdlibSoundDriver { +public: + AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {} + virtual const char *getInstrumentExtension() const { return ".ADL"; } + virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi); + virtual void setChannelFrequency(int channel, int frequency); + virtual void playSample(const byte *data, int size, int channel, int volume); +}; + +class PCSoundFxPlayer { +public: + + PCSoundFxPlayer(PCSoundDriver *driver); + ~PCSoundFxPlayer(); + + bool load(const char *song); + void play(); + void stop(); + void fadeOut(); + + static void updateCallback(void *ref); + + enum { + NUM_INSTRUMENTS = 15, + NUM_CHANNELS = 4 + }; + +private: + + void update(); + void handleEvents(); + void handlePattern(int channel, const byte *patternData); + void unload(); + + bool _playing; + int _currentPos; + int _currentOrder; + int _numOrders; + int _eventsDelay; + int _fadeOutCounter; + int _updateTicksCounter; + int _instrumentsChannelTable[NUM_CHANNELS]; + byte *_sfxData; + byte *_instrumentsData[NUM_INSTRUMENTS]; + PCSoundDriver *_driver; +}; + + +void PCSoundDriver::setUpdateCallback(UpdateCallback upCb, void *ref) { _upCb = upCb; _upRef = ref; } -void SoundDriver::findNote(int freq, int *note, int *oct) const { +void PCSoundDriver::findNote(int freq, int *note, int *oct) const { *note = _noteTableCount - 1; for (int i = 0; i < _noteTableCount; ++i) { if (_noteTable[i] <= freq) { @@ -48,9 +232,9 @@ void SoundDriver::findNote(int freq, int *note, int *oct) const { *oct = *note / 12; } -void SoundDriver::resetChannel(int channel) { +void PCSoundDriver::resetChannel(int channel) { stopChannel(channel); - stopSound(); + stopAll(); } AdlibSoundDriver::AdlibSoundDriver(Audio::Mixer *mixer) @@ -99,7 +283,7 @@ void AdlibSoundDriver::stopChannel(int channel) { } } -void AdlibSoundDriver::stopSound() { +void AdlibSoundDriver::stopAll() { int i; for (i = 0; i < 18; ++i) { OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 63); @@ -119,7 +303,7 @@ void AdlibSoundDriver::initCard() { _vibrato = 0x20; OPLWriteReg(_opl, 0xBD, _vibrato); OPLWriteReg(_opl, 0x08, 0x40); - + int i; for (i = 0; i < 18; ++i) { OPLWriteReg(_opl, 0x40 | _operatorsTable[i], 0); @@ -182,7 +366,7 @@ void AdlibSoundDriver::setupInstrument(const byte *data, int channel) { mod = _operatorsTable[_voiceOperatorsTable[2 * channel + 0]]; car = _operatorsTable[_voiceOperatorsTable[2 * channel + 1]]; } - + if (ins->mode == 0 || ins->channel == 6) { reg = &ins->regMod; OPLWriteReg(_opl, 0x20 | mod, reg->vibrato); @@ -228,18 +412,18 @@ void AdlibSoundDriver::loadRegisterInstrument(const byte *data, AdlibRegisterSou reg->vibrato |= 0x10; } reg->vibrato |= READ_LE_UINT16(data + 2) & 0xF; // frequency multiplier - + reg->attackDecay = READ_LE_UINT16(data + 6) << 4; // attack rate reg->attackDecay |= READ_LE_UINT16(data + 12) & 0xF; // decay rate - + reg->sustainRelease = READ_LE_UINT16(data + 8) << 4; // sustain level reg->sustainRelease |= READ_LE_UINT16(data + 14) & 0xF; // release rate - + reg->feedbackStrength = READ_LE_UINT16(data + 4) << 1; // feedback if (READ_LE_UINT16(data + 24) == 0) { // frequency modulation reg->feedbackStrength |= 1; } - + reg->keyScaling = READ_LE_UINT16(data); reg->outputLevel = READ_LE_UINT16(data + 16); reg->freqMod = READ_LE_UINT16(data + 24); @@ -281,7 +465,7 @@ void AdlibSoundDriverINS::setChannelFrequency(int channel, int frequency) { } } -void AdlibSoundDriverINS::playSound(const byte *data, int size, int channel, int volume) { +void AdlibSoundDriverINS::playSample(const byte *data, int size, int channel, int volume) { assert(channel < 4); _channelsVolumeTable[channel] = 127; resetChannel(channel); @@ -330,7 +514,7 @@ void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) { } int freq, note, oct; findNote(frequency, ¬e, &oct); - + note += oct * 12; if (ins->amDepth) { note = ins->amDepth; @@ -352,7 +536,7 @@ void AdlibSoundDriverADL::setChannelFrequency(int channel, int frequency) { } } -void AdlibSoundDriverADL::playSound(const byte *data, int size, int channel, int volume) { +void AdlibSoundDriverADL::playSample(const byte *data, int size, int channel, int volume) { assert(channel < 4); _channelsVolumeTable[channel] = 127; setupInstrument(data, channel); @@ -389,107 +573,277 @@ void AdlibSoundDriverADL::playSound(const byte *data, int size, int channel, int } } -const int SoundDriver::_noteTable[] = { - 0xEEE, 0xE17, 0xD4D, 0xC8C, 0xBD9, 0xB2F, 0xA8E, 0x9F7, - 0x967, 0x8E0, 0x861, 0x7E8, 0x777, 0x70B, 0x6A6, 0x647, - 0x5EC, 0x597, 0x547, 0x4FB, 0x4B3, 0x470, 0x430, 0x3F4, - 0x3BB, 0x385, 0x353, 0x323, 0x2F6, 0x2CB, 0x2A3, 0x27D, - 0x259, 0x238, 0x218, 0x1FA, 0x1DD, 0x1C2, 0x1A9, 0x191, - 0x17B, 0x165, 0x151, 0x13E, 0x12C, 0x11C, 0x10C, 0x0FD, - 0x0EE, 0x0E1, 0x0D4, 0x0C8, 0x0BD, 0x0B2, 0x0A8, 0x09F, - 0x096, 0x08E, 0x086, 0x07E, 0x077, 0x070, 0x06A, 0x064, - 0x05E, 0x059, 0x054, 0x04F, 0x04B, 0x047, 0x043, 0x03F, - 0x03B, 0x038, 0x035, 0x032, 0x02F, 0x02C, 0x02A, 0x027, - 0x025, 0x023, 0x021, 0x01F, 0x01D, 0x01C, 0x01A, 0x019, - 0x017, 0x016, 0x015, 0x013, 0x012, 0x011, 0x010, 0x00F -}; +PCSoundFxPlayer::PCSoundFxPlayer(PCSoundDriver *driver) + : _playing(false), _driver(driver) { + memset(_instrumentsData, 0, sizeof(_instrumentsData)); + _sfxData = NULL; + _fadeOutCounter = 0; + _driver->setUpdateCallback(updateCallback, this); +} -const int SoundDriver::_noteTableCount = ARRAYSIZE(_noteTable); +PCSoundFxPlayer::~PCSoundFxPlayer() { + _driver->setUpdateCallback(NULL, NULL); + if (_playing) { + stop(); + } +} -const int AdlibSoundDriver::_freqTable[] = { - 0x157, 0x16C, 0x181, 0x198, 0x1B1, 0x1CB, - 0x1E6, 0x203, 0x222, 0x243, 0x266, 0x28A -}; +bool PCSoundFxPlayer::load(const char *song) { + debug(9, "PCSoundFxPlayer::load('%s')", song); -const int AdlibSoundDriver::_freqTableCount = ARRAYSIZE(_freqTable); + /* stop (w/ fade out) the previous song */ + while (_fadeOutCounter != 0 && _fadeOutCounter < 100) { + g_system->delayMillis(50); + } + _fadeOutCounter = 0; -const int AdlibSoundDriver::_operatorsTable[] = { - 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 -}; + if (_playing) { + stop(); + } -const int AdlibSoundDriver::_operatorsTableCount = ARRAYSIZE(_operatorsTable); + _sfxData = readBundleSoundFile(song); + if (!_sfxData) { + warning("Unable to load soundfx module '%s'", song); + return 0; + } -const int AdlibSoundDriver::_voiceOperatorsTable[] = { - 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 16, 16, 14, 14, 17, 17, 13, 13 -}; + for (int i = 0; i < NUM_INSTRUMENTS; ++i) { + _instrumentsData[i] = NULL; -const int AdlibSoundDriver::_voiceOperatorsTableCount = ARRAYSIZE(_voiceOperatorsTable); + char instrument[13]; + memcpy(instrument, _sfxData + 20 + i * 30, 12); + instrument[12] = '\0'; + if (strlen(instrument) != 0) { + char *dot = strrchr(instrument, '.'); + if (dot) { + *dot = '\0'; + } + strcat(instrument, _driver->getInstrumentExtension()); + _instrumentsData[i] = readBundleSoundFile(instrument); + if (!_instrumentsData[i]) { + warning("Unable to load soundfx instrument '%s'", instrument); + } + } + } + return 1; +} -PaulaSoundDriver::PaulaSoundDriver(Audio::Mixer *mixer) - : _mixer(mixer) { - memset(_channelsFreqTable, 0, sizeof(_channelsFreqTable)); - memset(_soundsQueue, 0, sizeof(_soundsQueue)); +void PCSoundFxPlayer::play() { + debug(9, "PCSoundFxPlayer::play()"); + if (_sfxData) { + for (int i = 0; i < NUM_CHANNELS; ++i) { + _instrumentsChannelTable[i] = -1; + } + _currentPos = 0; + _currentOrder = 0; + _numOrders = _sfxData[470]; + _eventsDelay = (252 - _sfxData[471]) * 50 / 1060; + _updateTicksCounter = 0; + _playing = true; + } } -void PaulaSoundDriver::setupChannel(int channel, const byte *data, int instrument, int volume) { +void PCSoundFxPlayer::stop() { + if (_playing || _fadeOutCounter != 0) { + _fadeOutCounter = 0; + _playing = false; + for (int i = 0; i < NUM_CHANNELS; ++i) { + _driver->stopChannel(i); + } + _driver->stopAll(); + unload(); + } } -void PaulaSoundDriver::setChannelFrequency(int channel, int frequency) { - assert(frequency > 0); - _channelsFreqTable[channel] = PAULA_FREQ / frequency; +void PCSoundFxPlayer::fadeOut() { + if (_playing) { + _fadeOutCounter = 1; + _playing = false; + } } -void PaulaSoundDriver::stopChannel(int channel) { - _mixer->stopHandle(_channelsTable[channel]); +void PCSoundFxPlayer::updateCallback(void *ref) { + ((PCSoundFxPlayer *)ref)->update(); } -void PaulaSoundDriver::playSound(const byte *data, int size, int channel, int volume) { - stopChannel(channel); - size = MIN<int>(size - SPL_HDR_SIZE, READ_BE_UINT16(data + 4)); - data += SPL_HDR_SIZE; - if (size > 0) { - _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_channelsTable[channel], const_cast<byte *>(data), size, _channelsFreqTable[channel], 0); - _mixer->setChannelVolume(_channelsTable[channel], volume * Audio::Mixer::kMaxChannelVolume / 63); +void PCSoundFxPlayer::update() { + if (_playing || (_fadeOutCounter != 0 && _fadeOutCounter < 100)) { + ++_updateTicksCounter; + if (_updateTicksCounter > _eventsDelay) { + handleEvents(); + _updateTicksCounter = 0; + } } } -void PaulaSoundDriver::stopSound() { - for (int i = 0; i < NUM_CHANNELS; ++i) { - _mixer->stopHandle(_channelsTable[i]); +void PCSoundFxPlayer::handleEvents() { + const byte *patternData = _sfxData + 600; + const byte *orderTable = _sfxData + 472; + uint16 patternNum = orderTable[_currentOrder] * 1024; + + for (int i = 0; i < 4; ++i) { + handlePattern(i, patternData + patternNum + _currentPos); + patternData += 4; + } + + if (_fadeOutCounter != 0 && _fadeOutCounter < 100) { + _fadeOutCounter += 2; + } + _currentPos += 16; + if (_currentPos >= 1024) { + _currentPos = 0; + ++_currentOrder; + if (_currentOrder == _numOrders) { + _currentOrder = 0; + } } + debug(7, "_currentOrder=%d/%d _currentPos=%d", _currentOrder, _numOrders, _currentPos); } -void PaulaSoundDriver::queueSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) { - SoundQueue *sq = &_soundsQueue[channel]; - sq->freq = frequency; - sq->data = data; - sq->size = size; - sq->volumeStep = volumeStep; - sq->stepCount = stepCount; - sq->step = stepCount; - sq->repeat = repeat != 0; - sq->volume = volume; +void PCSoundFxPlayer::handlePattern(int channel, const byte *patternData) { + int instrument = patternData[2] >> 4; + if (instrument != 0) { + --instrument; + if (_instrumentsChannelTable[channel] != instrument || _fadeOutCounter != 0) { + _instrumentsChannelTable[channel] = instrument; + const int volume = _sfxData[instrument] - _fadeOutCounter; + _driver->setupChannel(channel, _instrumentsData[instrument], instrument, volume); + } + } + int16 freq = (int16)READ_BE_UINT16(patternData); + if (freq > 0) { + _driver->stopChannel(channel); + _driver->setChannelFrequency(channel, freq); + } +} + +void PCSoundFxPlayer::unload() { + for (int i = 0; i < NUM_INSTRUMENTS; ++i) { + free(_instrumentsData[i]); + _instrumentsData[i] = NULL; + } + free(_sfxData); + _sfxData = NULL; } -void PaulaSoundDriver::update() { + +PCSound::PCSound(Audio::Mixer *mixer, CineEngine *vm) + : Sound(mixer, vm) { + if (_vm->getGameType() == GType_FW) { + _soundDriver = new AdlibSoundDriverINS(_mixer); + } else { + _soundDriver = new AdlibSoundDriverADL(_mixer); + } + _player = new PCSoundFxPlayer(_soundDriver); +} + +PCSound::~PCSound() { + delete _player; + delete _soundDriver; +} + +void PCSound::loadMusic(const char *name) { + _player->load(name); +} + +void PCSound::playMusic() { + _player->play(); +} + +void PCSound::stopMusic() { + _player->stop(); +} + +void PCSound::fadeOutMusic() { + _player->fadeOut(); +} + +void PCSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) { + _soundDriver->playSample(data, size, channel, volume); +} + +void PCSound::stopSound(int channel) { + _soundDriver->resetChannel(channel); +} + +PaulaSound::PaulaSound(Audio::Mixer *mixer, CineEngine *vm) + : Sound(mixer, vm) { + memset(_soundChannelsTable, 0, sizeof(_soundChannelsTable)); + _moduleStream = 0; +} + +PaulaSound::~PaulaSound() { +} + +void PaulaSound::loadMusic(const char *name) { + Common::File f; + if (f.open(name)) { + _moduleStream = Audio::makeSoundFxStream(&f, _mixer->getOutputRate()); + } +} + +void PaulaSound::playMusic() { + _mixer->stopHandle(_moduleHandle); + if (_moduleStream) { + _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_moduleHandle, _moduleStream); + } +} + +void PaulaSound::stopMusic() { + _mixer->stopHandle(_moduleHandle); +} + +void PaulaSound::fadeOutMusic() { + // TODO + stopMusic(); +} + +void PaulaSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) { + SoundChannel *ch = &_soundChannelsTable[channel]; + ch->frequency = frequency; + ch->data = data; + ch->size = size; + ch->volumeStep = volumeStep; + ch->stepCount = stepCount; + ch->step = stepCount; + ch->repeat = repeat != 0; + ch->volume = volume; +} + +void PaulaSound::stopSound(int channel) { + _mixer->stopHandle(_channelsTable[channel]); +} + +void PaulaSound::update() { // process volume slides and start sound playback for (int i = 0; i < NUM_CHANNELS; ++i) { - SoundQueue *sq = &_soundsQueue[i]; - if (sq->data) { - if (sq->step) { - --sq->step; + SoundChannel *ch = &_soundChannelsTable[i]; + if (ch->data) { + if (ch->step) { + --ch->step; continue; } - sq->step = sq->stepCount; - sq->volume = CLIP(sq->volume + sq->volumeStep, 0, 63); - setChannelFrequency(i, sq->freq); - playSound(sq->data, sq->size, i, sq->volume); - if (!sq->repeat) { - sq->data = 0; + ch->step = ch->stepCount; + ch->volume = CLIP(ch->volume + ch->volumeStep, 0, 63); + playSoundChannel(i, ch->frequency, ch->data, ch->size, ch->volume); + if (!ch->repeat) { + ch->data = 0; } } } } +void PaulaSound::playSoundChannel(int channel, int frequency, const uint8 *data, int size, int volume) { + stopSound(channel); + assert(frequency > 0); + frequency = PAULA_FREQ / frequency; + size = MIN<int>(size - SPL_HDR_SIZE, READ_BE_UINT16(data + 4)); + data += SPL_HDR_SIZE; + if (size > 0) { + _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_channelsTable[channel], const_cast<byte *>(data), size, frequency, 0); + _mixer->setChannelVolume(_channelsTable[channel], volume * Audio::Mixer::kMaxChannelVolume / 63); + } +} + } // End of namespace Cine diff --git a/engines/cine/sound.h b/engines/cine/sound.h new file mode 100644 index 0000000000..584cdab62f --- /dev/null +++ b/engines/cine/sound.h @@ -0,0 +1,129 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2006 The ScummVM project + * + * cinE Engine is (C) 2004-2005 by CinE Team + * + * 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 CINE_SOUND_H_ +#define CINE_SOUND_H_ + +#include "common/util.h" +#include "sound/mixer.h" + +namespace Audio { + class AudioStream; +} + +namespace Cine { + +class CineEngine; + +class Sound { +public: + + Sound(Audio::Mixer *mixer, CineEngine *vm) : _mixer(mixer), _vm(vm) {} + virtual ~Sound() {} + + virtual void loadMusic(const char *name) = 0; + virtual void playMusic() = 0; + virtual void stopMusic() = 0; + virtual void fadeOutMusic() = 0; + + virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) = 0; + virtual void stopSound(int channel) = 0; + virtual void update() {} + +protected: + + Audio::Mixer *_mixer; + CineEngine *_vm; +}; + +class PCSoundDriver; +class PCSoundFxPlayer; + +class PCSound : public Sound { +public: + + PCSound(Audio::Mixer *mixer, CineEngine *vm); + virtual ~PCSound(); + + virtual void loadMusic(const char *name); + virtual void playMusic(); + virtual void stopMusic(); + virtual void fadeOutMusic(); + + virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat); + virtual void stopSound(int channel); + +protected: + + PCSoundDriver *_soundDriver; + PCSoundFxPlayer *_player; +}; + +class PaulaSound : public Sound { +public: + + PaulaSound(Audio::Mixer *mixer, CineEngine *vm); + virtual ~PaulaSound(); + + virtual void loadMusic(const char *name); + virtual void playMusic(); + virtual void stopMusic(); + virtual void fadeOutMusic(); + + virtual void playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat); + virtual void stopSound(int channel); + virtual void update(); + + enum { + PAULA_FREQ = 7093789, + NUM_CHANNELS = 4, + SPL_HDR_SIZE = 22 + }; + + struct SoundChannel { + int frequency; + const uint8 *data; + int size; + int volumeStep; + int stepCount; + int step; + bool repeat; + int volume; + }; + +protected: + + void playSoundChannel(int channel, int frequency, const uint8 *data, int size, int volume); + + Audio::SoundHandle _channelsTable[NUM_CHANNELS]; + SoundChannel _soundChannelsTable[NUM_CHANNELS]; + Audio::SoundHandle _moduleHandle; + Audio::AudioStream *_moduleStream; +}; + +extern Sound *g_sound; + +} // End of namespace Cine + +#endif /* CINE_SOUND_H_ */ diff --git a/engines/cine/sound_driver.h b/engines/cine/sound_driver.h deleted file mode 100644 index 6ca1fa8f5a..0000000000 --- a/engines/cine/sound_driver.h +++ /dev/null @@ -1,182 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2006 The ScummVM project - * - * cinE Engine is (C) 2004-2005 by CinE Team - * - * 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 CINE_SOUNDDRIVER_H -#define CINE_SOUNDDRIVER_H - -#include "sound/audiostream.h" -#include "sound/fmopl.h" -#include "sound/mixer.h" - -namespace Cine { - -class SoundDriver { -public: - typedef void (*UpdateCallback)(void *); - - virtual ~SoundDriver() {} - - virtual void setupChannel(int channel, const byte *data, int instrument, int volume) = 0; - virtual void setChannelFrequency(int channel, int frequency) = 0; - virtual void stopChannel(int channel) = 0; - virtual void playSound(const byte *data, int size, int channel, int volume) = 0; - virtual void stopSound() = 0; - virtual const char *getInstrumentExtension() const { return ""; } - virtual void update() {} - - void setUpdateCallback(UpdateCallback upCb, void *ref); - void resetChannel(int channel); - void findNote(int freq, int *note, int *oct) const; - -protected: - UpdateCallback _upCb; - void *_upRef; - - static const int _noteTable[]; - static const int _noteTableCount; -}; - -struct AdlibRegisterSoundInstrument { - uint16 vibrato; - uint16 attackDecay; - uint16 sustainRelease; - uint16 feedbackStrength; - uint16 keyScaling; - uint16 outputLevel; - uint16 freqMod; -}; - -struct AdlibSoundInstrument { - byte mode; - byte channel; - AdlibRegisterSoundInstrument regMod; - AdlibRegisterSoundInstrument regCar; - byte waveSelectMod; - byte waveSelectCar; - byte amDepth; -}; - -class AdlibSoundDriver : public SoundDriver, Audio::AudioStream { -public: - AdlibSoundDriver(Audio::Mixer *mixer); - virtual ~AdlibSoundDriver(); - - // SoundDriver interface - virtual void setupChannel(int channel, const byte *data, int instrument, int volume); - virtual void stopChannel(int channel); - virtual void stopSound(); - - // AudioStream interface - virtual int readBuffer(int16 *buffer, const int numSamples); - virtual bool isStereo() const { return false; } - virtual bool endOfData() const { return false; } - virtual int getRate() const { return _sampleRate; } - - void initCard(); - void update(int16 *buf, int len); - void setupInstrument(const byte *data, int channel); - void loadRegisterInstrument(const byte *data, AdlibRegisterSoundInstrument *reg); - virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi) = 0; - -protected: - FM_OPL *_opl; - int _sampleRate; - Audio::Mixer *_mixer; - Audio::SoundHandle _soundHandle; - - byte _vibrato; - int _channelsVolumeTable[4]; - AdlibSoundInstrument _instrumentsTable[4]; - - static const int _freqTable[]; - static const int _freqTableCount; - static const int _operatorsTable[]; - static const int _operatorsTableCount; - static const int _voiceOperatorsTable[]; - static const int _voiceOperatorsTableCount; -}; - -// Future Wars adlib driver -class AdlibSoundDriverINS : public AdlibSoundDriver { -public: - AdlibSoundDriverINS(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {} - virtual const char *getInstrumentExtension() const { return ".INS"; } - virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi); - virtual void setChannelFrequency(int channel, int frequency); - virtual void playSound(const byte *data, int size, int channel, int volume); -}; - -// Operation Stealth adlib driver -class AdlibSoundDriverADL : public AdlibSoundDriver { -public: - AdlibSoundDriverADL(Audio::Mixer *mixer) : AdlibSoundDriver(mixer) {} - virtual const char *getInstrumentExtension() const { return ".ADL"; } - virtual void loadInstrument(const byte *data, AdlibSoundInstrument *asi); - virtual void setChannelFrequency(int channel, int frequency); - virtual void playSound(const byte *data, int size, int channel, int volume); -}; - -class PaulaSoundDriver : public SoundDriver { -public: - PaulaSoundDriver(Audio::Mixer *mixer); - - virtual void setupChannel(int channel, const byte *data, int instrument, int volume); - virtual void setChannelFrequency(int channel, int frequency); - virtual void stopChannel(int channel); - virtual void playSound(const byte *data, int size, int channel, int volume); - virtual void stopSound(); - - // Future Wars specific - void queueSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat); - virtual void update(); - - enum { - PAULA_FREQ = 7093789, - NUM_CHANNELS = 4, - SPL_HDR_SIZE = 22 - }; - - struct SoundQueue { - int freq; - const uint8 *data; - int size; - int volumeStep; - int stepCount; - int step; - bool repeat; - int volume; - }; - -private: - Audio::Mixer *_mixer; - Audio::SoundHandle _channelsTable[NUM_CHANNELS]; - uint _channelsFreqTable[NUM_CHANNELS]; - SoundQueue _soundsQueue[NUM_CHANNELS]; -}; - -extern SoundDriver *g_soundDriver; // TEMP - -} // End of namespace Cine - -#endif /* CINE_SOUNDDRIVER_H_ */ diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 51f8f5d94c..b7b86bab3f 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -29,7 +29,7 @@ #include "cine/cine.h" #include "cine/main_loop.h" #include "cine/object.h" -#include "cine/sfx_player.h" +#include "cine/sound.h" #include "cine/bg_list.h" #include "cine/various.h" @@ -438,7 +438,7 @@ bool CineEngine::makeLoad(char *saveName) { return false; } - g_sfxPlayer->stop(); + g_sound->stopMusic(); freeAnimDataTable(); unloadAllMasks(); // if (g_cine->getGameType() == Cine::GType_OS) { |