diff options
-rw-r--r-- | engines/chewy/resource.cpp | 1 | ||||
-rw-r--r-- | engines/chewy/video/cfo_decoder.cpp | 120 | ||||
-rw-r--r-- | engines/chewy/video/cfo_decoder.h | 15 |
3 files changed, 100 insertions, 36 deletions
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp index a873edf563..23ac5c2ef2 100644 --- a/engines/chewy/resource.cpp +++ b/engines/chewy/resource.cpp @@ -34,7 +34,6 @@ namespace Chewy { // ====================== // back/episode1.gep // cut/blende.rnd -// cut/cut.tap // misc/*.taf, room/*.taf // misc/exit.eib // misc/inventar.iib diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp index 99fd665523..bfdf0656bb 100644 --- a/engines/chewy/video/cfo_decoder.cpp +++ b/engines/chewy/video/cfo_decoder.cpp @@ -20,7 +20,12 @@ * */ +#include "audio/audiostream.h" +#include "audio/mixer.h" +#include "audio/decoders/raw.h" #include "common/stream.h" +#include "common/system.h" +#include "engines/engine.h" #include "video/flic_decoder.h" #include "chewy/video/cfo_decoder.h" @@ -47,7 +52,7 @@ enum CustomSubChunk { kChunkFreeSoundEffect = 16, kChunkMusicFadeIn = 17, kChunkMusicFadeOut = 18, - kChunkSetStero = 19, + kChunkSetBalance = 19, kChunkSetSpeed = 20, kChunkClearScreen = 21 }; @@ -71,6 +76,19 @@ bool CfoDecoder::loadStream(Common::SeekableReadStream *stream) { CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) : Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) { readHeader(); + + for (int i = 0; i < MAX_SOUND_EFFECTS; i++) { + _soundEffects[i] = nullptr; + _soundEffectSize[i] = 0; + } +} + +CfoDecoder::CfoVideoTrack::~CfoVideoTrack() { + g_engine->_mixer->stopAll(); + + for (int i = 0; i < MAX_SOUND_EFFECTS; i++) { + delete[] _soundEffects[i]; + } } void CfoDecoder::CfoVideoTrack::readHeader() { @@ -154,107 +172,145 @@ void CfoDecoder::CfoVideoTrack::handleFrame() { void CfoDecoder::CfoVideoTrack::handleCustomFrame() { uint16 chunkCount = _fileStream->readUint16LE(); + uint16 delay, number, channel, volume, repeat, balance; + Audio::AudioStream *stream; + // Read subchunks for (uint32 i = 0; i < chunkCount; ++i) { uint32 frameSize = _fileStream->readUint32LE(); uint16 frameType = _fileStream->readUint16LE(); - uint8 *data = new uint8[frameSize]; - _fileStream->read(data, frameSize); switch (frameType) { case kChunkFadeIn: - warning("kChunkFadeIn"); + delay = _fileStream->readUint16LE(); + + warning("kChunkFadeIn, delay %d", delay); // TODO break; case kChunkFadeOut: - warning("kChunkFadeOut"); + delay = _fileStream->readUint16LE(); + + warning("kChunkFadeOut, delay %d", delay); // TODO break; case kChunkLoadMusic: warning("kChunkLoadMusic"); // TODO + _fileStream->skip(frameSize); break; case kChunkLoadRaw: - warning("kChunkLoadRaw"); - // TODO + error("Unused chunk kChunkLoadRaw found"); break; case kChunkLoadVoc: - warning("kChunkLoadVoc"); - // TODO + number = _fileStream->readUint16LE(); + assert(number < MAX_SOUND_EFFECTS); + delete[] _soundEffects[number]; + + _soundEffectSize[number] = frameSize - 2; + _soundEffects[number] = (byte *)malloc(frameSize - 2); + _fileStream->read(_soundEffects[number], frameSize - 2); break; case kChunkPlayMusic: warning("kChunkPlayMusic"); + // TODO + _fileStream->skip(frameSize); break; case kChunkPlaySeq: warning("kChunkPlaySeq"); // TODO + _fileStream->skip(frameSize); break; case kChunkPlayPattern: warning("kChunkPlayPattern"); // TODO + _fileStream->skip(frameSize); break; case kChunkStopMusic: - warning("kChunkStopMusic"); - // TODO + g_engine->_mixer->stopHandle(_musicHandle); break; case kChunkWaitMusicEnd: - warning("kChunkWaitMusicEnd"); - // TODO + do { + g_system->delayMillis(10); + } while (g_engine->_mixer->isSoundHandleActive(_musicHandle)); break; case kChunkSetMusicVolume: - warning("kChunkSetMusicVolume"); - // TODO + volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63; + + g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType, volume); break; case kChunkSetLoopMode: warning("kChunkSetLoopMode"); // TODO + _fileStream->skip(frameSize); break; case kChunkPlayRaw: - warning("kChunkPlayRaw"); - // TODO + error("Unused chunk kChunkPlayRaw found"); break; case kChunkPlayVoc: - warning("kChunkPlayVoc"); - // TODO + number = _fileStream->readUint16LE(); + channel = _fileStream->readUint16LE(); + volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63; + repeat = _fileStream->readUint16LE(); + assert(number < MAX_SOUND_EFFECTS); + assert(channel < MAX_SOUND_EFFECTS); + + stream = Audio::makeLoopingAudioStream( + Audio::makeRawStream(_soundEffects[number], + _soundEffectSize[number], 22050, Audio::FLAG_UNSIGNED, + DisposeAfterUse::NO), + (repeat == 0) ? 1 : repeat); + + g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume); + g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream); break; case kChunkSetSoundVolume: - warning("kChunkSetSoundVolume"); - // TODO + volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63; + + g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume); break; case kChunkSetChannelVolume: - warning("kChunkSetChannelVolume"); - // TODO + channel = _fileStream->readUint16LE(); + volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63; + assert(channel < MAX_SOUND_EFFECTS); + + g_engine->_mixer->setChannelVolume(_soundHandle[channel], volume); break; case kChunkFreeSoundEffect: - warning("kChunkFreeSoundEffect"); - // TODO + number = _fileStream->readUint16LE(); + assert(number < MAX_SOUND_EFFECTS); + + delete[] _soundEffects[number]; + _soundEffects[number] = nullptr; break; case kChunkMusicFadeIn: warning("kChunkMusicFadeIn"); // TODO + _fileStream->skip(frameSize); break; case kChunkMusicFadeOut: warning("kChunkMusicFadeOut"); // TODO + _fileStream->skip(frameSize); break; - case kChunkSetStero: - warning("kChunkSetStero"); - // TODO + case kChunkSetBalance: + channel = _fileStream->readUint16LE(); + balance = (_fileStream->readUint16LE() * 2) - 127; + assert(channel < MAX_SOUND_EFFECTS); + + g_engine->_mixer->setChannelBalance(_soundHandle[channel], balance); break; case kChunkSetSpeed: warning("kChunkSetSpeed"); // TODO + _fileStream->skip(frameSize); break; case kChunkClearScreen: - warning("kChunkClearScreen"); - // TODO + g_system->fillScreen(0); break; default: error("Unknown subchunk: %d", frameType); break; } - - delete[] data; } } diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h index 57c083858f..9150d681a1 100644 --- a/engines/chewy/video/cfo_decoder.h +++ b/engines/chewy/video/cfo_decoder.h @@ -23,12 +23,14 @@ #ifndef CHEWY_VIDEO_CFO_DECODER_H #define CHEWY_VIDEO_CFO_DECODER_H - +#include "audio/mixer.h" #include "graphics/surface.h" #include "video/flic_decoder.h" namespace Chewy { +#define MAX_SOUND_EFFECTS 10 + // A FLIC decoder, with a modified header and additional custom frames class CfoDecoder : public Video::FlicDecoder { public: @@ -37,11 +39,11 @@ public: bool loadStream(Common::SeekableReadStream *stream); -protected: +private: class CfoVideoTrack : public Video::FlicDecoder::FlicVideoTrack { public: CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height); - ~CfoVideoTrack() {} + virtual ~CfoVideoTrack(); void readHeader(); @@ -49,8 +51,15 @@ protected: bool rewind() { return false; } const ::Graphics::Surface *decodeNextFrame(); + + private: void handleFrame(); void handleCustomFrame(); + + Audio::SoundHandle _musicHandle; + Audio::SoundHandle _soundHandle[MAX_SOUND_EFFECTS]; + byte *_soundEffects[MAX_SOUND_EFFECTS]; + uint32 _soundEffectSize[MAX_SOUND_EFFECTS]; }; }; |