From 02e2b78e5c2e1f63668d32183a2ba5d2b57c4031 Mon Sep 17 00:00:00 2001 From: Benjamin Haisch Date: Mon, 22 Sep 2008 20:55:26 +0000 Subject: TOLTECS: Added sound to the movie player (finally). Still TODO: Ability to abort movies. --- engines/toltecs/movie.cpp | 85 +++++++++++++++++++++++++++++++++++++++++------ engines/toltecs/movie.h | 13 ++++++-- 2 files changed, 84 insertions(+), 14 deletions(-) (limited to 'engines/toltecs') diff --git a/engines/toltecs/movie.cpp b/engines/toltecs/movie.cpp index ef280fa508..b5665aaf47 100644 --- a/engines/toltecs/movie.cpp +++ b/engines/toltecs/movie.cpp @@ -49,7 +49,7 @@ MoviePlayer::~MoviePlayer() { void MoviePlayer::playMovie(uint resIndex) { - uint32 chunkCount, frameCount, subtitleSlot; + uint32 subtitleSlot; byte moviePalette[768]; memset(moviePalette, 0, sizeof(moviePalette)); @@ -59,19 +59,34 @@ void MoviePlayer::playMovie(uint resIndex) { _vm->_arc->openResource(resIndex); - frameCount = _vm->_arc->readUint32LE(); - chunkCount = _vm->_arc->readUint32LE(); subtitleSlot = kMaxScriptSlots - 1; - - // TODO: Read/figure out rest of the header - _vm->_arc->seek(0x10, SEEK_CUR); + + _frameCount = _vm->_arc->readUint32LE(); + _chunkCount = _vm->_arc->readUint32LE(); + + // TODO: Figure out rest of the header + _vm->_arc->readUint32LE(); + _vm->_arc->readUint32LE(); + _framesPerSoundChunk = _vm->_arc->readUint32LE(); + _vm->_arc->readUint32LE(); + _vm->_sceneWidth = 640; _vm->_sceneHeight = 400; _vm->_cameraHeight = 400; _vm->_cameraX = 0; _vm->_cameraY = 0; - while (chunkCount--) { + _audioStream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_UNSIGNED); + + _vm->_mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream); + + _soundChunkFramesLeft = 0; + _lastPrefetchOfs = 0; + fetchAudioChunks(); + + uint32 lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle); + + while (_chunkCount--) { byte chunkType; uint32 chunkSize; @@ -91,12 +106,25 @@ void MoviePlayer::playMovie(uint resIndex) { switch (chunkType) { case 0: // image data case 1: + unpackRle(chunkBuffer, _vm->_screen->_backScreen); // TODO: Rework this _vm->_screen->updateShakeScreen(); + _vm->_screen->_fullRefresh = true; _vm->updateInput(); _vm->updateScreen(); - g_system->delayMillis(80); + + _soundChunkFramesLeft--; + if (_soundChunkFramesLeft <= _framesPerSoundChunk) { + fetchAudioChunks(); + } + + while (_vm->_mixer->getSoundElapsedTime(_audioStreamHandle) < lastTime + 111) { + g_system->delayMillis(0); + } + + lastTime = _vm->_mixer->getSoundElapsedTime(_audioStreamHandle); + break; case 2: // palette data unpackPalette(chunkBuffer, moviePalette, 256, 3); @@ -104,7 +132,6 @@ void MoviePlayer::playMovie(uint resIndex) { break; //case 3: -- what is this type case 4: // audio data - // TODO: Handle audio data break; case 5: // TODO: Check if the text is a subtitle (last character == 0xFE). @@ -119,8 +146,8 @@ void MoviePlayer::playMovie(uint resIndex) { _vm->_screen->startShakeScreen(chunkBuffer[0]); break; case 7: // setup subtitle parameters - _vm->_screen->_talkTextY = READ_LE_UINT16(&chunkBuffer[0]); - _vm->_screen->_talkTextX = READ_LE_UINT16(&chunkBuffer[2]); + _vm->_screen->_talkTextY = READ_LE_UINT16(chunkBuffer + 0); + _vm->_screen->_talkTextX = READ_LE_UINT16(chunkBuffer + 2); _vm->_screen->_talkTextFontColor = chunkBuffer[4]; debug(0, "_talkTextX = %d; _talkTextY = %d; _talkTextFontColor = %d", _vm->_screen->_talkTextX, _vm->_screen->_talkTextY, _vm->_screen->_talkTextFontColor); @@ -139,7 +166,43 @@ void MoviePlayer::playMovie(uint resIndex) { } + _audioStream->finish(); + _vm->_mixer->stopHandle(_audioStreamHandle); + _vm->_arc->closeResource(); + + debug(0, "playMovie() done"); + +} + +void MoviePlayer::fetchAudioChunks() { + + uint32 startOfs = _vm->_arc->pos(); + uint32 chunkCount = _chunkCount; + uint prefetchChunkCount = 0; + + if (_lastPrefetchOfs != 0) + _vm->_arc->seek(_lastPrefetchOfs, SEEK_SET); + + while (chunkCount-- && prefetchChunkCount < _framesPerSoundChunk / 2) { + byte chunkType = _vm->_arc->readByte(); + uint32 chunkSize = _vm->_arc->readUint32LE(); + if (chunkType == 4) { + byte *chunkBuffer = new byte[chunkSize]; + _vm->_arc->read(chunkBuffer, chunkSize); + _audioStream->queueBuffer(chunkBuffer, chunkSize); + chunkBuffer = NULL; + prefetchChunkCount++; + _soundChunkFramesLeft += _framesPerSoundChunk; + delete[] chunkBuffer; + } else { + _vm->_arc->seek(chunkSize, SEEK_CUR); + } + } + + _lastPrefetchOfs = _vm->_arc->pos(); + + _vm->_arc->seek(startOfs, SEEK_SET); } diff --git a/engines/toltecs/movie.h b/engines/toltecs/movie.h index 9ab5435121..40b1f2ea27 100644 --- a/engines/toltecs/movie.h +++ b/engines/toltecs/movie.h @@ -47,16 +47,23 @@ namespace Toltecs { class MoviePlayer { public: - MoviePlayer(ToltecsEngine *vm); - ~MoviePlayer(); + MoviePlayer(ToltecsEngine *vm); + ~MoviePlayer(); void playMovie(uint resIndex); protected: - ToltecsEngine *_vm; + ToltecsEngine *_vm; + Audio::AppendableAudioStream *_audioStream; + Audio::SoundHandle _audioStreamHandle; + + uint32 _chunkCount, _frameCount, _lastPrefetchOfs; + uint32 _soundChunkFramesLeft, _framesPerSoundChunk; void unpackPalette(byte *source, byte *dest, int elemCount, int elemSize); void unpackRle(byte *source, byte *dest); + + void fetchAudioChunks(); }; -- cgit v1.2.3