aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/sound
diff options
context:
space:
mode:
authorathrxx2019-03-20 21:36:44 +0100
committerathrxx2019-04-13 18:54:58 +0200
commitb80927992807ce9b9ce69920f86d7f2e7f7b45be (patch)
tree833637a9185dca3a62eec78867b38b31b3a6a275 /engines/kyra/sound
parent8c92e045ce59f456be5b2a3f51b558f9abc9d472 (diff)
downloadscummvm-rg350-b80927992807ce9b9ce69920f86d7f2e7f7b45be.tar.gz
scummvm-rg350-b80927992807ce9b9ce69920f86d7f2e7f7b45be.tar.bz2
scummvm-rg350-b80927992807ce9b9ce69920f86d7f2e7f7b45be.zip
KYRA: (EOB2/Amiga) - update sound driver
- add fade out method - some renaming - turn a warning into a debug message
Diffstat (limited to 'engines/kyra/sound')
-rw-r--r--engines/kyra/sound/drivers/audiomaster2.cpp147
-rw-r--r--engines/kyra/sound/drivers/audiomaster2.h5
-rw-r--r--engines/kyra/sound/sound.h1
-rw-r--r--engines/kyra/sound/sound_amiga_eob.cpp43
-rw-r--r--engines/kyra/sound/sound_intern.h4
5 files changed, 158 insertions, 42 deletions
diff --git a/engines/kyra/sound/drivers/audiomaster2.cpp b/engines/kyra/sound/drivers/audiomaster2.cpp
index d050a6101f..dbc6f30424 100644
--- a/engines/kyra/sound/drivers/audiomaster2.cpp
+++ b/engines/kyra/sound/drivers/audiomaster2.cpp
@@ -39,8 +39,8 @@ public:
~AudioMaster2IOManager();
struct IOUnit {
- IOUnit() : _next(0), _sampleData(0), _sampleDataRepeat(0), _lenOnce(0), _lenRepeat(0), _startTick(0), _endTick(0), _transposeData(0), _rate(0), _period(0), _transposePara(0), _transposeCounter(0),
- _levelAdjustData(0), _volumeSetting(0), _outputVolume(0), _levelAdjustPara(0), _levelAdjustCounter(0), _flags(0) {}
+ IOUnit() : _next(0), _sampleData(0), _sampleDataRepeat(0), _lenOnce(0), _lenRepeat(0), _startTick(0), _endTick(0), _transposeData(0), _rate(0), _period(0), _transposePara(0), _transposeDuration(0),
+ _levelAdjustData(0), _volumeSetting(0), _outputVolume(0), _levelAdjustPara(0), _levelAdjustDuration(0), _fadeOutState(-1), _flags(0) {}
IOUnit *_next;
const int8 *_sampleData;
@@ -53,18 +53,22 @@ public:
uint16 _rate;
uint16 _period;
uint16 _transposePara;
- uint8 _transposeCounter;
+ uint8 _transposeDuration;
const uint8 *_levelAdjustData;
uint16 _volumeSetting;
uint16 _outputVolume;
int16 _levelAdjustPara;
- uint8 _levelAdjustCounter;
+ uint8 _levelAdjustDuration;
+ int16 _fadeOutState;
uint8 _flags;
};
void clearChain();
void deployChannels(IOUnit **dest);
IOUnit *requestFreeUnit();
+
+ void fadeOut();
+ bool isFading();
uint32 _sync;
uint32 _tempo;
@@ -93,11 +97,17 @@ public:
void flushResource(const Common::String &name);
void flushAllResources();
+ void fadeOut(int delay);
+ bool isFading();
+
void setMusicVolume(int volume);
void setSoundEffectVolume(int volume);
void interrupt();
+ void resetCounter();
+ int getPlayDuration();
+
void sync(SoundResource *res);
void stopChannels();
@@ -105,11 +115,13 @@ private:
void updateDevice();
AudioMaster2IOManager::IOUnit *_channels[4];
-
AudioMaster2IOManager *_io;
AudioMaster2ResourceManager *_res;
Audio::Mixer *_mixer;
+ uint32 _durationCounter;
+ uint8 _fadeOutSteps;
+
static AudioMaster2Internal *_refInstance;
static int _refCount;
@@ -138,6 +150,7 @@ public:
virtual void interrupt(AudioMaster2IOManager *io);
virtual void setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume) {}
+ virtual void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 tempo) {}
enum Mode {
kIdle = 0,
@@ -156,7 +169,6 @@ protected:
private:
virtual void release() = 0;
virtual void setupEnvelopes(AudioMaster2IOManager::IOUnit *unit) {}
- virtual void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 tempo) {}
int _refCnt;
bool _playing;
@@ -204,6 +216,7 @@ public:
void loadVolumeData(Common::ReadStream *stream, uint32 size);
void setupMusicNote(AudioMaster2IOManager::IOUnit *unit, uint8 note, uint16 volume);
+ void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 rate);
struct EnvelopeData {
EnvelopeData(const uint8 *data, uint32 size) : volume(0x40), _data(data), _dataSize(size) {}
@@ -217,11 +230,10 @@ private:
void release();
void setupEnvelopes(AudioMaster2IOManager::IOUnit *unit);
- void setupSoundEffect(AudioMaster2IOManager::IOUnit *unit, uint32 sync, uint32 rate);
EnvelopeData *_transpose;
EnvelopeData *_levelAdjust;
- SoundResource8SVX *_samplesResource;
+ SoundResource *_samplesResource;
};
class SoundResourceSMUS : public SoundResource {
@@ -288,6 +300,7 @@ public:
void initResource(SoundResource *resource);
void releaseResource(const Common::String &resName);
+ void stopChain();
void flush();
SoundResource *getResource(const Common::String &resName, SoundResource::Mode mode);
@@ -299,7 +312,6 @@ public:
private:
SoundResource *retrieveFromChain(const Common::String &resName);
void linkToChain(SoundResource *resource, SoundResource::Mode mode);
- void stopChain();
SoundResource *_chainPlaying;
SoundResource *_chainInactive;
@@ -413,13 +425,32 @@ AudioMaster2IOManager::IOUnit *AudioMaster2IOManager::requestFreeUnit() {
return 0;
}
+void AudioMaster2IOManager::fadeOut() {
+ for (int i = 0; i < 8; ++i) {
+ if (_units[i]->_flags & 2)
+ _units[i]->_fadeOutState = 0;
+ }
+}
+
+bool AudioMaster2IOManager::isFading() {
+ for (int i = 0; i < 8; ++i) {
+ if (_units[i]->_flags & 2) {
+ if (_units[i]->_fadeOutState > -1)
+ return true;
+ } else {
+ _units[i]->_fadeOutState = -1;
+ }
+ }
+ return false;
+}
+
void SoundResource::loadName(Common::ReadStream *stream, uint32 size) {
char *data = new char[size + 1];
stream->read(data, size);
data[size] = '\0';
_name = data;
-
+
delete[] data;
}
@@ -618,12 +649,13 @@ void SoundResourceINST::loadSamples(Common::ReadStream *stream, uint32 size) {
SoundResource *instr = _res->getResource(data, SoundResource::kIdle);
if (instr) {
int type = instr->getType();
- if (type != 4)
+ if (type == 1)
error("SoundResourceINST::loadInstrument(): Unexpected resource type");
instr->open();
- _samplesResource = (SoundResource8SVX*)instr;
+ _samplesResource = instr;
} else {
- warning("SoundResourceINST::loadInstrument(): Samples resource '%s' not found for '%s'.", data, _name.c_str());
+ // This will come up quite often in EOB II. But never with intruments that are actually used. No need to bother the user with a warning here.
+ debugC(9, kDebugLevelSound, "SoundResourceINST::loadInstrument(): Samples resource '%s' not found for '%s'.", data, _name.c_str());
}
delete[] data;
@@ -650,7 +682,7 @@ void SoundResourceINST::setupEnvelopes(AudioMaster2IOManager::IOUnit *unit) {
assert(unit);
if (_transpose) {
unit->_transposeData = _transpose->_data;
- unit->_transposeCounter = 0;
+ unit->_transposeDuration = 0;
unit->_transposePara = 0;
} else {
unit->_transposeData = 0;
@@ -658,7 +690,7 @@ void SoundResourceINST::setupEnvelopes(AudioMaster2IOManager::IOUnit *unit) {
if (_levelAdjust) {
unit->_levelAdjustData = _levelAdjust->_data;
- unit->_levelAdjustCounter = 0;
+ unit->_levelAdjustDuration = 0;
unit->_levelAdjustPara = 0;
} else {
unit->_levelAdjustData = 0;
@@ -877,6 +909,18 @@ void AudioMaster2ResourceManager::releaseResource(const Common::String &resName)
res->close();
}
+void AudioMaster2ResourceManager::stopChain() {
+ Common::StackLock lock(*_mutex);
+
+ SoundResource *cur = _chainPlaying;
+ while (cur) {
+ cur->setPlayStatus(false);
+ cur = cur->_next;
+ }
+
+ _driver->stopChannels();
+}
+
void AudioMaster2ResourceManager::flush() {
stopChain();
@@ -905,6 +949,11 @@ SoundResource *AudioMaster2ResourceManager::getResource(const Common::String &re
if (!res)
return 0;
+ if (mode == SoundResource::kIdle)
+ res->setPlayStatus(false);
+ else if (res->getType() == 1)
+ _driver->resetCounter();
+
linkToChain(res, mode);
return res;
@@ -1023,18 +1072,6 @@ void AudioMaster2ResourceManager::linkToChain(SoundResource *resource, SoundReso
}
}
-void AudioMaster2ResourceManager::stopChain() {
- Common::StackLock lock(*_mutex);
-
- SoundResource *cur = _chainPlaying;
- while (cur) {
- cur->setPlayStatus(false);
- cur = cur->_next;
- }
-
- _driver->stopChannels();
-}
-
AudioMaster2IFFLoader::~AudioMaster2IFFLoader() {
initResource();
}
@@ -1122,8 +1159,9 @@ void AudioMaster2IFFLoader::initResource() {
AudioMaster2Internal *AudioMaster2Internal::_refInstance = 0;
int AudioMaster2Internal::_refCount = 0;
-AudioMaster2Internal::AudioMaster2Internal(Audio::Mixer *mixer) : Paula(true, mixer->getOutputRate(), mixer->getOutputRate() / 50), _mixer(mixer), _res(0), _ready(false) {
+AudioMaster2Internal::AudioMaster2Internal(Audio::Mixer *mixer) : Paula(true, mixer->getOutputRate(), mixer->getOutputRate() / 50), _mixer(mixer), _res(0), _fadeOutSteps(0), _durationCounter(0), _ready(false) {
_channels[0] = _channels[1] = _channels[2] = _channels[3] = 0;
+ setAudioFilter(true);
}
AudioMaster2Internal::~AudioMaster2Internal() {
@@ -1204,6 +1242,18 @@ void AudioMaster2Internal::flushAllResources() {
_res->flush();
}
+void AudioMaster2Internal::fadeOut(int delay) {
+ if (!_ready)
+ return;
+
+ _fadeOutSteps = delay >> 3;
+ _io->fadeOut();
+}
+
+bool AudioMaster2Internal::isFading() {
+ return _io->isFading();
+}
+
void AudioMaster2Internal::setMusicVolume(int volume) {
if (_ready)
_res->setMasterVolume(1, volume);
@@ -1218,12 +1268,21 @@ void AudioMaster2Internal::interrupt() {
if (!_ready)
return;
+ _durationCounter++;
_io->_sync += _io->_tempo;
_res->interrupt(_io);
_io->deployChannels(_channels);
updateDevice();
}
+void AudioMaster2Internal::resetCounter() {
+ _durationCounter = 0;
+}
+
+int AudioMaster2Internal::getPlayDuration() {
+ return _durationCounter;
+}
+
void AudioMaster2Internal::sync(SoundResource *res) {
if (!_ready || !res)
return;
@@ -1273,7 +1332,7 @@ void AudioMaster2Internal::updateDevice() {
unit->_period += unit->_transposePara;
const uint8 *data = unit->_transposeData;
- if (unit->_transposeCounter-- <= 1) {
+ if (unit->_transposeDuration-- <= 1) {
for (bool loop = true; loop; ) {
uint8 para = *data++;
@@ -1301,7 +1360,7 @@ void AudioMaster2Internal::updateDevice() {
data -= ((para + 1) << 1);
} else {
- unit->_transposeCounter = para;
+ unit->_transposeDuration = para;
unit->_transposePara = *data++;
unit->_transposeData = data;
loop = false;
@@ -1319,7 +1378,7 @@ void AudioMaster2Internal::updateDevice() {
unit->_outputVolume += unit->_levelAdjustPara;
const uint8 *data = unit->_levelAdjustData;
- if (unit->_levelAdjustCounter-- <= 1) {
+ if (unit->_levelAdjustDuration-- <= 1) {
for (bool loop = true; loop; ) {
uint8 para = *data++;
if (para == 0xFF) {
@@ -1358,14 +1417,13 @@ void AudioMaster2Internal::updateDevice() {
continue;
}
- unit->_levelAdjustCounter = para;
+ unit->_levelAdjustDuration = para;
if (para == 1) {
unit->_outputVolume = para2;
unit->_levelAdjustPara = 0;
} else {
int16 va = para2 - unit->_outputVolume;
- va /= para;
unit->_levelAdjustPara = va / para;
}
@@ -1396,6 +1454,17 @@ void AudioMaster2Internal::updateDevice() {
setChannelPeriod(i, unit->_period);
setChannelVolume(i, unit->_outputVolume >> 8);
}
+
+ if (unit->_fadeOutState > -1) {
+ setChannelVolume(i, ((unit->_outputVolume / _fadeOutSteps) * (_fadeOutSteps - unit->_fadeOutState)) >> 8);
+ if (++unit->_fadeOutState > _fadeOutSteps)
+ unit->_fadeOutState = -1;
+ }
+ }
+
+ if (_fadeOutSteps && !_io->isFading()) {
+ _fadeOutSteps = 0;
+ _res->stopChain();
}
}
@@ -1432,6 +1501,18 @@ void AudioMaster2::flushAllResources() {
_am2i->flushAllResources();
}
+void AudioMaster2::fadeOut(int delay) {
+ _am2i->fadeOut(delay);
+}
+
+bool AudioMaster2::isFading() {
+ return _am2i->isFading();
+}
+
+int AudioMaster2::getPlayDuration() {
+ return _am2i->getPlayDuration();
+}
+
void AudioMaster2::setMusicVolume(int volume) {
_am2i->setMusicVolume(volume);
}
diff --git a/engines/kyra/sound/drivers/audiomaster2.h b/engines/kyra/sound/drivers/audiomaster2.h
index b9a3824ba0..0ac21d23ba 100644
--- a/engines/kyra/sound/drivers/audiomaster2.h
+++ b/engines/kyra/sound/drivers/audiomaster2.h
@@ -66,6 +66,11 @@ public:
void flushResource(const Common::String &name);
void flushAllResources();
+ void fadeOut(int delay);
+ bool isFading();
+
+ int getPlayDuration();
+
void setMusicVolume(int volume);
void setSoundEffectVolume(int volume);
diff --git a/engines/kyra/sound/sound.h b/engines/kyra/sound/sound.h
index abeb6050bc..871263cf65 100644
--- a/engines/kyra/sound/sound.h
+++ b/engines/kyra/sound/sound.h
@@ -207,6 +207,7 @@ public:
* playing a new track or sound effect.
*/
virtual void beginFadeOut() = 0;
+ virtual void beginFadeOut(int) { beginFadeOut(); }
/**
* Stops all audio playback when paused. Continues after end of pause.
diff --git a/engines/kyra/sound/sound_amiga_eob.cpp b/engines/kyra/sound/sound_amiga_eob.cpp
index eccf380a69..444c85995c 100644
--- a/engines/kyra/sound/sound_amiga_eob.cpp
+++ b/engines/kyra/sound/sound_amiga_eob.cpp
@@ -104,20 +104,25 @@ void SoundAmiga_EoB::loadSoundFile(Common::String file) {
if (!in)
return;
+ // This value can deviate up to 5 bytes from the real size in EOB II Amiga.
+ // The original simply tries to read 64000 bytes from the file (ignoring this
+ // value). We do the same.
+ // EOB I strangely always seems to have correct values.
uint16 readSize = in->readUint16LE() - 10;
uint8 cmp = in->readByte();
in->seek(1, SEEK_CUR);
uint32 outSize = in->readUint32LE();
in->seek(2, SEEK_CUR);
- if (in->read(_fileBuffer, readSize) != readSize)
- error("SoundAmiga_EoB::loadSoundFile(): Failed to load sound file '%s'", file.c_str());
+ readSize = in->read(_fileBuffer, 64000);
delete in;
+ if (cmp == 0 && readSize < outSize)
+ outSize = readSize;
+
uint8 *buf = new uint8[outSize];
if (cmp == 0) {
- assert(readSize == outSize);
memcpy(buf, _fileBuffer, outSize);
} else if (cmp == 3) {
Screen::decodeFrame3(_fileBuffer, buf, outSize, true);
@@ -135,7 +140,7 @@ void SoundAmiga_EoB::loadSoundFile(Common::String file) {
}
void SoundAmiga_EoB::playTrack(uint8 track) {
- if (!_musicEnabled)
+ if (!_musicEnabled || !_ready)
return;
Common::String newSound;
@@ -149,7 +154,17 @@ void SoundAmiga_EoB::playTrack(uint8 track) {
newSound = "FINALE.SMUS";
}
} else if (_vm->game() == GI_EOB2) {
-
+ if (_currentResourceSet == kMusicIntro) {
+ if (track > 11 && track < 16) {
+ const char *const songs[] = { "INTRO1A.SMUS", "CHARGEN3.SMUS", "INTRO1B.SMUS", "INTRO1C.SMUS" };
+ newSound = songs[track - 12];
+ }
+ } else if (_currentResourceSet == kMusicFinale) {
+ if (track > 0 && track < 4) {
+ const char *const songs[] = { "FINALE1B.SMUS", "FINALE1C.SMUS", "FINALE1D.SMUS" };
+ newSound = songs[track - 1];
+ }
+ }
}
if (!newSound.empty() && _ready) {
@@ -161,11 +176,17 @@ void SoundAmiga_EoB::playTrack(uint8 track) {
void SoundAmiga_EoB::haltTrack() {
if (!_lastSound.empty())
_driver->stopSound(_lastSound);
+ _lastSound.clear();
}
void SoundAmiga_EoB::playSoundEffect(uint8 track, uint8 volume) {
- if (_currentResourceSet == -1 || !_ready)
+ if (_currentResourceSet == -1 || !_sfxEnabled || !_ready)
+ return;
+
+ if (_vm->game() == GI_EOB2 && _currentResourceSet == kMusicIntro && track == 14) {
+ _driver->startSound("TELEPORT.SAM");
return;
+ }
if (!_resInfo[_currentResourceSet]->soundList || track >= 120 || !_sfxEnabled)
return;
@@ -191,8 +212,10 @@ void SoundAmiga_EoB::playSoundEffect(uint8 track, uint8 volume) {
}
}
-void SoundAmiga_EoB::beginFadeOut() {
- haltTrack();
+void SoundAmiga_EoB::beginFadeOut(int delay) {
+ _driver->fadeOut(delay);
+ while (_driver->isFading() && !_vm->shouldQuit())
+ _vm->delay(5);
}
void SoundAmiga_EoB::updateVolumeSettings() {
@@ -207,6 +230,10 @@ void SoundAmiga_EoB::updateVolumeSettings() {
_driver->setSoundEffectVolume((mute ? 0 : ConfMan.getInt("sfx_volume")));
}
+int SoundAmiga_EoB::checkTrigger() {
+ return _driver->getPlayDuration();
+}
+
void SoundAmiga_EoB::unloadLevelSounds() {
if (_currentFile != -1) {
_driver->flushResource(Common::String::format("L%dM1A1", _currentFile));
diff --git a/engines/kyra/sound/sound_intern.h b/engines/kyra/sound/sound_intern.h
index b6e28dad17..fbf19d742e 100644
--- a/engines/kyra/sound/sound_intern.h
+++ b/engines/kyra/sound/sound_intern.h
@@ -422,8 +422,10 @@ public:
void playTrack(uint8 track);
void haltTrack();
void playSoundEffect(uint8 track, uint8 volume = 0xFF);
- void beginFadeOut();
+ void beginFadeOut() { beginFadeOut(160); }
+ void beginFadeOut(int delay);
void updateVolumeSettings();
+ int checkTrigger();
private:
void unloadLevelSounds();