- Implemented opcode 97: o2_isAnySoundPlaying

- reworked sound channel handling in HoF
  => fixed some voice related bugs

svn-id: r31209
This commit is contained in:
Johannes Schickel 2008-03-21 16:18:27 +00:00
parent 88069c943a
commit a169619526
10 changed files with 104 additions and 43 deletions

View File

@ -53,6 +53,7 @@ KyraEngine::KyraEngine(OSystem *system, const GameFlags &flags)
_quitFlag = false;
_speechFile = "";
_trackMap = 0;
_trackMapSize = 0;
_lastMusicCommand = -1;

View File

@ -84,6 +84,12 @@ enum kDebugLevels {
kDebugLevelTimer = 1 << 10 // prints debug output of "TimerManager" functions
};
enum kMusicDataID {
kMusicIntro = 0,
kMusicIngame,
kMusicFinale
};
class Screen;
class Resource;
class Sound;
@ -191,6 +197,8 @@ protected:
uint8 _flagsTable[100]; // TODO: check this value
// sound
Common::String _speechFile;
int _curMusicTheme;
int _curSfxFile;
int16 _lastMusicCommand;

View File

@ -1708,6 +1708,7 @@ void KyraEngine_v2::restoreGfxRect32x32(int x, int y) {
#pragma mark -
void KyraEngine_v2::openTalkFile(int newFile) {
debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v2::openTalkFile(%d)", newFile);
char talkFilename[16];
if (_oldTalkFile > 0) {
@ -1732,10 +1733,17 @@ void KyraEngine_v2::snd_playVoiceFile(int id) {
char vocFile[9];
assert(id >= 0 && id <= 9999999);
sprintf(vocFile, "%07d", id);
_sound->voicePlay(vocFile);
if (_sound->voiceFileIsPresent(vocFile)) {
while (!_sound->voicePlay(vocFile)) {
updateWithText();
_system->delayMillis(10);
}
_speechFile = vocFile;
}
}
void KyraEngine_v2::snd_loadSoundFile(int id) {
debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v2::snd_loadSoundFile(%d)", id);
if (id < 0 || !_trackMap)
return;
@ -1746,6 +1754,7 @@ void KyraEngine_v2::snd_loadSoundFile(int id) {
}
void KyraEngine_v2::playVoice(int high, int low) {
debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine_v2::playVoice(%d, %d)", high, low);
if (!_flags.isTalkie)
return;
int vocFile = high * 10000 + low * 10;

View File

@ -158,12 +158,6 @@ struct NestedSequence {
uint16 finalCommand;
};
enum kMusicDataID {
kMusicIntro = 0,
kMusicIngame,
kMusicFinale
};
class KyraEngine_v2 : public KyraEngine {
friend class Debugger_v2;
friend class TextDisplayer_v2;
@ -1036,6 +1030,7 @@ protected:
int o2_setCauldronState(ScriptState *script);
int o2_showItemString(ScriptState *script);
int o2_getRand(ScriptState *script);
int o2_isAnySoundPlaying(ScriptState *script);
int o2_setDeathHandlerFlag(ScriptState *script);
int o2_setDrawNoShapeFlag(ScriptState *script);
int o2_setRunFlag(ScriptState *script);

View File

@ -884,6 +884,11 @@ int KyraEngine_v2::o2_getRand(ScriptState *script) {
return _rnd.getRandomNumberRng(stackPos(0), stackPos(1));
}
int KyraEngine_v2::o2_isAnySoundPlaying(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_isAnySoundPlaying(%p) ()", (const void *)script);
return _sound->voiceIsPlaying();
}
int KyraEngine_v2::o2_setDeathHandlerFlag(ScriptState *script) {
debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v2::o2_setDeathHandlerFlag(%p) (%d)", (const void *)script, stackPos(0));
_deathHandler = stackPos(0);
@ -1782,7 +1787,7 @@ void KyraEngine_v2::setupOpcodeTable() {
Opcode(o2_showItemString),
// 0x60
Opcode(o2_getRand),
OpcodeUnImpl(),
Opcode(o2_isAnySoundPlaying),
Opcode(o2_setDeathHandlerFlag),
Opcode(o2_setDrawNoShapeFlag),
// 0x64

View File

@ -1968,13 +1968,14 @@ void KyraEngine_v2::seq_cmpFadeFrame(const char *cmpFile) {
}
void KyraEngine_v2::seq_playTalkText(uint8 chatNum) {
debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playIntroChat(%i)", chatNum);
debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playTalkText(%i)", chatNum);
assert(chatNum < _sequenceSoundListSize);
if (chatNum < 12 && !_flags.isDemo && textEnabled())
seq_setTextEntry(chatNum, 160, 168, _sequenceStringsDuration[chatNum], 160);
_speechFile = _sequenceSoundList[chatNum];
_sound->voicePlay(_sequenceSoundList[chatNum]);
}

View File

@ -39,26 +39,44 @@
namespace Kyra {
Sound::Sound(KyraEngine *vm, Audio::Mixer *mixer)
: _vm(vm), _mixer(mixer), _currentVocFile(0), _vocHandles(),
_musicEnabled(1), _sfxEnabled(true), _soundDataList(0) {
: _vm(vm), _mixer(mixer), _soundChannels(), _musicEnabled(1),
_sfxEnabled(true), _soundDataList(0) {
}
Sound::~Sound() {
}
void Sound::voicePlay(const char *file) {
bool Sound::voiceFileIsPresent(const char *file) {
char filenamebuffer[25];
for (int i = 0; _supportedCodes[i].fileext; ++i) {
strcpy(filenamebuffer, file);
strcat(filenamebuffer, _supportedCodes[i].fileext);
if (_vm->resource()->getFileSize(filenamebuffer) > 0)
return true;
}
strcpy(filenamebuffer, file);
strcat(filenamebuffer, ".VOC");
if (_vm->resource()->getFileSize(filenamebuffer) > 0)
return true;
return false;
}
bool Sound::voicePlay(const char *file, bool isSfx) {
uint32 fileSize = 0;
byte *fileData = 0;
bool found = false;
char filenamebuffer[25];
int h = 0;
if (_currentVocFile) {
while (_mixer->isSoundHandleActive(_vocHandles[h]))
h++;
if (h >= kNumVocHandles)
return;
}
while (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle) && h < kNumChannelHandles)
h++;
if (h >= kNumChannelHandles)
return false;
Audio::AudioStream *audioStream = 0;
for (int i = 0; _supportedCodes[i].fileext; ++i) {
strcpy(filenamebuffer, file);
@ -67,7 +85,7 @@ void Sound::voicePlay(const char *file) {
Common::SeekableReadStream *stream = _vm->resource()->getFileStream(filenamebuffer);
if (!stream)
continue;
_currentVocFile = _supportedCodes[i].streamFunc(stream, true, 0, 0, 1);
audioStream = _supportedCodes[i].streamFunc(stream, true, 0, 0, 1);
found = true;
break;
}
@ -78,30 +96,47 @@ void Sound::voicePlay(const char *file) {
fileData = _vm->resource()->fileData(filenamebuffer, &fileSize);
if (!fileData)
return;
return false;
Common::MemoryReadStream vocStream(fileData, fileSize);
_currentVocFile = Audio::makeVOCStream(vocStream);
audioStream = Audio::makeVOCStream(vocStream);
}
_mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_vocHandles[h], _currentVocFile);
_soundChannels[h].file = file;
_mixer->playInputStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].channelHandle, audioStream);
delete [] fileData;
fileSize = 0;
return true;
}
void Sound::voiceStop() {
for (int h = 0; h < kNumVocHandles; h++) {
if (_mixer->isSoundHandleActive(_vocHandles[h]))
_mixer->stopHandle(_vocHandles[h]);
void Sound::voiceStop(const char *file) {
if (!file) {
for (int h = 0; h < kNumChannelHandles; h++) {
if (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle))
_mixer->stopHandle(_soundChannels[h].channelHandle);
}
} else {
for (int i = 0; i < kNumChannelHandles; ++i) {
if (_soundChannels[i].file == file)
_mixer->stopHandle(_soundChannels[i].channelHandle);
}
}
}
bool Sound::voiceIsPlaying() {
bool Sound::voiceIsPlaying(const char *file) {
bool res = false;
for (int h = 0; h < kNumVocHandles; h++) {
if (_mixer->isSoundHandleActive(_vocHandles[h]))
res = true;
if (!file) {
for (int h = 0; h < kNumChannelHandles; h++) {
if (_mixer->isSoundHandleActive(_soundChannels[h].channelHandle))
res = true;
}
} else {
for (int i = 0; i < kNumChannelHandles; ++i) {
if (_soundChannels[i].file == file)
res = true;
}
}
return res;
}
@ -510,12 +545,12 @@ void KyraEngine::snd_playWanderScoreViaMap(int command, int restart) {
void KyraEngine::snd_stopVoice() {
debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_stopVoice()");
_sound->voiceStop();
_sound->voiceStop(_speechFile.empty() ? 0 : _speechFile.c_str());
}
bool KyraEngine::snd_voiceIsPlaying() {
debugC(9, kDebugLevelMain | kDebugLevelSound, "KyraEngine::snd_voiceIsPlaying()");
return _sound->voiceIsPlaying();
return _sound->voiceIsPlaying(_speechFile.empty() ? 0 : _speechFile.c_str());
}
// static res

View File

@ -52,7 +52,6 @@
#include "sound/softsynth/ym2612.h"
#include "kyra/kyra.h"
#include "kyra/kyra_v2.h"
namespace Audio {
class AudioStream;
@ -149,6 +148,8 @@ public:
void enableSFX(bool enable) { _sfxEnabled = enable; }
bool sfxEnabled() const { return _sfxEnabled; }
virtual bool voiceFileIsPresent(const char *file);
/**
* Plays the specified voice file.
*
@ -160,28 +161,29 @@ public:
* files
*
* @param file file to be played
* @param isSfx marks file as sfx instead of voice
* @return channel the voice file is played on
*/
virtual void voicePlay(const char *file);
virtual bool voicePlay(const char *file, bool isSfx = false);
/**
* Checks if a voice is being played.
*
* @return true when playing, else false
*/
bool voiceIsPlaying();
bool voiceIsPlaying(const char *file = 0);
/**
* Stops playback of the current voice.
*/
void voiceStop();
void voiceStop(const char *file = 0);
protected:
const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->_fileListLen) ? _soundDataList->_fileList[file] : ""; }
const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; }
const int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; }
enum {
kNumVocHandles = 4
kNumChannelHandles = 4
};
int _musicEnabled;
@ -194,8 +196,12 @@ protected:
private:
const AudioDataStruct *_soundDataList;
Audio::AudioStream *_currentVocFile;
Audio::SoundHandle _vocHandles[kNumVocHandles];
struct SoundChannel {
Common::String file;
Audio::SoundHandle channelHandle;
};
SoundChannel _soundChannels[kNumChannelHandles];
struct SpeechCodecs {
const char *fileext;
@ -429,7 +435,7 @@ private:
int _lastTrack;
Audio::AudioStream *_currentSFX;
Audio::SoundHandle _sfxHandles[kNumVocHandles];
Audio::SoundHandle _sfxHandles[kNumChannelHandles];
//SoundTowns_v2_TwnDriver *_driver;
uint8 *_twnTrackData;

View File

@ -1437,9 +1437,9 @@ void SoundTowns_v2::voicePlay(const char *file) {
int h = 0;
if (_currentSFX) {
while (_mixer->isSoundHandleActive(_sfxHandles[h]))
while (_mixer->isSoundHandleActive(_sfxHandles[h]) && h < kNumChannelHandles)
h++;
if (h >= kNumVocHandles)
if (h >= kNumChannelHandles)
return;
}

View File

@ -66,6 +66,7 @@ void KyraEngine_v1::snd_playVoiceFile(int id) {
char vocFile[9];
assert(id >= 0 && id < 9999);
sprintf(vocFile, "%03d", id);
_speechFile = vocFile;
_sound->voicePlay(vocFile);
}