DIRECTOR: Implement loading for SND data

This commit is contained in:
Scott Percival 2020-03-21 19:35:32 +08:00
parent 124b9ecc31
commit d36d0473d9
6 changed files with 135 additions and 9 deletions

View File

@ -121,6 +121,18 @@ BitmapCast::BitmapCast(Common::ReadStreamEndian &stream, uint32 castTag, uint16
_tag = castTag;
}
SoundCast::SoundCast(Common::ReadStreamEndian &stream, uint16 version) {
_type = kCastSound;
_audio = nullptr;
if (version == 4) {
for (int i = 0; i < 0xe; i++) {
stream.readByte();
}
_looping = stream.readByte() & 0x10;
}
}
TextCast::TextCast(Common::ReadStreamEndian &stream, uint16 version, int32 bgcolor) {
_type = kCastText;

View File

@ -30,6 +30,10 @@ namespace Graphics {
struct Surface;
}
namespace Audio {
struct SeekableAudioStream;
}
namespace Common {
class SeekableReadStream;
class ReadStreamEndian;
@ -71,6 +75,14 @@ public:
uint32 _tag;
};
class SoundCast : public Cast {
public:
SoundCast(Common::ReadStreamEndian &stream, uint16 version);
bool _looping;
Audio::SeekableAudioStream *_audio;
};
class ShapeCast : public Cast {
public:
ShapeCast(Common::ReadStreamEndian &stream, uint16 version);

View File

@ -26,6 +26,7 @@
#include "common/memstream.h"
#include "common/substream.h"
#include "audio/decoders/raw.h"
#include "engines/util.h"
#include "graphics/primitives.h"
#include "graphics/macgui/macfontmanager.h"
@ -243,11 +244,6 @@ void Score::loadArchive() {
debug("STUB: Unhandled 'PICT' resource");
}
// Sound resources
if (_movieArchive->hasResource(MKTAG('s', 'n', 'd', ' '), -1)) {
debug("STUB: Unhandled 'snd ' resource");
}
// Film Loop resources
if (_movieArchive->hasResource(MKTAG('S', 'C', 'V', 'W'), -1)) {
debug("STUB: Unhandled 'SCVW' resource");
@ -256,6 +252,7 @@ void Score::loadArchive() {
setSpriteCasts();
loadSpriteImages(false);
loadSpriteSounds(false);
// Now process STXTs
Common::Array<uint16> stxt = _movieArchive->getResourceIDList(MKTAG('S','T','X','T'));
@ -375,6 +372,43 @@ void Score::loadSpriteImages(bool isSharedCast) {
}
}
void Score::loadSpriteSounds(bool isSharedCast) {
debugC(1, kDebugLoading, "****** Preloading sprite sounds");
for (Common::HashMap<int, Cast *>::iterator c = _loadedCast->begin(); c != _loadedCast->end(); ++c) {
if (!c->_value)
continue;
if (c->_value->_type != kCastSound)
continue;
SoundCast *soundCast = (SoundCast *)c->_value;
uint32 tag = MKTAG('s', 'n', 'd', ' ');
uint16 sndId = (uint16)(c->_key + _castIDoffset);
if (_vm->getVersion() >= 4 && soundCast->_children.size() > 0) {
sndId = soundCast->_children[0].index;
tag = soundCast->_children[0].tag;
}
Common::SeekableSubReadStreamEndian *sndData = NULL;
switch (tag) {
case MKTAG('s', 'n', 'd', ' '):
if (_movieArchive->hasResource(MKTAG('s', 'n', 'd', ' '), sndId)) {
debugC(2, kDebugLoading, "****** Loading 'snd ' id: %d", sndId);
sndData = _movieArchive->getResource(MKTAG('s', 'n', 'd', ' '), sndId);
}
break;
}
if (sndData != NULL && soundCast != NULL) {
Audio::SeekableAudioStream *audio = makeSNDStream(sndData);
soundCast->_audio = audio;
}
}
}
Score::~Score() {
if (_surface && _surface->w)
@ -741,6 +775,10 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
debugC(3, kDebugLoading, "Score::loadCastData(): loading kCastBitmap (%d children)", res->children.size());
_loadedCast->setVal(id, new BitmapCast(castStream, res->tag, _vm->getVersion()));
break;
case kCastSound:
debugC(3, kDebugLoading, "Score::loadCastData(): loading kCastSound (%d children)", res->children.size());
_loadedCast->setVal(id, new SoundCast(castStream, _vm->getVersion()));
break;
case kCastText:
debugC(3, kDebugLoading, "Score::loadCastData(): loading kCastText (%d children)", res->children.size());
_loadedCast->setVal(id, new TextCast(castStream, _vm->getVersion(), _stageColor));
@ -773,10 +811,6 @@ void Score::loadCastData(Common::SeekableSubReadStreamEndian &stream, uint16 id,
warning("STUB: Score::loadCastData(): kCastPicture (%d children)", res->children.size());
size2 = 0;
break;
case kCastSound:
warning("STUB: Score::loadCastData(): kCastSound (%d children)", res->children.size());
size2 = 0;
break;
case kCastMovie:
warning("STUB: Score::loadCastData(): kCastMovie (%d children)", res->children.size());
size2 = 0;

View File

@ -89,6 +89,7 @@ public:
Sprite *getSpriteById(uint16 id);
void setSpriteCasts();
void loadSpriteImages(bool isSharedCast);
void loadSpriteSounds(bool isSharedCast);
void copyCastStxts();
Graphics::ManagedSurface *getSurface() { return _surface; }

View File

@ -21,12 +21,15 @@
*/
#include "common/file.h"
#include "common/substream.h"
#include "audio/decoders/wave.h"
#include "audio/decoders/raw.h"
#include "audio/mixer.h"
#include "audio/softsynth/pcspk.h"
#include "audio/decoders/aiff.h"
#include "director/director.h"
#include "director/sound.h"
namespace Director {
@ -92,6 +95,14 @@ void DirectorSound::playMCI(Audio::AudioStream &stream, uint32 from, uint32 to)
_mixer->playStream(Audio::Mixer::kSFXSoundType, _scriptSound, subSeekStream);
}
void DirectorSound::playStream(Audio::AudioStream &stream, uint8 soundChannel) {
Audio::SeekableAudioStream *seekStream = dynamic_cast<Audio::SeekableAudioStream *>(&stream);
if (soundChannel == 1)
_mixer->playStream(Audio::Mixer::kSFXSoundType, _sound1, seekStream);
else
_mixer->playStream(Audio::Mixer::kSFXSoundType, _sound2, seekStream);
}
bool DirectorSound::isChannelActive(uint8 channelID) {
if (channelID == 1) {
return _mixer->isSoundHandleActive(*_sound1);
@ -114,4 +125,56 @@ void DirectorSound::systemBeep() {
_speaker->play(Audio::PCSpeaker::kWaveFormSquare, 500, 150);
}
Audio::SeekableAudioStream *makeSNDStream(Common::SeekableSubReadStreamEndian *stream) {
if (debugChannelSet(5, kDebugLoading)) {
debugC(5, kDebugLoading, "snd header:");
stream->hexdump(0x4e);
}
// unk1
for (uint32 i = 0; i < 0x14; i++) {
stream->readByte();
}
uint16 channels = stream->readUint16();
if (channels != 1 || channels != 2) {
warning("STUB: loadSpriteSounds: no support for old sound format");
return NULL;
}
uint16 rate = stream->readUint16();
// unk2
for (uint32 i = 0; i < 0x06; i++) {
stream->readByte();
}
uint32 length = stream->readUint32();
/*uint16 unk3 =*/stream->readUint16();
/*uint32 length_copy =*/stream->readUint32();
/*uint8 unk4 =*/stream->readByte();
/*uint8 unk5 =*/stream->readByte();
/*uint16 unk6 =*/stream->readUint16();
// unk7
for (uint32 i = 0; i < 0x12; i++) {
stream->readByte();
}
uint16 bits = stream->readUint16();
// unk8
for (uint32 i = 0; i < 0x0c; i++) {
stream->readByte();
}
byte flags = 0;
flags |= channels == 2 ? Audio::FLAG_STEREO : 0;
flags |= bits == 16 ? Audio::FLAG_16BITS : 0;
flags |= bits == 8 ? Audio::FLAG_UNSIGNED : 0;
uint32 size = length * channels * (bits == 16 ? 2 : 1);
byte *data = (byte *)malloc(size);
assert(data);
stream->read(data, size);
return Audio::makeRawStream(data, size, rate, flags);
}
} // End of namespace Director

View File

@ -27,6 +27,7 @@ namespace Audio {
class AudioStream;
class SoundHandle;
class PCSpeaker;
class SeekableAudioStream;
}
namespace Director {
@ -48,11 +49,14 @@ public:
void playWAV(Common::String filename, uint8 channelID);
void playAIFF(Common::String filename, uint8 channelID);
void playMCI(Audio::AudioStream &stream, uint32 from, uint32 to);
void playStream(Audio::AudioStream &stream, uint8 soundChannel);
void systemBeep();
bool isChannelActive(uint8 channelID);
void stopSound();
};
Audio::SeekableAudioStream *makeSNDStream(Common::SeekableSubReadStreamEndian *stream);
} // End of namespace Director
#endif