2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2003-10-21 12:29:37 +00:00
|
|
|
*
|
|
|
|
* 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.
|
2014-02-18 01:34:23 +00:00
|
|
|
*
|
2003-10-21 12:29:37 +00:00
|
|
|
* 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.
|
2014-02-18 01:34:23 +00:00
|
|
|
*
|
2003-10-21 12:29:37 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2005-10-18 01:30:26 +00:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2003-10-21 12:29:37 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-09-19 08:40:12 +00:00
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
#include "common/config-manager.h"
|
2006-03-29 15:59:37 +00:00
|
|
|
#include "common/endian.h"
|
2010-11-19 17:03:07 +00:00
|
|
|
#include "common/memstream.h"
|
2011-04-24 08:34:27 +00:00
|
|
|
#include "common/textconsole.h"
|
2006-03-29 15:59:37 +00:00
|
|
|
|
2003-12-01 20:48:41 +00:00
|
|
|
#include "queen/sound.h"
|
2003-10-23 06:44:35 +00:00
|
|
|
#include "queen/input.h"
|
2007-02-21 20:27:48 +00:00
|
|
|
#include "queen/logic.h"
|
2003-12-14 00:33:21 +00:00
|
|
|
#include "queen/music.h"
|
2003-12-11 22:16:35 +00:00
|
|
|
#include "queen/queen.h"
|
2003-10-21 12:29:37 +00:00
|
|
|
#include "queen/resource.h"
|
|
|
|
|
2011-02-09 01:09:01 +00:00
|
|
|
#include "audio/audiostream.h"
|
|
|
|
#include "audio/decoders/flac.h"
|
|
|
|
#include "audio/decoders/mp3.h"
|
|
|
|
#include "audio/decoders/raw.h"
|
|
|
|
#include "audio/decoders/vorbis.h"
|
2016-04-14 13:10:21 +00:00
|
|
|
#include "audio/mods/rjp1.h"
|
2004-11-27 15:58:18 +00:00
|
|
|
|
2006-11-23 22:10:25 +00:00
|
|
|
#define SB_HEADER_SIZE_V104 110
|
|
|
|
#define SB_HEADER_SIZE_V110 122
|
2003-10-21 12:29:37 +00:00
|
|
|
|
|
|
|
namespace Queen {
|
|
|
|
|
2008-07-31 13:45:58 +00:00
|
|
|
// The sounds in the PC versions are all played at 11840 Hz. Unfortunately, we
|
|
|
|
// did not know that at the time, so there are plenty of compressed versions
|
|
|
|
// which claim that they should be played at 11025 Hz. This "wrapper" class
|
|
|
|
// works around that.
|
|
|
|
|
|
|
|
class AudioStreamWrapper : public Audio::AudioStream {
|
|
|
|
protected:
|
|
|
|
Audio::AudioStream *_stream;
|
2008-08-25 18:47:27 +00:00
|
|
|
int _rate;
|
2008-07-31 13:45:58 +00:00
|
|
|
|
|
|
|
public:
|
|
|
|
AudioStreamWrapper(Audio::AudioStream *stream) {
|
|
|
|
_stream = stream;
|
2008-08-25 18:47:27 +00:00
|
|
|
|
|
|
|
int rate = _stream->getRate();
|
|
|
|
|
|
|
|
// A file where the sample rate claims to be 11025 Hz is
|
|
|
|
// probably compressed with the old tool. We force the real
|
|
|
|
// sample rate, which is 11840 Hz.
|
|
|
|
//
|
|
|
|
// However, a file compressed with the newer tool is not
|
|
|
|
// guaranteed to have a sample rate of 11840 Hz. LAME will
|
|
|
|
// automatically resample it to 12000 Hz. So in all other
|
|
|
|
// cases, we use the rate from the file.
|
|
|
|
|
|
|
|
if (rate == 11025)
|
|
|
|
_rate = 11840;
|
|
|
|
else
|
|
|
|
_rate = rate;
|
2008-07-31 13:45:58 +00:00
|
|
|
}
|
|
|
|
~AudioStreamWrapper() {
|
|
|
|
delete _stream;
|
|
|
|
}
|
|
|
|
int readBuffer(int16 *buffer, const int numSamples) {
|
|
|
|
return _stream->readBuffer(buffer, numSamples);
|
|
|
|
}
|
|
|
|
bool isStereo() const {
|
|
|
|
return _stream->isStereo();
|
|
|
|
}
|
|
|
|
bool endOfData() const {
|
|
|
|
return _stream->endOfData();
|
|
|
|
}
|
2011-02-07 23:18:47 +00:00
|
|
|
bool endOfStream() const {
|
2008-07-31 13:45:58 +00:00
|
|
|
return _stream->endOfStream();
|
|
|
|
}
|
|
|
|
int getRate() const {
|
2008-08-25 18:47:27 +00:00
|
|
|
return _rate;
|
2008-07-31 13:45:58 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
class SilentSound : public PCSound {
|
2007-02-20 19:23:07 +00:00
|
|
|
public:
|
2007-02-21 20:27:48 +00:00
|
|
|
SilentSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
|
2007-02-20 19:23:07 +00:00
|
|
|
protected:
|
|
|
|
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
|
|
|
|
// Do nothing
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
class SBSound : public PCSound {
|
2007-02-20 19:23:07 +00:00
|
|
|
public:
|
2007-02-21 20:27:48 +00:00
|
|
|
SBSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
|
2007-02-20 19:23:07 +00:00
|
|
|
protected:
|
|
|
|
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle);
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef USE_MAD
|
2007-02-21 20:27:48 +00:00
|
|
|
class MP3Sound : public PCSound {
|
2007-02-20 19:23:07 +00:00
|
|
|
public:
|
2007-02-21 20:27:48 +00:00
|
|
|
MP3Sound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
|
2007-02-20 19:23:07 +00:00
|
|
|
protected:
|
|
|
|
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
|
2010-11-19 17:03:07 +00:00
|
|
|
Common::SeekableReadStream *tmp = f->readStream(size);
|
2007-07-15 19:24:00 +00:00
|
|
|
assert(tmp);
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(Audio::Mixer::kSFXSoundType, soundHandle, new AudioStreamWrapper(Audio::makeMP3Stream(tmp, DisposeAfterUse::YES)));
|
2007-02-20 19:23:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_VORBIS
|
2007-02-21 20:27:48 +00:00
|
|
|
class OGGSound : public PCSound {
|
2007-02-20 19:23:07 +00:00
|
|
|
public:
|
2007-02-21 20:27:48 +00:00
|
|
|
OGGSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
|
2007-02-20 19:23:07 +00:00
|
|
|
protected:
|
|
|
|
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
|
2010-11-19 17:03:07 +00:00
|
|
|
Common::SeekableReadStream *tmp = f->readStream(size);
|
2007-07-15 19:24:00 +00:00
|
|
|
assert(tmp);
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(Audio::Mixer::kSFXSoundType, soundHandle, new AudioStreamWrapper(Audio::makeVorbisStream(tmp, DisposeAfterUse::YES)));
|
2007-02-20 19:23:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_FLAC
|
2007-02-21 20:27:48 +00:00
|
|
|
class FLACSound : public PCSound {
|
2007-02-20 19:23:07 +00:00
|
|
|
public:
|
2007-04-26 19:08:53 +00:00
|
|
|
FLACSound(Audio::Mixer *mixer, QueenEngine *vm) : PCSound(mixer, vm) {}
|
2007-02-20 19:23:07 +00:00
|
|
|
protected:
|
|
|
|
void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
|
2010-11-19 17:03:07 +00:00
|
|
|
Common::SeekableReadStream *tmp = f->readStream(size);
|
2007-07-15 19:24:00 +00:00
|
|
|
assert(tmp);
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(Audio::Mixer::kSFXSoundType, soundHandle, new AudioStreamWrapper(Audio::makeFLACStream(tmp, DisposeAfterUse::YES)));
|
2007-02-20 19:23:07 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif // #ifdef USE_FLAC
|
|
|
|
|
2005-07-30 21:11:48 +00:00
|
|
|
Sound::Sound(Audio::Mixer *mixer, QueenEngine *vm) :
|
2007-02-21 20:27:48 +00:00
|
|
|
_mixer(mixer), _vm(vm), _sfxToggle(true), _speechToggle(true), _musicToggle(true),
|
2007-03-20 23:24:54 +00:00
|
|
|
_speechSfxExists(false), _lastOverride(0), _musicVolume(0) {
|
2003-10-21 12:29:37 +00:00
|
|
|
}
|
|
|
|
|
2007-02-20 19:23:07 +00:00
|
|
|
Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 compression) {
|
2007-02-21 20:27:48 +00:00
|
|
|
if (vm->resource()->getPlatform() == Common::kPlatformAmiga)
|
|
|
|
return new AmigaSound(mixer, vm);
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2005-04-07 08:57:40 +00:00
|
|
|
switch (compression) {
|
|
|
|
case COMPRESSION_NONE:
|
|
|
|
return new SBSound(mixer, vm);
|
|
|
|
case COMPRESSION_MP3:
|
|
|
|
#ifndef USE_MAD
|
|
|
|
warning("Using MP3 compressed datafile, but MP3 support not compiled in");
|
|
|
|
return new SilentSound(mixer, vm);
|
|
|
|
#else
|
|
|
|
return new MP3Sound(mixer, vm);
|
|
|
|
#endif
|
|
|
|
case COMPRESSION_OGG:
|
2005-08-10 12:42:56 +00:00
|
|
|
#ifndef USE_VORBIS
|
2005-04-07 08:57:40 +00:00
|
|
|
warning("Using OGG compressed datafile, but OGG support not compiled in");
|
|
|
|
return new SilentSound(mixer, vm);
|
|
|
|
#else
|
|
|
|
return new OGGSound(mixer, vm);
|
|
|
|
#endif
|
|
|
|
case COMPRESSION_FLAC:
|
|
|
|
#ifndef USE_FLAC
|
|
|
|
warning("Using FLAC compressed datafile, but FLAC support not compiled in");
|
|
|
|
return new SilentSound(mixer, vm);
|
|
|
|
#else
|
|
|
|
return new FLACSound(mixer, vm);
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
warning("Unknown compression type");
|
|
|
|
return new SilentSound(mixer, vm);
|
2003-10-21 12:29:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-20 23:24:54 +00:00
|
|
|
void Sound::setVolume(int vol) {
|
2011-03-20 11:01:27 +00:00
|
|
|
if (ConfMan.hasKey("mute") && ConfMan.getBool("mute"))
|
|
|
|
_musicVolume = 0;
|
|
|
|
else
|
|
|
|
_musicVolume = vol;
|
|
|
|
|
|
|
|
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicVolume);
|
2007-03-20 23:24:54 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void Sound::saveState(byte *&ptr) {
|
|
|
|
WRITE_BE_UINT16(ptr, _lastOverride); ptr += 2;
|
2006-11-24 18:37:43 +00:00
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void Sound::loadState(uint32 ver, byte *&ptr) {
|
|
|
|
_lastOverride = (int16)READ_BE_INT16(ptr); ptr += 2;
|
2003-12-20 16:54:46 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
PCSound::PCSound(Audio::Mixer *mixer, QueenEngine *vm)
|
|
|
|
: Sound(mixer, vm) {
|
2007-02-18 21:46:40 +00:00
|
|
|
|
2007-11-15 20:21:33 +00:00
|
|
|
_music = new MidiMusic(vm);
|
2007-02-21 20:27:48 +00:00
|
|
|
}
|
2007-02-18 21:46:40 +00:00
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
PCSound::~PCSound() {
|
|
|
|
delete _music;
|
2007-02-18 21:46:40 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void PCSound::playSfx(uint16 sfx) {
|
2007-09-01 19:13:04 +00:00
|
|
|
if (sfxOn() && sfx != 0)
|
2007-02-21 20:27:48 +00:00
|
|
|
playSound(_sfxName[sfx - 1], false);
|
|
|
|
}
|
2007-02-18 21:46:40 +00:00
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void PCSound::playSong(int16 songNum) {
|
2003-12-28 01:47:37 +00:00
|
|
|
if (songNum <= 0) {
|
2007-02-21 20:27:48 +00:00
|
|
|
_music->stopSong();
|
2003-12-14 00:33:21 +00:00
|
|
|
return;
|
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2004-01-25 05:03:35 +00:00
|
|
|
int16 newTune;
|
|
|
|
if (_vm->resource()->isDemo()) {
|
2004-01-25 16:57:05 +00:00
|
|
|
if (songNum == 17) {
|
2007-02-21 20:27:48 +00:00
|
|
|
_music->stopSong();
|
2004-01-25 16:57:05 +00:00
|
|
|
return;
|
|
|
|
}
|
2004-01-25 05:03:35 +00:00
|
|
|
newTune = _songDemo[songNum - 1].tuneList[0] - 1;
|
|
|
|
} else {
|
|
|
|
newTune = _song[songNum - 1].tuneList[0] - 1;
|
|
|
|
}
|
2003-11-07 02:33:20 +00:00
|
|
|
|
2004-01-04 03:37:12 +00:00
|
|
|
if (_tune[newTune].sfx[0]) {
|
2006-11-24 18:37:43 +00:00
|
|
|
playSfx(_tune[newTune].sfx[0]);
|
2003-12-14 00:33:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-01-25 05:03:35 +00:00
|
|
|
if (!musicOn())
|
2003-12-14 04:07:22 +00:00
|
|
|
return;
|
|
|
|
|
2013-01-26 13:42:41 +00:00
|
|
|
int overrideCmd = (_vm->resource()->isDemo()) ? _songDemo[songNum - 1].overrideCmd : _song[songNum - 1].overrideCmd;
|
|
|
|
switch (overrideCmd) {
|
2005-04-07 08:57:40 +00:00
|
|
|
// Override all songs
|
|
|
|
case 1:
|
|
|
|
break;
|
|
|
|
// Alter song settings (such as volume) and exit
|
|
|
|
case 2:
|
2007-02-21 20:27:48 +00:00
|
|
|
_music->toggleVChange();
|
2005-04-07 08:57:40 +00:00
|
|
|
default:
|
|
|
|
return;
|
2004-01-04 03:37:12 +00:00
|
|
|
}
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2003-12-28 01:17:29 +00:00
|
|
|
_lastOverride = songNum;
|
2005-07-30 21:11:48 +00:00
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
_music->queueTuneList(newTune);
|
|
|
|
_music->playMusic();
|
2003-11-07 02:33:20 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void PCSound::stopSong() {
|
|
|
|
_music->stopSong();
|
|
|
|
}
|
2007-02-18 21:46:40 +00:00
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void PCSound::playSpeech(const char *base) {
|
|
|
|
if (speechOn()) {
|
|
|
|
playSound(base, true);
|
|
|
|
}
|
2004-01-12 13:40:02 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
void PCSound::setVolume(int vol) {
|
2007-03-16 22:28:25 +00:00
|
|
|
Sound::setVolume(vol);
|
2007-02-21 20:27:48 +00:00
|
|
|
_music->setVolume(vol);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PCSound::playSound(const char *base, bool isSpeech) {
|
|
|
|
char name[13];
|
|
|
|
strcpy(name, base);
|
|
|
|
// alter filename to add zeros and append ".SB"
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
|
|
if (name[i] == ' ')
|
|
|
|
name[i] = '0';
|
|
|
|
}
|
|
|
|
strcat(name, ".SB");
|
2008-07-15 20:26:12 +00:00
|
|
|
if (isSpeech) {
|
|
|
|
while (_mixer->isSoundHandleActive(_speechHandle)) {
|
|
|
|
_vm->input()->delay(10);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
_mixer->stopHandle(_sfxHandle);
|
|
|
|
}
|
2007-02-21 20:27:48 +00:00
|
|
|
uint32 size;
|
|
|
|
Common::File *f = _vm->resource()->findSound(name, &size);
|
|
|
|
if (f) {
|
|
|
|
playSoundData(f, size, isSpeech ? &_speechHandle : &_sfxHandle);
|
|
|
|
_speechSfxExists = isSpeech;
|
|
|
|
} else {
|
|
|
|
_speechSfxExists = false;
|
|
|
|
}
|
2004-01-12 13:40:02 +00:00
|
|
|
}
|
|
|
|
|
2006-11-24 18:37:43 +00:00
|
|
|
void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
|
2008-07-15 20:31:11 +00:00
|
|
|
// In order to simplify the code, we don't parse the .sb header but hard-code the
|
|
|
|
// values. Refer to tracker item #1876741 for details on the format/fields.
|
2006-11-24 18:37:43 +00:00
|
|
|
int headerSize;
|
|
|
|
f->seek(2, SEEK_CUR);
|
|
|
|
uint16 version = f->readUint16LE();
|
|
|
|
switch (version) {
|
|
|
|
case 104:
|
|
|
|
headerSize = SB_HEADER_SIZE_V104;
|
|
|
|
break;
|
|
|
|
case 110:
|
|
|
|
headerSize = SB_HEADER_SIZE_V110;
|
|
|
|
break;
|
|
|
|
default:
|
2009-05-31 10:02:16 +00:00
|
|
|
warning("Unhandled SB file version %d, defaulting to 104", version);
|
2006-11-24 18:37:43 +00:00
|
|
|
headerSize = SB_HEADER_SIZE_V104;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
f->seek(headerSize - 4, SEEK_CUR);
|
|
|
|
size -= headerSize;
|
|
|
|
uint8 *sound = (uint8 *)malloc(size);
|
|
|
|
if (sound) {
|
|
|
|
f->read(sound, size);
|
2008-09-01 17:55:52 +00:00
|
|
|
Audio::Mixer::SoundType type = (soundHandle == &_speechHandle) ? Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType;
|
2010-01-19 22:19:43 +00:00
|
|
|
|
2010-01-30 15:26:54 +00:00
|
|
|
Audio::AudioStream *stream = Audio::makeRawStream(sound, size, 11840, Audio::FLAG_UNSIGNED);
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(type, soundHandle, stream);
|
2005-11-07 18:34:55 +00:00
|
|
|
}
|
2003-10-21 12:29:37 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
AmigaSound::AmigaSound(Audio::Mixer *mixer, QueenEngine *vm)
|
|
|
|
: Sound(mixer, vm), _fanfareRestore(0), _fanfareCount(0), _fluteCount(0) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::playSfx(uint16 sfx) {
|
|
|
|
if (_vm->logic()->currentRoom() == 111) {
|
|
|
|
// lightning sound
|
|
|
|
playSound("88SSSSSS");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::playSong(int16 song) {
|
|
|
|
debug(2, "Sound::playSong %d override %d", song, _lastOverride);
|
|
|
|
|
2007-02-25 19:01:59 +00:00
|
|
|
if (song < 0) {
|
|
|
|
stopSong();
|
|
|
|
return;
|
|
|
|
}
|
2007-02-22 12:25:30 +00:00
|
|
|
|
2007-02-25 19:01:59 +00:00
|
|
|
// remap song numbers for the Amiga
|
2007-02-22 12:25:30 +00:00
|
|
|
switch (song) {
|
2007-02-21 20:27:48 +00:00
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
song = 39;
|
|
|
|
break;
|
|
|
|
case 37:
|
|
|
|
case 52:
|
|
|
|
case 196:
|
|
|
|
song = 90;
|
|
|
|
break;
|
|
|
|
case 38:
|
|
|
|
case 89:
|
|
|
|
song = 3;
|
|
|
|
break;
|
|
|
|
case 24:
|
|
|
|
case 158:
|
|
|
|
song = 117;
|
|
|
|
break;
|
2007-11-30 04:10:28 +00:00
|
|
|
case 71:
|
|
|
|
case 72:
|
|
|
|
case 73:
|
|
|
|
case 75:
|
2007-02-21 20:27:48 +00:00
|
|
|
song = 133;
|
|
|
|
break;
|
|
|
|
case 203:
|
|
|
|
song = 67;
|
|
|
|
break;
|
|
|
|
case 145:
|
|
|
|
song = 140;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 53:
|
|
|
|
case 204:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 44;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 136:
|
|
|
|
case 142:
|
|
|
|
case 179:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 86;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 101:
|
|
|
|
case 102:
|
|
|
|
case 143:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 188;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 65:
|
|
|
|
case 62:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 69;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 118:
|
|
|
|
case 119:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 137;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 130:
|
|
|
|
case 131:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 59;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 174:
|
|
|
|
case 175:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 57;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 171:
|
|
|
|
case 121:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 137;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 138:
|
|
|
|
case 170:
|
|
|
|
case 149:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 28;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 122:
|
|
|
|
case 180:
|
|
|
|
case 83:
|
|
|
|
case 98:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 83;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 20:
|
|
|
|
case 33:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 34;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 29:
|
|
|
|
case 35:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 36;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 7:
|
|
|
|
case 9:
|
|
|
|
case 10:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 11;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 110:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 94;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 111:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 95;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 30:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 43;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 76:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 27;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
case 194:
|
|
|
|
case 195:
|
2007-11-30 19:05:10 +00:00
|
|
|
song = 32;
|
|
|
|
break;
|
2007-02-22 12:25:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_lastOverride != 32 && _lastOverride != 44) {
|
|
|
|
if (playSpecialSfx(song)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_lastOverride == song && _mixer->isSoundHandleActive(_modHandle)) {
|
2007-02-26 20:50:33 +00:00
|
|
|
return;
|
2007-02-22 12:25:30 +00:00
|
|
|
}
|
|
|
|
switch (song) {
|
|
|
|
// hotel
|
2007-02-21 20:27:48 +00:00
|
|
|
case 39:
|
2007-02-22 12:25:30 +00:00
|
|
|
playModule("HOTEL", 1);
|
|
|
|
break;
|
|
|
|
case 19:
|
|
|
|
playModule("HOTEL", 3);
|
|
|
|
break;
|
|
|
|
case 34:
|
|
|
|
playModule("HOTEL", 2);
|
|
|
|
break;
|
|
|
|
case 36:
|
|
|
|
playModule("HOTEL", 4);
|
2007-02-21 20:27:48 +00:00
|
|
|
_fanfareRestore = _lastOverride;
|
2007-02-22 12:25:30 +00:00
|
|
|
_fanfareCount = 60;
|
|
|
|
break;
|
2007-02-21 20:27:48 +00:00
|
|
|
// jungle
|
|
|
|
case 40:
|
|
|
|
playModule("JUNG", 1);
|
|
|
|
_fanfareRestore = _lastOverride;
|
|
|
|
_fanfareCount = 80;
|
|
|
|
_fluteCount = 100;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
playModule("JUNG", 2);
|
|
|
|
_fluteCount = 100;
|
|
|
|
break;
|
|
|
|
// temple
|
|
|
|
case 54:
|
2007-02-22 12:25:30 +00:00
|
|
|
playModule("TEMPLE", 1);
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
playModule("TEMPLE", 2);
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
playModule("TEMPLE", 3);
|
|
|
|
break;
|
|
|
|
case 31:
|
|
|
|
playModule("TEMPLE", 4);
|
|
|
|
_fanfareRestore = _lastOverride;
|
|
|
|
_fanfareCount = 80;
|
|
|
|
break;
|
2007-02-21 20:27:48 +00:00
|
|
|
// floda
|
2007-02-22 12:25:30 +00:00
|
|
|
case 41:
|
|
|
|
playModule("FLODA", 4);
|
2007-02-21 20:27:48 +00:00
|
|
|
_fanfareRestore = _lastOverride;
|
2007-02-22 12:25:30 +00:00
|
|
|
_fanfareCount = 60;
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
playModule("FLODA", 3);
|
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
playModule("FLODA", 1);
|
|
|
|
break;
|
|
|
|
case 17:
|
|
|
|
playModule("FLODA", 2);
|
|
|
|
break;
|
|
|
|
case 43:
|
|
|
|
playModule("FLODA", 5);
|
|
|
|
break;
|
2007-02-21 20:27:48 +00:00
|
|
|
// end credits
|
2007-02-22 12:25:30 +00:00
|
|
|
case 67:
|
|
|
|
playModule("TITLE", 1);
|
|
|
|
break;
|
|
|
|
// intro credits
|
|
|
|
case 88:
|
|
|
|
playModule("TITLE", 1);
|
|
|
|
break;
|
|
|
|
// valley
|
|
|
|
case 90:
|
|
|
|
playModule("AWESTRUK", 1);
|
|
|
|
break;
|
|
|
|
// confrontation
|
|
|
|
case 91:
|
|
|
|
playModule("'JUNGLE'", 1);
|
|
|
|
break;
|
|
|
|
// Frank
|
|
|
|
case 46:
|
|
|
|
playModule("FRANK", 1);
|
|
|
|
break;
|
|
|
|
// trader bob
|
|
|
|
case 6:
|
|
|
|
playModule("BOB", 1);
|
|
|
|
break;
|
|
|
|
// azura
|
|
|
|
case 44:
|
|
|
|
playModule("AZURA", 1);
|
|
|
|
break;
|
|
|
|
// amazon fortress
|
|
|
|
case 21:
|
|
|
|
playModule("FORT", 1);
|
|
|
|
break;
|
|
|
|
// rocket
|
|
|
|
case 32:
|
|
|
|
playModule("ROCKET", 1);
|
|
|
|
break;
|
|
|
|
// robot
|
|
|
|
case 92:
|
|
|
|
playModule("ROBOT", 1);
|
|
|
|
break;
|
2007-02-21 20:27:48 +00:00
|
|
|
default:
|
|
|
|
// song not available in the amiga version
|
|
|
|
return;
|
2007-02-22 12:25:30 +00:00
|
|
|
}
|
2009-08-30 20:50:23 +00:00
|
|
|
_lastOverride = song;
|
2007-02-21 20:27:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::stopSfx() {
|
|
|
|
_mixer->stopHandle(_sfxHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::stopSong() {
|
|
|
|
_mixer->stopHandle(_modHandle);
|
|
|
|
_fanfareCount = _fluteCount = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::updateMusic() {
|
|
|
|
if (_fanfareCount > 0) {
|
|
|
|
--_fanfareCount;
|
|
|
|
if (_fanfareCount == 0) {
|
|
|
|
playSong(_fanfareRestore);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (_fluteCount > 0 && (_lastOverride == 40 || _lastOverride == 3)) {
|
|
|
|
--_fluteCount;
|
|
|
|
if (_fluteCount == 0) {
|
2007-11-18 20:27:31 +00:00
|
|
|
playPattern("JUNG", 5 + _vm->randomizer.getRandomNumber(6));
|
2007-02-21 20:27:48 +00:00
|
|
|
_fluteCount = 100;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::playSound(const char *base) {
|
2007-02-22 12:12:45 +00:00
|
|
|
debug(7, "AmigaSound::playSound(%s)", base);
|
2007-02-21 20:27:48 +00:00
|
|
|
char soundName[20];
|
|
|
|
sprintf(soundName, "%s.AMR", base);
|
|
|
|
|
|
|
|
uint32 soundSize;
|
|
|
|
Common::File *f = _vm->resource()->findSound(soundName, &soundSize);
|
|
|
|
if (f) {
|
|
|
|
uint8 *soundData = (uint8 *)malloc(soundSize);
|
|
|
|
if (soundData) {
|
|
|
|
f->read(soundData, soundSize);
|
2010-01-19 22:19:43 +00:00
|
|
|
|
2010-01-30 15:26:54 +00:00
|
|
|
Audio::AudioStream *stream = Audio::makeRawStream(soundData, soundSize, 11025, 0);
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, stream);
|
2007-02-21 20:27:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-18 20:27:31 +00:00
|
|
|
Audio::AudioStream *AmigaSound::loadModule(const char *base, int num) {
|
|
|
|
debug(7, "AmigaSound::loadModule(%s, %d)", base, num);
|
2007-02-21 20:27:48 +00:00
|
|
|
char name[20];
|
|
|
|
|
|
|
|
// load song/pattern data
|
|
|
|
uint32 sngDataSize;
|
|
|
|
sprintf(name, "%s.SNG", base);
|
|
|
|
uint8 *sngData = _vm->resource()->loadFile(name, 0, &sngDataSize);
|
|
|
|
Common::MemoryReadStream sngStr(sngData, sngDataSize);
|
|
|
|
|
|
|
|
// load instruments/wave data
|
|
|
|
uint32 insDataSize;
|
|
|
|
sprintf(name, "%s.INS", base);
|
|
|
|
uint8 *insData = _vm->resource()->loadFile(name, 0, &insDataSize);
|
|
|
|
Common::MemoryReadStream insStr(insData, insDataSize);
|
|
|
|
|
2007-11-18 20:27:31 +00:00
|
|
|
Audio::AudioStream *stream = Audio::makeRjp1Stream(&sngStr, &insStr, num, _mixer->getOutputRate());
|
2007-02-21 20:27:48 +00:00
|
|
|
|
|
|
|
delete[] sngData;
|
|
|
|
delete[] insData;
|
|
|
|
|
2007-11-18 20:27:31 +00:00
|
|
|
return stream;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AmigaSound::playModule(const char *base, int song) {
|
|
|
|
_mixer->stopHandle(_modHandle);
|
|
|
|
Audio::AudioStream *stream = loadModule(base, song);
|
|
|
|
if (stream) {
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_modHandle, stream);
|
2007-11-18 20:27:31 +00:00
|
|
|
}
|
2007-02-21 20:27:48 +00:00
|
|
|
_fanfareCount = 0;
|
|
|
|
}
|
|
|
|
|
2007-11-18 20:27:31 +00:00
|
|
|
void AmigaSound::playPattern(const char *base, int pattern) {
|
|
|
|
_mixer->stopHandle(_patHandle);
|
|
|
|
Audio::AudioStream *stream = loadModule(base, -pattern);
|
|
|
|
if (stream) {
|
2010-04-12 09:14:17 +00:00
|
|
|
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_patHandle, stream);
|
2007-11-18 20:27:31 +00:00
|
|
|
}
|
2007-02-25 19:01:59 +00:00
|
|
|
}
|
|
|
|
|
2007-02-21 20:27:48 +00:00
|
|
|
bool AmigaSound::playSpecialSfx(int16 sfx) {
|
|
|
|
switch (sfx) {
|
|
|
|
case 5: // normal volume
|
|
|
|
break;
|
|
|
|
case 15: // soft volume
|
|
|
|
break;
|
|
|
|
case 14: // medium volume
|
|
|
|
break;
|
|
|
|
case 25: // open door
|
|
|
|
playSound("116BSSSS");
|
|
|
|
break;
|
|
|
|
case 26: // close door
|
|
|
|
playSound("105ASSSS");
|
|
|
|
break;
|
|
|
|
case 56: // light switch
|
|
|
|
playSound("27SSSSSS");
|
|
|
|
break;
|
|
|
|
case 57: // hydraulic doors open
|
|
|
|
playSound("96SSSSSS");
|
|
|
|
break;
|
|
|
|
case 58: // hydraulic doors close
|
|
|
|
playSound("97SSSSSS");
|
|
|
|
break;
|
|
|
|
case 59: // metallic door slams
|
|
|
|
playSound("105SSSSS");
|
|
|
|
break;
|
|
|
|
case 63: // oracle rezzes in
|
|
|
|
playSound("132SSSSS");
|
|
|
|
break;
|
|
|
|
case 27: // cloth slide 1
|
|
|
|
playSound("135SSSSS");
|
|
|
|
break;
|
|
|
|
case 83: // splash
|
|
|
|
playSound("18SSSSSS");
|
|
|
|
break;
|
|
|
|
case 85: // agression enhancer
|
|
|
|
playSound("138BSSSS");
|
|
|
|
break;
|
|
|
|
case 68: // dino ray
|
|
|
|
playSound("138SSSSS");
|
|
|
|
break;
|
|
|
|
case 140: // dino transformation
|
|
|
|
playSound("55BSSSSS");
|
|
|
|
break;
|
|
|
|
case 141: // experimental laser
|
|
|
|
playSound("55SSSSSS");
|
|
|
|
break;
|
|
|
|
case 94: // plane hatch open
|
|
|
|
playSound("3SSSSSSS");
|
|
|
|
break;
|
|
|
|
case 95: // plane hatch close
|
|
|
|
playSound("4SSSSSSS");
|
|
|
|
break;
|
|
|
|
case 117: // oracle rezzes out
|
|
|
|
playSound("70SSSSSS");
|
|
|
|
break;
|
|
|
|
case 124: // dino horn
|
|
|
|
playSound("103SSSSS");
|
|
|
|
break;
|
|
|
|
case 127: // punch
|
|
|
|
playSound("128SSSSS");
|
|
|
|
break;
|
|
|
|
case 128: // body hits ground
|
|
|
|
playSound("129SSSSS");
|
|
|
|
break;
|
|
|
|
case 137: // explosion
|
|
|
|
playSound("88SSSSSS");
|
|
|
|
break;
|
|
|
|
case 86: // stone door grind 1
|
|
|
|
playSound("1001SSSS");
|
|
|
|
break;
|
|
|
|
case 188: // stone door grind 2
|
|
|
|
playSound("1002SSSS");
|
|
|
|
break;
|
|
|
|
case 28: // cloth slide 2
|
|
|
|
playSound("1005SSSS");
|
|
|
|
break;
|
|
|
|
case 151: // rattle bars
|
|
|
|
playSound("115SSSSS");
|
|
|
|
break;
|
|
|
|
case 152: // door dissolves
|
|
|
|
playSound("56SSSSSS");
|
|
|
|
break;
|
|
|
|
case 153: // altar slides
|
|
|
|
playSound("85SSSSSS");
|
|
|
|
break;
|
|
|
|
case 166 : // pull lever
|
|
|
|
playSound("1008SSSS");
|
|
|
|
break;
|
|
|
|
case 182: // zap Frank
|
|
|
|
playSound("1023SSSS");
|
|
|
|
break;
|
|
|
|
case 69: // splorch
|
|
|
|
playSound("137ASSSS");
|
|
|
|
break;
|
|
|
|
case 70: // robot laser
|
|
|
|
playSound("61SSSSSS");
|
|
|
|
break;
|
|
|
|
case 133: // pick hits stone
|
|
|
|
playSound("71SSSSSS");
|
|
|
|
break;
|
|
|
|
case 165: // press button
|
|
|
|
playSound("1007SSSS");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-01-26 18:33:27 +00:00
|
|
|
} // End of namespace Queen
|