aboutsummaryrefslogtreecommitdiff
path: root/engines/chewy/video
diff options
context:
space:
mode:
authorFilippos Karapetis2016-09-26 04:10:02 +0300
committerFilippos Karapetis2016-10-03 00:33:57 +0300
commit7234574370d20684263e5e4f635348d161b8ce3a (patch)
tree9bb0ab3c4f112beeed7faee8dfc06e1adf21e463 /engines/chewy/video
parentecc212a31ab94e1abda628217eacff9ac6f39948 (diff)
downloadscummvm-rg350-7234574370d20684263e5e4f635348d161b8ce3a.tar.gz
scummvm-rg350-7234574370d20684263e5e4f635348d161b8ce3a.tar.bz2
scummvm-rg350-7234574370d20684263e5e4f635348d161b8ce3a.zip
CHEWY: Add support for sound effects in videos
Diffstat (limited to 'engines/chewy/video')
-rw-r--r--engines/chewy/video/cfo_decoder.cpp120
-rw-r--r--engines/chewy/video/cfo_decoder.h15
2 files changed, 100 insertions, 35 deletions
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];
};
};