fix for bug #769744 (COMI: Trying to append to a nonexistant stream)

svn-id: r9025
This commit is contained in:
Max Horn 2003-07-14 21:37:45 +00:00
parent 42d0b2e6f7
commit bb87787314
5 changed files with 77 additions and 92 deletions

View File

@ -2251,11 +2251,9 @@ void Scumm_v6::o6_talkActor() {
}
pointer[j] = 0;
// Stop any talking that's still going on
if (_sound->_talkChannel > -1)
_mixer->stop(_sound->_talkChannel);
// Play speech
_sound->playBundleSound(pointer, &_sound->_talkChannelHandle);
_sound->_talkChannel = _sound->playBundleSound(pointer);
_messagePtr = _transText;
}
@ -3108,11 +3106,9 @@ void Scumm_v6::decodeParseString(int m, int n) {
}
pointer[j] = 0;
// Stop any talking that's still going on
if (_sound->_talkChannel > -1)
_mixer->stop(_sound->_talkChannel);
// Play speech
_sound->playBundleSound(pointer, &_sound->_talkChannelHandle);
_sound->_talkChannel = _sound->playBundleSound(pointer);
_messagePtr = _transText;
}

View File

@ -513,13 +513,8 @@ void Scumm_v8::decodeParseString(int m, int n) {
}
pointer[j] = 0;
int new_sound = _sound->playBundleSound(pointer);
if (new_sound != -1) {
// Stop any talking that's still going on
if (_sound->_talkChannel > -1)
_mixer->stop(_sound->_talkChannel);
_sound->_talkChannel = new_sound;
}
// Play speech
_sound->playBundleSound(pointer, &_sound->_talkChannelHandle);
_messagePtr = _transText;
}

View File

