aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/parallaction/sound.h10
-rw-r--r--engines/parallaction/sound_br.cpp58
-rw-r--r--engines/parallaction/sound_ns.cpp41
-rw-r--r--sound/iff.cpp95
-rw-r--r--sound/iff.h27
5 files changed, 113 insertions, 118 deletions
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h
index f0ecea67bb..8a5582b378 100644
--- a/engines/parallaction/sound.h
+++ b/engines/parallaction/sound.h
@@ -154,10 +154,9 @@ class AmigaSoundMan_ns : public SoundMan_ns {
uint32 dataSize;
bool dispose;
Audio::SoundHandle handle;
- uint32 flags;
} _channels[NUM_SFX_CHANNELS];
- void loadChannelData(const char *filename, Channel *ch);
+ Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
AmigaSoundMan_ns(Parallaction_ns *vm);
@@ -202,11 +201,8 @@ protected:
uint32 dataSize;
bool dispose;
Audio::SoundHandle handle;
- uint32 flags;
} _channels[NUM_SFX_CHANNELS];
- virtual void loadChannelData(const char *filename, Channel *ch) = 0;
-
public:
SoundMan_br(Parallaction_br *vm);
~SoundMan_br();
@@ -228,7 +224,7 @@ class DosSoundMan_br : public SoundMan_br {
MidiPlayer_MSC *_midiPlayer;
- void loadChannelData(const char *filename, Channel *ch);
+ Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver);
@@ -246,7 +242,7 @@ class AmigaSoundMan_br : public SoundMan_br {
Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle;
- void loadChannelData(const char *filename, Channel *ch);
+ Audio::AudioStream *loadChannelData(const char *filename, Channel *ch, bool looping);
public:
AmigaSoundMan_br(Parallaction_br *vm);
diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp
index 4915eb41e2..464201b2d6 100644
--- a/engines/parallaction/sound_br.cpp
+++ b/engines/parallaction/sound_br.cpp
@@ -401,7 +401,7 @@ DosSoundMan_br::~DosSoundMan_br() {
delete _midiPlayer;
}
-void DosSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
+Audio::AudioStream *DosSoundMan_br::loadChannelData(const char *filename, Channel *ch, bool looping) {
Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
ch->dataSize = stream->size();
@@ -414,6 +414,15 @@ void DosSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
// TODO: Confirm sound rate
ch->header.samplesPerSec = 11025;
+
+ uint32 loopStart = 0, loopEnd = 0, flags = Audio::Mixer::FLAG_UNSIGNED;
+ if (looping) {
+ loopEnd = ch->dataSize;
+ flags |= Audio::Mixer::FLAG_LOOP;
+ }
+
+ // Create the input stream
+ return Audio::makeLinearInputStream((byte *)ch->data, ch->dataSize, ch->header.samplesPerSec, flags, loopStart, loopEnd);
}
void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) {
@@ -426,16 +435,8 @@ void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, i
debugC(1, kDebugAudio, "DosSoundMan_br::playSfx(%s, %u, %i, %i)", filename, channel, looping, volume);
Channel *ch = &_channels[channel];
- loadChannelData(filename, ch);
-
- uint32 loopStart = 0, loopEnd = 0, flags = Audio::Mixer::FLAG_UNSIGNED;
- if (looping) {
- loopEnd = ch->dataSize;
- flags |= Audio::Mixer::FLAG_LOOP;
- }
-
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
- ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
+ Audio::AudioStream *input = loadChannelData(filename, ch, looping);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume);
}
void DosSoundMan_br::playMusic() {
@@ -468,8 +469,10 @@ AmigaSoundMan_br::~AmigaSoundMan_br() {
stopMusic();
}
-void AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
+Audio::AudioStream *AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch, bool looping) {
Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
+ Audio::AudioStream *input = 0;
+
if (_vm->getFeatures() & GF_DEMO) {
ch->dataSize = stream->size();
ch->data = (int8*)malloc(ch->dataSize);
@@ -478,12 +481,20 @@ void AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
// TODO: Confirm sound rate
ch->header.samplesPerSec = 11025;
+
+ uint32 loopStart = 0, loopEnd = 0, flags = 0;
+ if (looping) {
+ loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
+ flags = Audio::Mixer::FLAG_LOOP;
+ }
+
+ input = Audio::makeLinearInputStream((byte *)ch->data, ch->dataSize, ch->header.samplesPerSec, flags, loopStart, loopEnd);
} else {
- Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize);
- decoder.decode();
+ input = Audio::make8SVXStream(*stream, looping);
+ delete stream;
}
- ch->dispose = true;
- delete stream;
+
+ return input;
}
void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) {
@@ -501,24 +512,13 @@ void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping,
debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel);
Channel *ch = &_channels[channel];
- loadChannelData(filename, ch);
-
- uint32 loopStart = 0, loopEnd = 0, flags = 0;
- if (looping) {
- // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
- // repeatHiSamples fields, but Nippon Safes handles loops according to flags
- // set in its location scripts and always operates on the whole data.
- loopStart = 0;
- loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
- flags = Audio::Mixer::FLAG_LOOP;
- }
+ Audio::AudioStream *input = loadChannelData(filename, ch, looping);
if (volume == -1) {
volume = ch->header.volume;
}
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
- ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume);
}
void AmigaSoundMan_br::playMusic() {
diff --git a/engines/parallaction/sound_ns.cpp b/engines/parallaction/sound_ns.cpp
index d0688c7264..b5ce54c78d 100644
--- a/engines/parallaction/sound_ns.cpp
+++ b/engines/parallaction/sound_ns.cpp
@@ -360,8 +360,9 @@ static int8 res_amigaBeep[AMIGABEEP_SIZE] = {
0, 20, 40, 60, 80, 60, 40, 20, 0, -20, -40, -60, -80, -60, -40, -20
};
+Audio::AudioStream *AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch, bool looping) {
+ Audio::AudioStream *input = 0;
-void AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch) {
if (!scumm_stricmp("beep", filename)) {
ch->header.oneShotHiSamples = 0;
ch->header.repeatHiSamples = 0;
@@ -376,14 +377,22 @@ void AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch) {
}
ch->dataSize = AMIGABEEP_SIZE * NUM_REPEATS;
ch->dispose = true;
- return;
+
+ uint32 loopStart = 0, loopEnd = 0, flags = 0;
+ if (looping) {
+ loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
+ flags = Audio::Mixer::FLAG_LOOP;
+ }
+
+ input = Audio::makeLinearInputStream((byte *)ch->data, ch->dataSize, ch->header.samplesPerSec, flags, loopStart, loopEnd);
+ } else {
+ Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
+ input = Audio::make8SVXStream(*stream, looping);
+ ch->dispose = true;
+ delete stream;
}
- Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
- Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize);
- decoder.decode();
- ch->dispose = true;
- delete stream;
+ return input;
}
void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping, int volume) {
@@ -397,27 +406,13 @@ void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping,
debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel);
Channel *ch = &_channels[channel];
- loadChannelData(filename, ch);
-
- uint32 loopStart, loopEnd, flags;
- if (looping) {
- // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
- // repeatHiSamples fields, but Nippon Safes handles loops according to flags
- // set in its location scripts and always operates on the whole data.
- loopStart = 0;
- loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
- flags = Audio::Mixer::FLAG_LOOP;
- } else {
- loopStart = loopEnd = 0;
- flags = 0;
- }
+ Audio::AudioStream *input = loadChannelData(filename, ch, looping);
if (volume == -1) {
volume = ch->header.volume;
}
- _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
- ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
+ _mixer->playInputStream(Audio::Mixer::kSFXSoundType, &ch->handle, input, -1, volume);
}
void AmigaSoundMan_ns::stopSfx(uint channel) {
diff --git a/sound/iff.cpp b/sound/iff.cpp
index de380276bb..bf3318d80e 100644
--- a/sound/iff.cpp
+++ b/sound/iff.cpp
@@ -26,58 +26,83 @@
#include "sound/iff.h"
#include "sound/audiostream.h"
#include "sound/mixer.h"
+#include "common/func.h"
namespace Audio {
-
-void A8SVXDecoder::readVHDR(Common::IFFChunk &chunk) {
- _header.oneShotHiSamples = chunk.readUint32BE();
- _header.repeatHiSamples = chunk.readUint32BE();
- _header.samplesPerHiCycle = chunk.readUint32BE();
- _header.samplesPerSec = chunk.readUint16BE();
- _header.octaves = chunk.readByte();
- _header.compression = chunk.readByte();
- _header.volume = chunk.readUint32BE();
+void Voice8Header::load(Common::ReadStream &stream) {
+ stream.read(this, sizeof(Voice8Header));
+ oneShotHiSamples = FROM_BE_32(oneShotHiSamples);
+ repeatHiSamples = FROM_BE_32(repeatHiSamples);
+ samplesPerHiCycle = FROM_BE_32(samplesPerHiCycle);
+ samplesPerSec = FROM_BE_16(samplesPerSec);
+ volume = FROM_BE_32(volume);
}
-void A8SVXDecoder::readBODY(Common::IFFChunk &chunk) {
-
- switch (_header.compression) {
- case 0:
- _dataSize = chunk.size;
- _data = (int8*)malloc(_dataSize);
- chunk.read(_data, _dataSize);
- break;
- case 1:
- warning("compressed IFF audio is not supported");
- break;
- }
-}
+struct A8SVXLoader {
+ Voice8Header _header;
+ int8 *_data;
+ uint32 _dataSize;
+ void load(Common::ReadStream &input) {
+ Common::IFFParser parser(input);
+ Common::IFFChunk *chunk;
+ while (chunk = parser.nextChunk()) {
+ callback(*chunk);
+ }
+ }
-A8SVXDecoder::A8SVXDecoder(Common::ReadStream &input, Voice8Header &header, int8 *&data, uint32 &dataSize) :
- IFFParser(input), _header(header), _data(data), _dataSize(dataSize) {
- if (_typeId != ID_8SVX)
- error("unknown audio format");
-}
+ bool callback(Common::IFFChunk &chunk) {
+ switch (chunk.id) {
+ case ID_VHDR:
+ _header.load(chunk);
+ break;
-void A8SVXDecoder::decode() {
+ case ID_BODY:
+ _dataSize = chunk.size;
+ _data = (int8*)malloc(_dataSize);
+ assert(_data);
+ loadData(&chunk);
+ return true;
+ }
- Common::IFFChunk *chunk;
+ return false;
+ }
- while ((chunk = nextChunk()) != 0) {
- switch (chunk->id) {
- case ID_VHDR:
- readVHDR(*chunk);
+ void loadData(Common::ReadStream *stream) {
+ switch (_header.compression) {
+ case 0:
+ stream->read(_data, _dataSize);
break;
- case ID_BODY:
- readBODY(*chunk);
+ case 1:
+ // implement other formats here
+ error("compressed IFF audio is not supported");
break;
}
+
+ }
+};
+
+
+AudioStream *make8SVXStream(Common::ReadStream &input, bool loop) {
+ A8SVXLoader loader;
+ loader.load(input);
+
+ uint32 loopStart = 0, loopEnd = 0, flags = 0;
+ if (loop) {
+ // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
+ // repeatHiSamples fields
+ loopStart = 0;
+ loopEnd = loader._header.oneShotHiSamples + loader._header.repeatHiSamples;
+ flags |= Audio::Mixer::FLAG_LOOP;
}
+
+ flags |= Audio::Mixer::FLAG_AUTOFREE;
+
+ return Audio::makeLinearInputStream((byte *)loader._data, loader._dataSize, loader._header.samplesPerSec, flags, loopStart, loopEnd);
}
}
diff --git a/sound/iff.h b/sound/iff.h
index 2bc8b51b82..82106cb75e 100644
--- a/sound/iff.h
+++ b/sound/iff.h
@@ -32,6 +32,7 @@
#define SOUND_IFF_H
#include "common/iff_container.h"
+#include "sound/audiostream.h"
namespace Audio {
@@ -47,34 +48,12 @@ struct Voice8Header {
Voice8Header() {
memset(this, 0, sizeof(Voice8Header));
}
-};
-
-
-/*
- A8SVX decoder reads 8SVX subtype of IFF files.
-
- TODO: make a factory function for this kind of stream?
- */
-class A8SVXDecoder : public Common::IFFParser {
-
-protected:
- Voice8Header &_header;
- int8* &_data;
- uint32 &_dataSize;
-protected:
- void readVHDR(Common::IFFChunk &chunk);
- void readBODY(Common::IFFChunk &chunk);
-
-public:
- A8SVXDecoder(Common::ReadStream &input, Voice8Header &header, int8 *&data, uint32 &dataSize);
- void decode();
+ void load(Common::ReadStream &stream);
};
+AudioStream *make8SVXStream(Common::ReadStream &stream, bool loop);
-/*
- TODO: Implement a parser for AIFF subtype.
- */
}