Reorganized the sound code a bit and fixed bug # 1404414 (Missing speech patterns).

svn-id: r20006
This commit is contained in:
Johannes Schickel 2006-01-13 23:06:04 +00:00
parent d04475121e
commit d2de796c31
8 changed files with 207 additions and 79 deletions

View file

@ -96,11 +96,19 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
return 1;
if (_itemInHand != -1) {
assert(_putDownFirst);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2000);
}
characterSays(_putDownFirst[0], 0, -2);
return 1;
}
if (queryGameFlag(0xF1)) {
assert(_waitForAmulet);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2001);
}
characterSays(_waitForAmulet[0], 0, -2);
return 1;
}
@ -108,6 +116,10 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
assert(_blackJewel);
makeBrandonFaceMouse();
drawJewelPress(jewel, 1);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2002);
}
characterSays(_blackJewel[0], 0, -2);
return 1;
}
@ -135,6 +147,10 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
} else if (_brandonStatusBit == 0) {
seq_brandonHealing();
assert(_healingTip);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2003);
}
characterSays(_healingTip[0], 0, -2);
}
break;
@ -146,6 +162,10 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
case 2:
if (_brandonStatusBit & 1) {
assert(_wispJewelStrings);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2004);
}
characterSays(_wispJewelStrings[0], 0, -2);
} else {
if (_brandonStatusBit & 2) {
@ -170,6 +190,10 @@ int KyraEngine::buttonAmuletCallback(Button *caller) {
case 3:
seq_dispelMagicAnimation();
assert(_magicJewelString);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2007);
}
characterSays(_magicJewelString[0], 0, -2);
break;

View file

@ -34,8 +34,6 @@
#include "sound/mixer.h"
#include "sound/mididrv.h"
#include "sound/voc.h"
#include "sound/audiostream.h"
#include "gui/message.h"
@ -264,7 +262,6 @@ KyraEngine::KyraEngine(GameDetector *detector, OSystem *system)
}
int KyraEngine::init(GameDetector &detector) {
_currentVocFile = 0;
_system->beginGFXTransaction();
initCommonGFX(detector);
_system->initSize(320, 200);
@ -282,10 +279,10 @@ int KyraEngine::init(GameDetector &detector) {
driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE);
}
_midi = new MusicPlayer(driver, this);
assert(_midi);
_midi->hasNativeMT32(native_mt32);
_midi->setVolume(255);
_sound = new SoundPC(driver, _mixer, this);
assert(_sound);
static_cast<SoundPC*>(_sound)->hasNativeMT32(native_mt32);
_sound->setVolume(255);
_saveFileMan = _system->getSavefileManager();
assert(_saveFileMan);
@ -431,7 +428,7 @@ KyraEngine::~KyraEngine() {
delete _animator;
delete _screen;
delete _res;
delete _midi;
delete _sound;
delete _saveFileMan;
delete _seq;
delete _scriptInterpreter;
@ -869,7 +866,7 @@ void KyraEngine::seq_demo() {
_screen->fadeFromBlack();
waitTicks(60);
_screen->fadeToBlack();
_midi->stopMusic();
_sound->stopMusic();
}
void KyraEngine::seq_intro() {
@ -897,7 +894,7 @@ void KyraEngine::seq_intro() {
_text->setTalkCoords(136);
waitTicks(30);
_seq->setCopyViewOffs(false);
_midi->stopMusic();
_sound->stopMusic();
if (_features & GF_TALKIE) {
_res->unloadPakFile("INTRO.VRM");
}
@ -1107,7 +1104,15 @@ void KyraEngine::seq_brandonHealing2() {
freeShapes123();
_screen->showMouse();
assert(_poisonGone);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2010);
}
characterSays(_poisonGone[0], 0, -2);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(2011);
}
characterSays(_poisonGone[1], 0, -2);
}
@ -1121,13 +1126,29 @@ void KyraEngine::seq_poisonDeathNow(int now) {
if (_poisonDeathCounter >= 2) {
snd_playWanderScoreViaMap(1, 1);
assert(_thePoison);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(7000);
}
characterSays(_thePoison[0], 0, -2);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(7001);
}
characterSays(_thePoison[1], 0, -2);
seq_poisonDeathNowAnim();
_deathHandler = 3;
} else {
assert(_thePoison);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(7002);
}
characterSays(_thePoison[2], 0, -2);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(7004);
}
characterSays(_thePoison[3], 0, -2);
}
}
@ -1190,10 +1211,11 @@ void KyraEngine::seq_playFluteAnimation() {
snd_playSoundEffect(0x63);
delayTime = 9;
soundType = 3;
} else if (queryGameFlag(0x86)) {
} else if (!queryGameFlag(0x86)) {
snd_playSoundEffect(0x61);
delayTime = 2;
soundType = 1;
setGameFlag(0x86);
} else {
snd_playSoundEffect(0x62);
delayTime = 2;
@ -1219,9 +1241,17 @@ void KyraEngine::seq_playFluteAnimation() {
if (soundType == 1) {
assert(_fluteString);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(1000);
}
characterSays(_fluteString[0], 0, -2);
} else if (soundType == 2) {
assert(_fluteString);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(1001);
}
characterSays(_fluteString[1], 0, -2);
}
}
@ -1481,6 +1511,10 @@ void KyraEngine::seq_fillFlaskWithWater(int item, int type) {
if (item >= 60 && item <= 77) {
assert(_flaskFull);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
snd_playVoiceFile(8006);
}
characterSays(_flaskFull[0], 0, -2);
} else if (item == 78) {
assert(type >= 0 && type < ARRAYSIZE(flaskTable1));
@ -1499,6 +1533,14 @@ void KyraEngine::seq_fillFlaskWithWater(int item, int type) {
_itemInHand = newItem;
assert(_fullFlask);
assert(type < _fullFlask_Size && type >= 0);
if (_features & GF_TALKIE) {
snd_voiceWaitForFinish();
static const uint16 voiceEntries[] = {
0x1F40, 0x1F41, 0x1F42, 0x1F45
};
assert(type < ARRAYSIZE(voiceEntries));
snd_playVoiceFile(voiceEntries[type]);
}
characterSays(_fullFlask[type], 0, -2);
}
@ -1700,19 +1742,19 @@ void KyraEngine::snd_playTheme(int file, int track) {
debug(9, "KyraEngine::snd_playTheme(%d)", file);
assert(file < _xmidiFilesCount);
_curMusicTheme = _newMusicTheme = file;
_midi->playMusic(_xmidiFiles[file]);
_midi->playTrack(track, false);
_sound->playMusic(_xmidiFiles[file]);
_sound->playTrack(track, false);
}
void KyraEngine::snd_playTrack(int track, bool looping) {
debug(9, "KyraEngine::snd_playTrack(%d, %d)", track, looping);
_midi->playTrack(track, looping);
_sound->playTrack(track, looping);
}
void KyraEngine::snd_setSoundEffectFile(int file) {
debug(9, "KyraEngine::snd_setSoundEffectFile(%d)", file);
assert(file < _xmidiFilesCount);
_midi->loadSoundEffectFile(_xmidiFiles[file]);
_sound->loadSoundEffectFile(_xmidiFiles[file]);
}
void KyraEngine::snd_playSoundEffect(int track) {
@ -1720,7 +1762,7 @@ void KyraEngine::snd_playSoundEffect(int track) {
if (track == 49) {
snd_playWanderScoreViaMap(56, 1);
} else {
_midi->playSoundEffect(track);
_sound->playSoundEffect(track);
}
}
@ -1762,7 +1804,7 @@ void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) {
}
} else {
_lastMusicCommand = 1;
_midi->beginFadeOut();
_sound->beginFadeOut();
}
}
@ -1771,31 +1813,32 @@ void KyraEngine::snd_playVoiceFile(int id) {
char vocFile[9];
assert(id >= 0 && id < 9999);
sprintf(vocFile, "%03d.VOC", id);
uint32 fileSize = 0;
byte *fileData = 0;
fileData = _res->fileData(vocFile, &fileSize);
assert(fileData);
Common::MemoryReadStream vocStream(fileData, fileSize);
_mixer->stopHandle(_vocHandle);
_currentVocFile = makeVOCStream(vocStream);
if (_currentVocFile)
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandle, _currentVocFile);
delete fileData;
fileSize = 0;
_sound->voicePlay(vocFile);
}
bool KyraEngine::snd_voicePlaying() {
return _mixer->isSoundHandleActive(_vocHandle);
return _sound->voiceIsPlaying();
}
void KyraEngine::snd_voiceWaitForFinish(bool ingame) {
debug(9, "KyraEngine::snd_voiceWaitForFinish(%d)", ingame);
while (snd_voicePlaying() && !_fastMode) {
if (ingame) {
delay(10, true);
} else {
waitTicks(10);
}
}
}
void KyraEngine::snd_startTrack() {
debug(9, "KyraEngine::snd_startTrack()");
_midi->startTrack();
_sound->startTrack();
}
void KyraEngine::snd_haltTrack() {
debug(9, "KyraEngine::snd_haltTrack()");
_midi->haltTrack();
_sound->haltTrack();
}
void KyraEngine::loadMouseShapes() {

View file

@ -118,7 +118,7 @@ struct BeadState {
class Movie;
class MusicPlayer;
class Sound;
class SeqPlayer;
class Resource;
class PAKFile;
@ -186,7 +186,7 @@ public:
Screen *screen() { return _screen; }
ScreenAnimator *animator() { return _animator; }
TextDisplayer *text() { return _text; }
MusicPlayer *midi() { return _midi; }
Sound *sound() { return _sound; }
uint32 tickLength() const { return _tickLength; }
Movie *createWSAMovie();
@ -218,6 +218,7 @@ public:
void snd_playTrack(int track, bool looping = false);
void snd_playVoiceFile(int id);
bool snd_voicePlaying();
void snd_voiceWaitForFinish(bool ingame = true);
void snd_playSoundEffect(int track);
void snd_playWanderScoreViaMap(int command, int restart);
@ -715,13 +716,11 @@ protected:
int _curMusicTheme;
int _newMusicTheme;
int16 _lastMusicCommand;
AudioStream *_currentVocFile;
Audio::SoundHandle _vocHandle;
Resource *_res;
Screen *_screen;
ScreenAnimator *_animator;
MusicPlayer *_midi;
Sound *_sound;
SeqPlayer *_seq;
Sprites *_sprites;
TextDisplayer *_text;

View file

@ -50,9 +50,7 @@ int KyraEngine::cmd_characterSays(ScriptState *script) {
if (_features & GF_TALKIE) {
debug(3, "cmd_characterSays(0x%X) (%d, '%s', %d, %d)", script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3));
while (snd_voicePlaying() && !_fastMode) {
delay(10);
}
snd_voiceWaitForFinish();
snd_playVoiceFile(stackPos(0));
characterSays(stackPosString(1), stackPos(2), stackPos(3));
} else {
@ -614,9 +612,7 @@ int KyraEngine::cmd_loadPageFromDisk(ScriptState *script) {
int KyraEngine::cmd_customPrintTalkString(ScriptState *script) {
if (_features & GF_TALKIE) {
debug(3, "cmd_customPrintTalkString(0x%X) (%d, '%s', %d, %d, %d)", script, stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF);
while (snd_voicePlaying() && !_fastMode) {
delay(10);
}
snd_voiceWaitForFinish();
snd_playVoiceFile(stackPos(0));
_text->printTalkTextMessage(stackPosString(1), stackPos(2), stackPos(3), stackPos(4) & 0xFF, 0, 2);
} else {

View file

@ -42,7 +42,7 @@ SeqPlayer::SeqPlayer(KyraEngine* vm, OSystem* system) {
_system = system;
_screen = vm->screen();
_midi = vm->midi();
_sound = vm->sound();
_res = vm->resource();
_copyViewOffs = false;
@ -374,7 +374,7 @@ void SeqPlayer::s1_fillRect() {
void SeqPlayer::s1_playEffect() {
uint8 track = *_seqData++;
_vm->waitTicks(3);
_midi->playSoundEffect(track);
_sound->playSoundEffect(track);
}
void SeqPlayer::s1_playTrack() {
@ -387,7 +387,7 @@ void SeqPlayer::s1_playTrack() {
// nothing to do here...
break;
case 1:
_midi->beginFadeOut();
_sound->beginFadeOut();
break;
case 56:
_vm->snd_playTheme(KyraEngine::MUSIC_INTRO, 3);
@ -406,7 +406,7 @@ void SeqPlayer::s1_playTrack() {
if (msg == 0) {
// nothing to do here...
} else if (msg == 1) {
_midi->beginFadeOut();
_sound->beginFadeOut();
} else {
_vm->snd_playTrack(msg);
}
@ -445,9 +445,7 @@ void SeqPlayer::s1_loadIntroVRM() {
}
void SeqPlayer::s1_playVocFile() {
while (_vm->snd_voicePlaying()) {
_system->delayMillis(10);
}
_vm->snd_voiceWaitForFinish(false);
uint8 a = *_seqData++;
_vm->snd_playVoiceFile(a);
}

View file

@ -44,7 +44,7 @@ protected:
KyraEngine *_vm;
OSystem *_system;
Screen *_screen;
MusicPlayer *_midi;
Sound *_sound;
Resource *_res;
uint8 *_handShapes[3];

View file

@ -24,9 +24,13 @@
#include "kyra/resource.h"
#include "kyra/sound.h"
#include "sound/mixer.h"
#include "sound/voc.h"
#include "sound/audiostream.h"
namespace Kyra {
MusicPlayer::MusicPlayer(MidiDriver *driver, KyraEngine *engine) {
SoundPC::SoundPC(MidiDriver *driver, Audio::Mixer *mixer, KyraEngine *engine) : Sound() {
_engine = engine;
_driver = driver;
_passThrough = false;
@ -49,14 +53,17 @@ MusicPlayer::MusicPlayer(MidiDriver *driver, KyraEngine *engine) {
if (ret != MERR_ALREADY_OPEN && ret != 0) {
error("couldn't open midi driver");
}
_currentVocFile = 0;
_mixer = mixer;
}
MusicPlayer::~MusicPlayer() {
SoundPC::~SoundPC() {
_driver->setTimerCallback(NULL, NULL);
close();
}
void MusicPlayer::setVolume(int volume) {
void SoundPC::setVolume(int volume) {
if (volume < 0)
volume = 0;
else if (volume > 255)
@ -77,7 +84,7 @@ void MusicPlayer::setVolume(int volume) {
}
}
int MusicPlayer::open() {
int SoundPC::open() {
// Don't ever call open without first setting the output driver!
if (!_driver)
return 255;
@ -90,13 +97,13 @@ int MusicPlayer::open() {
return 0;
}
void MusicPlayer::close() {
void SoundPC::close() {
if (_driver)
_driver->close();
_driver = 0;
}
void MusicPlayer::send(uint32 b) {
void SoundPC::send(uint32 b) {
if (_passThrough) {
if ((b & 0xFFF0) == 0x007BB0)
return;
@ -140,7 +147,7 @@ void MusicPlayer::send(uint32 b) {
_channel[_virChannel[channel]]->send(b);
}
void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
void SoundPC::metaEvent(byte type, byte *data, uint16 length) {
switch (type) {
case 0x2F: // End of Track
if (_eventFromMusic) {
@ -161,7 +168,7 @@ void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) {
}
}
void MusicPlayer::playMusic(const char *file) {
void SoundPC::playMusic(const char *file) {
uint32 size;
uint8 *data = (_engine->resource())->fileData(file, &size);
@ -173,7 +180,7 @@ void MusicPlayer::playMusic(const char *file) {
playMusic(data, size);
}
void MusicPlayer::playMusic(uint8 *data, uint32 size) {
void SoundPC::playMusic(uint8 *data, uint32 size) {
stopMusic();
_parserSource = data;
@ -193,7 +200,7 @@ void MusicPlayer::playMusic(uint8 *data, uint32 size) {
_parser->property(MidiParser::mpAutoLoop, false);
}
void MusicPlayer::loadSoundEffectFile(const char *file) {
void SoundPC::loadSoundEffectFile(const char *file) {
uint32 size;
uint8 *data = (_engine->resource())->fileData(file, &size);
@ -205,7 +212,7 @@ void MusicPlayer::loadSoundEffectFile(const char *file) {
loadSoundEffectFile(data, size);
}
void MusicPlayer::loadSoundEffectFile(uint8 *data, uint32 size) {
void SoundPC::loadSoundEffectFile(uint8 *data, uint32 size) {
stopSoundEffect();
_soundEffectSource = data;
@ -225,7 +232,7 @@ void MusicPlayer::loadSoundEffectFile(uint8 *data, uint32 size) {
_soundEffect->property(MidiParser::mpAutoLoop, false);
}
void MusicPlayer::stopMusic() {
void SoundPC::stopMusic() {
_isLooping = false;
_isPlaying = false;
if (_parser) {
@ -241,7 +248,7 @@ void MusicPlayer::stopMusic() {
}
}
void MusicPlayer::stopSoundEffect() {
void SoundPC::stopSoundEffect() {
_sfxIsPlaying = false;
if (_soundEffect) {
_soundEffect->unloadMusic();
@ -252,8 +259,8 @@ void MusicPlayer::stopSoundEffect() {
}
}
void MusicPlayer::onTimer(void *refCon) {
MusicPlayer *music = (MusicPlayer *)refCon;
void SoundPC::onTimer(void *refCon) {
SoundPC *music = (SoundPC *)refCon;
// this should be set to the fadeToBlack value
static const uint32 musicFadeTime = 2 * 1000;
@ -295,7 +302,7 @@ void MusicPlayer::onTimer(void *refCon) {
}
}
void MusicPlayer::playTrack(uint8 track, bool loop) {
void SoundPC::playTrack(uint8 track, bool loop) {
if (_parser) {
_isPlaying = true;
_isLooping = loop;
@ -306,7 +313,7 @@ void MusicPlayer::playTrack(uint8 track, bool loop) {
}
}
void MusicPlayer::playSoundEffect(uint8 track) {
void SoundPC::playSoundEffect(uint8 track) {
if (_soundEffect) {
_sfxIsPlaying = true;
_soundEffect->setTrack(track);
@ -315,10 +322,27 @@ void MusicPlayer::playSoundEffect(uint8 track) {
}
}
void MusicPlayer::beginFadeOut() {
void SoundPC::beginFadeOut() {
// this should be something like fade out...
_fadeMusicOut = true;
_fadeStartTime = _engine->_system->getMillis();
}
void SoundPC::voicePlay(const char *file) {
uint32 fileSize = 0;
byte *fileData = 0;
fileData = _engine->resource()->fileData(file, &fileSize);
assert(fileData);
Common::MemoryReadStream vocStream(fileData, fileSize);
_mixer->stopHandle(_vocHandle);
_currentVocFile = makeVOCStream(vocStream);
if (_currentVocFile)
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandle, _currentVocFile);
delete fileData;
fileSize = 0;
}
bool SoundPC::voiceIsPlaying() {
return _mixer->isSoundHandleActive(_vocHandle);
}
} // end of namespace Kyra

View file

@ -28,13 +28,50 @@
#include "sound/midiparser.h"
#include "kyra/kyra.h"
class AudioStream;
namespace Audio {
class Mixer;
class SoundHandle;
} // end of namespace Audio
namespace Kyra {
class MusicPlayer : public MidiDriver {
class Sound {
public:
Sound() {}
virtual ~Sound() {}
virtual void setVolume(int volume) = 0;
virtual int getVolume() = 0;
virtual void playMusic(const char *file) = 0;
virtual void playMusic(uint8 *data, uint32 size) = 0;
virtual void stopMusic() = 0;
virtual void playTrack(uint8 track, bool looping = true) = 0;
virtual void haltTrack() = 0;
virtual void startTrack() = 0;
virtual void loadSoundEffectFile(const char *file) = 0;
virtual void loadSoundEffectFile(uint8 *data, uint32 size) = 0;
virtual void stopSoundEffect() = 0;
virtual void playSoundEffect(uint8 track) = 0;
virtual void beginFadeOut() = 0;
virtual bool fadeOut() = 0;
virtual void voicePlay(const char *file) = 0;
virtual void voiceUnload() = 0;
virtual bool voiceIsPlaying() = 0;
};
class SoundPC : public MidiDriver, public Sound {
public:
MusicPlayer(MidiDriver *driver, KyraEngine *engine);
~MusicPlayer();
SoundPC(MidiDriver *driver, Audio::Mixer *mixer, KyraEngine *engine);
~SoundPC();
void setVolume(int volume);
int getVolume() { return _volume; }
@ -42,23 +79,27 @@ public:
void hasNativeMT32(bool nativeMT32) { _nativeMT32 = nativeMT32; }
bool isMT32() { return _nativeMT32; }
void playMusic(const char* file);
void playMusic(uint8* data, uint32 size);
void playMusic(const char *file);
void playMusic(uint8 *data, uint32 size);
void stopMusic();
void playTrack(uint8 track, bool looping = true);
void playTrack(uint8 track, bool looping);
void haltTrack() { _isPlaying = false; }
void startTrack() { _isPlaying = true; }
void setPassThrough(bool b) { _passThrough = b; }
void loadSoundEffectFile(const char* file);
void loadSoundEffectFile(uint8* data, uint32 size);
void loadSoundEffectFile(const char *file);
void loadSoundEffectFile(uint8 *data, uint32 size);
void stopSoundEffect();
void playSoundEffect(uint8 track);
void beginFadeOut();
bool fadeOut() { return _fadeMusicOut; }
void voicePlay(const char *file);
void voiceUnload() {};
bool voiceIsPlaying();
//MidiDriver interface implementation
int open();
@ -77,10 +118,10 @@ protected:
static void onTimer(void *data);
MidiChannel* _channel[32];
MidiChannel *_channel[32];
int _virChannel[16];
uint8 _channelVolume[16];
MidiDriver* _driver;
MidiDriver *_driver;
bool _nativeMT32;
bool _passThrough;
uint8 _volume;
@ -95,8 +136,11 @@ protected:
MidiParser *_soundEffect;
byte *_soundEffectSource;
KyraEngine *_engine;
Audio::Mixer *_mixer;
AudioStream *_currentVocFile;
Audio::SoundHandle _vocHandle;
};
} // end of namespace Kyra
#endif