CINE: Implement music fade out for Amiga/AtariST music.

This commit is contained in:
Johannes Schickel 2012-09-11 22:21:43 +02:00
parent f8e93ea9f7
commit c31d1971b5
2 changed files with 69 additions and 9 deletions

View File

@ -998,21 +998,27 @@ void PCSound::stopSound(int channel) {
}
PaulaSound::PaulaSound(Audio::Mixer *mixer, CineEngine *vm)
: Sound(mixer, vm), _sfxTimer(0) {
: Sound(mixer, vm), _sfxTimer(0), _musicTimer(0), _musicFadeTimer(0) {
_moduleStream = 0;
// The original is using the following timer frequency:
// 0.709379Mhz / 8000 = 88.672375Hz
// 1000000 / 88.672375Hz = 11277.46944863us
g_system->getTimerManager()->installTimerProc(&PaulaSound::sfxTimerProc, 11277, this, "PaulaSound::sfxTimerProc");
// The original is using the following timer frequency:
// 0.709379Mhz / 14565 = 48.704359Hz
// 1000000 / 48.704359Hz = 20532.04313806us
g_system->getTimerManager()->installTimerProc(&PaulaSound::musicTimerProc, 20532, this, "PaulaSound::musicTimerProc");
}
PaulaSound::~PaulaSound() {
Common::StackLock lock(_mutex);
Common::StackLock sfxLock(_sfxMutex);
g_system->getTimerManager()->removeTimerProc(&PaulaSound::sfxTimerProc);
for (int i = 0; i < NUM_CHANNELS; ++i) {
stopSound(i);
}
Common::StackLock musicLock(_musicMutex);
g_system->getTimerManager()->removeTimerProc(&PaulaSound::musicTimerProc);
stopMusic();
}
@ -1022,6 +1028,25 @@ void PaulaSound::loadMusic(const char *name) {
stopSound(i);
}
// Fade music out when there is music playing.
_musicMutex.lock();
if (_mixer->isSoundHandleActive(_moduleHandle)) {
// Only start fade out when it is not in progress.
if (!_musicFadeTimer) {
_musicFadeTimer = 1;
}
_musicMutex.unlock();
while (_musicFadeTimer != 64) {
g_system->delayMillis(50);
}
} else {
_musicMutex.unlock();
}
Common::StackLock lock(_musicMutex);
assert(!_mixer->isSoundHandleActive(_moduleHandle));
if (_vm->getGameType() == GType_FW) {
// look for separate files
Common::File f;
@ -1042,26 +1067,32 @@ void PaulaSound::loadMusic(const char *name) {
void PaulaSound::playMusic() {
debugC(5, kCineDebugSound, "PaulaSound::playMusic()");
Common::StackLock lock(_musicMutex);
_mixer->stopHandle(_moduleHandle);
if (_moduleStream) {
_musicFadeTimer = 0;
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_moduleHandle, _moduleStream);
}
}
void PaulaSound::stopMusic() {
debugC(5, kCineDebugSound, "PaulaSound::stopMusic()");
Common::StackLock lock(_musicMutex);
_mixer->stopHandle(_moduleHandle);
}
void PaulaSound::fadeOutMusic() {
debugC(5, kCineDebugSound, "PaulaSound::fadeOutMusic()");
// TODO
stopMusic();
Common::StackLock lock(_musicMutex);
_musicFadeTimer = 1;
}
void PaulaSound::playSound(int channel, int frequency, const uint8 *data, int size, int volumeStep, int stepCount, int volume, int repeat) {
debugC(5, kCineDebugSound, "PaulaSound::playSound() channel %d size %d", channel, size);
Common::StackLock lock(_mutex);
Common::StackLock lock(_sfxMutex);
assert(frequency > 0);
stopSound(channel);
@ -1090,7 +1121,7 @@ void PaulaSound::playSound(int channel, int frequency, const uint8 *data, int si
void PaulaSound::stopSound(int channel) {
debugC(5, kCineDebugSound, "PaulaSound::stopSound() channel %d", channel);
Common::StackLock lock(_mutex);
Common::StackLock lock(_sfxMutex);
_mixer->stopHandle(_channelsTable[channel].handle);
}
@ -1101,7 +1132,7 @@ void PaulaSound::sfxTimerProc(void *param) {
}
void PaulaSound::sfxTimerCallback() {
Common::StackLock lock(_mutex);
Common::StackLock lock(_sfxMutex);
if (_sfxTimer < 6) {
++_sfxTimer;
@ -1133,6 +1164,30 @@ void PaulaSound::sfxTimerCallback() {
}
}
void PaulaSound::musicTimerProc(void *param) {
PaulaSound *sound = (PaulaSound *)param;
sound->musicTimerCallback();
}
void PaulaSound::musicTimerCallback() {
Common::StackLock lock(_musicMutex);
++_musicTimer;
if (_musicTimer == 6) {
_musicTimer = 0;
if (_musicFadeTimer) {
++_musicFadeTimer;
if (_musicFadeTimer == 64) {
stopMusic();
} else {
if (_mixer->isSoundHandleActive(_moduleHandle)) {
_mixer->setChannelVolume(_moduleHandle, (64 - _musicFadeTimer) * Audio::Mixer::kMaxChannelVolume / 64);
}
}
}
}
}
const int PaulaSound::_channelBalance[NUM_CHANNELS] = {
// L/R/R/L This is according to the Hardware Reference Manual.
// TODO: It seems the order is swapped for some Amiga models:

View File

@ -98,7 +98,6 @@ public:
};
protected:
Common::Mutex _mutex;
struct SfxChannel {
Audio::SoundHandle handle;
@ -115,10 +114,16 @@ protected:
};
SfxChannel _channelsTable[NUM_CHANNELS];
static const int _channelBalance[NUM_CHANNELS];
Common::Mutex _sfxMutex;
int _sfxTimer;
static void sfxTimerProc(void *param);
void sfxTimerCallback();
Common::Mutex _musicMutex;
int _musicTimer;
int _musicFadeTimer;
static void musicTimerProc(void *param);
void musicTimerCallback();
Audio::SoundHandle _moduleHandle;
Audio::AudioStream *_moduleStream;
};