@ -91,7 +91,7 @@ Sound::Sound(Scumm *parent) {
_musicBundleBufFinal = NULL;
_musicBundleBufOutput = NULL;
_musicDisk = 0;
_talkChannel = -1;
_talkChannelHandle = 0;
_current_cache = 0;
_currentCDSound = 0;
@ -535,14 +535,15 @@ void Sound::processSfxQueues() {
if (_talk_sound_mode != 0) {
if (_talk_sound_mode & 1)
startTalkSound(_talk_sound_a1, _talk_sound_b1, 1);
if (_talk_sound_mode & 2)
_talkChannel = startTalkSound(_talk_sound_a2, _talk_sound_b2, 2);
if (_talk_sound_mode & 2) {
startTalkSound(_talk_sound_a2, _talk_sound_b2, 2, &_talkChannelHandle);
}
_talk_sound_mode = 0;
}
if (_scumm->VAR(_scumm->VAR_TALK_ACTOR)) { //_sfxMode & 2) {
act = _scumm->VAR(_scumm->VAR_TALK_ACTOR);
finished = (_talkChannel >= 0) && (_scumm->_mixer->_channels[_talkChannel] == NULL);
finished = !_talkChannelHandle;
if (act != 0 && (uint) act < 0x80 && !_scumm->_string[0].no_talk_anim) {
a = _scumm->derefActor(act, "processSfxQueues");
@ -564,7 +565,6 @@ void Sound::processSfxQueues() {
if (finished && _scumm->_talkDelay == 0) {
_scumm->stopTalk();
_sfxMode &= ~2;
_talkChannel = -1;
}
}
@ -579,14 +579,14 @@ static int compareMP3OffsetTable(const void *a, const void *b) {
return ((const MP3OffsetTable *)a)->org_offset - ((const MP3OffsetTable *)b)->org_offset;
}
int Sound::startTalkSound(uint32 offset, uint32 b, int mode) {
void Sound::startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle *handle) {
int num = 0, i;
int size;
byte *sound;
if (_sfxFile->isOpen() == false) {
warning("startTalkSound: SFX file is not open");
return -1;
return;
}
// FIXME hack until more is known
@ -597,8 +597,8 @@ int Sound::startTalkSound(uint32 offset, uint32 b, int mode) {
_sfxFile->seek(offset + 48, SEEK_SET);
sound = (byte *)malloc(b - 64);
_sfxFile->read(sound, b - 64);
_scumm->_mixer->playRaw(NULL, sound, b - 64, 11025, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
return -1;
_scumm->_mixer->playRaw(handle, sound, b - 64, 11025, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
return;
}
// Some games frequently assume that starting one sound effect will
@ -610,11 +610,13 @@ int Sound::startTalkSound(uint32 offset, uint32 b, int mode) {
// HACK: Checking for script 99 in Sam & Max is to keep Conroy's song
// from being interrupted.
int talkChannel = (_talkChannelHandle - 1);
if (mode == 1 && (_scumm->_gameId == GID_TENTACLE
|| (_scumm->_gameId == GID_SAMNMAX && !_scumm->isScriptRunning(99)))) {
for (i = 0; i < _scumm->_mixer->NUM_CHANNELS; i++) {
if (i != _talkChannel)
if (i != talkChannel) {
_scumm->_mixer->stop(i);
}
}
}
@ -631,7 +633,7 @@ int Sound::startTalkSound(uint32 offset, uint32 b, int mode) {
if (result == NULL) {
warning("startTalkSound: did not find sound at offset %d !", offset);
return -1;
return;
}
if (2 * num != result->num_tags) {
warning("startTalkSound: number of tags do not match (%d - %d) !", b,
@ -656,15 +658,12 @@ int Sound::startTalkSound(uint32 offset, uint32 b, int mode) {
_curSoundPos = 0;
_mouthSyncMode = true;
return startSfxSound(_sfxFile, size);
startSfxSound(_sfxFile, size, handle);
}
void Sound::stopTalkSound() {
if (_sfxMode & 2) {
if (_talkChannel != -1) {
_scumm->_mixer->stop(_talkChannel);
_talkChannel = -1;
}
_scumm->_mixer->stopHandle(_talkChannelHandle);
_sfxMode &= ~2;
}
}
@ -904,7 +903,7 @@ void Sound::pauseSounds(bool pause) {
}
}
int Sound::startSfxSound(File *file, int file_size) {
void Sound::startSfxSound(File *file, int file_size, PlayingSoundHandle *handle) {
char ident[8];
int block_type;
byte work[8];
@ -913,7 +912,7 @@ int Sound::startSfxSound(File *file, int file_size) {
byte *data;
if (_scumm->_noDigitalSamples)
return -1;
return;
if (file_size > 0) {
int alloc_size = file_size;
@ -926,12 +925,12 @@ int Sound::startSfxSound(File *file, int file_size) {
if (file->read(data, file_size) != (uint)file_size) {
/* no need to free the memory since error will shut down */
error("startSfxSound: cannot read %d bytes", size);
return -1;
}
if (_vorbis_mode)
return playSfxSound_Vorbis(data, file_size);
playSfxSound_Vorbis(data, file_size, handle);
else
return playSfxSound_MP3(data, file_size);
playSfxSound_MP3(data, file_size, handle);
return;
}
if (file->read(ident, 8) != 8)
@ -944,13 +943,13 @@ int Sound::startSfxSound(File *file, int file_size) {
} else {
invalid:;
warning("startSfxSound: invalid header");
return -1;
return;
}
block_type = file->readByte();
if (block_type != 1) {
warning("startSfxSound: Expecting block_type == 1, got %d", block_type);
return -1;
return;
}
file->read(work, 3);
@ -961,22 +960,20 @@ int Sound::startSfxSound(File *file, int file_size) {
if (comp != 0) {
warning("startSfxSound: Unsupported compression type %d", comp);
return -1;
return;
}
data = (byte *)malloc(size);
if (data == NULL) {
error("startSfxSound: out of memory");
return -1;
}
if (file->read(data, size) != size) {
/* no need to free the memory since error will shut down */
error("startSfxSound: cannot read %d bytes", size);
return -1;
}
return playSfxSound(data, size, 1000000 / (256 - rate), true);
playSfxSound(data, size, 1000000 / (256 - rate), true, handle);
}
File *Sound::openSfxFile() {
@ -1288,13 +1285,13 @@ void Sound::bundleMusicHandler(Scumm *scumm) {
free(buffer);
}
int Sound::playBundleSound(char *sound) {
byte *ptr = 0, *orig_ptr;
void Sound::playBundleSound(char *sound, PlayingSoundHandle *handle) {
byte *ptr = 0, *orig_ptr = 0;
byte *final;
bool result;
if (_scumm->_noDigitalSamples)
return -1;
return;
if (_scumm->_gameId == GID_CMI) {
char voxfile[20];
@ -1312,9 +1309,8 @@ int Sound::playBundleSound(char *sound) {
else
error("Don't know which bundle file to load");
if (!result) {
return -1;
}
if (!result)
return;
int32 rate = 22050, channels, output_size = 0;
int32 tag, size = -1, bits = 0;
@ -1378,44 +1374,42 @@ int Sound::playBundleSound(char *sound) {
final = (byte *)malloc(size);
memcpy(final, ptr, size);
free(orig_ptr);
if (_scumm->_actorToPrintStrFor != 0xFF && _scumm->_actorToPrintStrFor != 0) {
Actor *a = _scumm->derefActor(_scumm->_actorToPrintStrFor, "playBundleSound");
rate = (rate * a->talkFrequency) / 256;
}
// Stop any sound currently playing on the given handle
if (handle)
_scumm->_mixer->stopHandle(*handle);
if (bits == 8) {
return _scumm->_mixer->playRaw(NULL, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
} else if (bits == 16){
return _scumm->_mixer->playRaw(NULL, final, size, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE);
_scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_UNSIGNED | SoundMixer::FLAG_AUTOFREE);
} else if (bits == 16) {
_scumm->_mixer->playRaw(handle, final, size, rate, SoundMixer::FLAG_16BITS | SoundMixer::FLAG_AUTOFREE);
} else {
warning("Sound::playBundleSound() to do more options to playRaw...");
return -1;
}
bail:
if (orig_ptr)
free(orig_ptr);
return -1;
free(orig_ptr);
}
int Sound::playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned) {
void Sound::playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned, PlayingSoundHandle *handle) {
if (_soundsPaused)
return -1;
return;
byte flags = SoundMixer::FLAG_AUTOFREE;
if (isUnsigned)
flags |= SoundMixer::FLAG_UNSIGNED;
return _scumm->_mixer->playRaw(NULL, sound, size, rate, flags);
_scumm->_mixer->playRaw(handle, sound, size, rate, flags);
}
int Sound::playSfxSound_MP3(void *sound, uint32 size) {
void Sound::playSfxSound_MP3(void *sound, uint32 size, PlayingSoundHandle *handle) {
#ifdef USE_MAD
if (_soundsPaused || _scumm->_noDigitalSamples)
return -1;
return _scumm->_mixer->playMP3(NULL, sound, size, SoundMixer::FLAG_AUTOFREE);
if (!_soundsPaused && !_scumm->_noDigitalSamples)
_scumm->_mixer->playMP3(handle, sound, size, SoundMixer::FLAG_AUTOFREE);
#endif
return -1;
}
#ifdef USE_VORBIS
@ -1480,27 +1474,23 @@ static ov_callbacks data_wrap = {
};
#endif
int Sound::playSfxSound_Vorbis(void *sound, uint32 size) {
void Sound::playSfxSound_Vorbis(void *sound, uint32 size, PlayingSoundHandle *handle) {
#ifdef USE_VORBIS
if (_soundsPaused || _scumm->_noDigitalSamples)
return -1;
OggVorbis_File *ov_file = new OggVorbis_File;
data_file_info *f = new data_file_info;
f->data = (char *) sound;
f->size = size;
f->curr_pos = 0;
if (ov_open_callbacks((void *) f, ov_file, NULL, 0, data_wrap) < 0) {
warning("Invalid file format");
delete ov_file;
delete f;
return -1;
if (!_soundsPaused && !_scumm->_noDigitalSamples) {
OggVorbis_File *ov_file = new OggVorbis_File;
data_file_info *f = new data_file_info;
f->data = (char *) sound;
f->size = size;
f->curr_pos = 0;
if (ov_open_callbacks((void *) f, ov_file, NULL, 0, data_wrap) < 0) {
warning("Invalid file format");
delete ov_file;
delete f;
} else
_scumm->_mixer->playVorbis(handle, ov_file, 0, false);
}
return _scumm->_mixer->playVorbis(NULL, ov_file, 0, false);
#endif
return -1;
}
// We use a real timer in an attempt to get better sync with CD tracks. This is

View File

@ -22,6 +22,7 @@
#define SOUND_H
#include "scummsys.h"
#include "sound/mixer.h"
class Bundle;
class DigitalTrackInfo;
@ -100,7 +101,7 @@ protected:
public:
int32 _bundleMusicPosition;
int _talkChannel; /* Mixer channel actor is talking on */
PlayingSoundHandle _talkChannelHandle; // Handle of mixer channel actor is talking on
bool _soundsPaused;
byte _sfxMode;
@ -118,7 +119,7 @@ public:
void processSoundQues();
void playSound(int sound);
void processSfxQueues();
int startTalkSound(uint32 offset, uint32 b, int mode);
void startTalkSound(uint32 offset, uint32 b, int mode, PlayingSoundHandle *handle = NULL);
void stopTalkSound();
bool isMouthSyncOff(uint pos);
int isSoundRunning(int sound) const;
@ -135,7 +136,7 @@ public:
void pauseBundleMusic(bool state);
void bundleMusicHandler(Scumm *scumm);
void stopBundleMusic();
int playBundleSound(char *sound);
void playBundleSound(char *sound, PlayingSoundHandle *handle);
uint32 decode12BitsSample(byte *src, byte **dst, uint32 size, bool stereo);
@ -152,12 +153,12 @@ protected:
void clearSoundQue();
File *openSfxFile();
int startSfxSound(File *file, int file_size);
void startSfxSound(File *file, int file_size, PlayingSoundHandle *handle);
void stopSfxSound();
bool isSfxFinished() const;
int playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned);
int playSfxSound_MP3(void *sound, uint32 size);
int playSfxSound_Vorbis(void *sound, uint32 size);
void playSfxSound(void *sound, uint32 size, uint rate, bool isUnsigned, PlayingSoundHandle *handle);
void playSfxSound_MP3(void *sound, uint32 size, PlayingSoundHandle *handle);
void playSfxSound_Vorbis(void *sound, uint32 size, PlayingSoundHandle *handle);
int getCachedTrack(int track);
int playMP3CDTrack(int track, int numLoops, int startFrame, int endFrame);

View File

@ -153,7 +153,7 @@ void Scumm::CHARSET_1() {
// FIXME: DIG and CMI never set sfxMode or any actor talk data...
// This hack will force the backup cutoff system to be used instead,
// unless the talkChannel is null (eg, this string has no sound attached)
if ((_gameId == GID_CMI || _gameId == GID_DIG) && (_sound->_talkChannel >= 0))
if ((_gameId == GID_CMI || _gameId == GID_DIG) && _sound->_talkChannelHandle)
return;
if ((_sound->_sfxMode & 2) == 0)
@ -298,7 +298,7 @@ void Scumm::CHARSET_1() {
if (_version <= 3) {
_charset->printChar(c);
} else {
if (_noSubtitles && (_haveMsg == 0xFE || _sound->_talkChannel >= 0)) {
if (_noSubtitles && (_haveMsg == 0xFE || _sound->_talkChannelHandle)) {
// Subtitles are turned off, and there is a voice version
// of this message -> don't print it.
} else
@ -594,7 +594,10 @@ void Scumm::addVerbToStack(int var)
pointer[j++] = ptr[i];
}
pointer[j] = 0;
_sound->_talkChannel = _sound->playBundleSound(pointer);
// Play speech
_sound->playBundleSound(pointer, &_sound->_talkChannelHandle);
addMessageToStack(_transText);
} else {
addMessageToStack(ptr);