CHEWY: Fix cutscene volume and panning
This commit fixes the initial volume and panning for SFX and music in cutscenes. These were set on the sound handle of the previous SFX or music track played, which would not affect the new sound.
This commit is contained in:
parent
0fe9e930b3
commit
c76d13a34c
8 changed files with 85 additions and 54 deletions
|
@ -607,6 +607,13 @@ void Atdsys::print_aad(int16 scrX, int16 scrY) {
|
|||
if (g_engine->_sound->speechEnabled() &&
|
||||
_aadv._strHeader->_vocNr - ATDS_VOC_OFFSET != -1) {
|
||||
if (_atdsv._vocNr != _aadv._strHeader->_vocNr - ATDS_VOC_OFFSET) {
|
||||
// TODO Panning does not work properly during cutscenes.
|
||||
// The x position seems to be fixed, probably that of the
|
||||
// character in the (now invisible) game screen, so all
|
||||
// cutscene voices are panned to the same position. I don't
|
||||
// know if the x position of the character speaking in the
|
||||
// cutscene is available somehow; otherwise panning must be
|
||||
// disabled (fixed center) during cutscenes.
|
||||
_atdsv._vocNr = _aadv._strHeader->_vocNr - ATDS_VOC_OFFSET;
|
||||
const int16 vocx = _G(moveState)[personId].Xypos[0] -
|
||||
_G(gameState).scrollx + _G(spieler_mi)[personId].HotX;
|
||||
|
|
|
@ -100,12 +100,12 @@ void Options::execute(TafInfo *ti) {
|
|||
8 + ti->correction[(SCHNULL_BAND << 1) + 1], 0);
|
||||
}
|
||||
|
||||
const int soundVolume = MAX(1, g_engine->_sound->getSoundVolume() * 32 / Audio::Mixer::kMaxMixerVolume);
|
||||
const int soundVolume = MAX(1, g_engine->_sound->getUserSoundVolume() * 32 / Audio::Mixer::kMaxMixerVolume);
|
||||
_G(out)->pop_box(32 - 2, 104 - 12, 42 + 4, 136 + 2, 192, 183, 182);
|
||||
_G(out)->printxy(32 + 3, 104 - 10, 15, 300, 0, "S");
|
||||
_G(out)->boxFill(33, 136 - soundVolume, 42, 136, 15);
|
||||
|
||||
const int musicVolume = MAX(1, g_engine->_sound->getMusicVolume() * 32 / Audio::Mixer::kMaxMixerVolume);
|
||||
const int musicVolume = MAX(1, g_engine->_sound->getUserMusicVolume() * 32 / Audio::Mixer::kMaxMixerVolume);
|
||||
_G(out)->pop_box(52 - 2, 104 - 12, 62 + 4, 136 + 2, 192, 183, 182);
|
||||
_G(out)->printxy(52 + 3, 104 - 10, 31, 300, 0, "M");
|
||||
_G(out)->boxFill(53, 136 - musicVolume, 62, 136, 31);
|
||||
|
@ -193,11 +193,11 @@ void Options::execute(TafInfo *ti) {
|
|||
key = Common::KEYCODE_ESCAPE;
|
||||
break;
|
||||
case 7: // S volume gauge
|
||||
g_engine->_sound->setSoundVolume(MIN(32, 136 - g_events->_mousePos.y) * Audio::Mixer::kMaxMixerVolume / 32);
|
||||
g_engine->_sound->setUserSoundVolume(MIN(32, 136 - g_events->_mousePos.y) * Audio::Mixer::kMaxMixerVolume / 32);
|
||||
g_engine->syncSoundSettings();
|
||||
break;
|
||||
case 8: // M volume gauge
|
||||
g_engine->_sound->setMusicVolume(MIN(32, 136 - g_events->_mousePos.y) * Audio::Mixer::kMaxMixerVolume / 32);
|
||||
g_engine->_sound->setUserMusicVolume(MIN(32, 136 - g_events->_mousePos.y) * Audio::Mixer::kMaxMixerVolume / 32);
|
||||
g_engine->syncSoundSettings();
|
||||
break;
|
||||
|
||||
|
|
|
@ -754,9 +754,9 @@ void flic_cut(int16 nr) {
|
|||
break;
|
||||
|
||||
case FCUT_112:
|
||||
g_engine->_sound->setMusicVolume(32 * Audio::Mixer::kMaxChannelVolume / 120);
|
||||
g_engine->_sound->setActiveMusicVolume(32);
|
||||
g_engine->_video->playVideo(nr);
|
||||
g_engine->_sound->setMusicVolume(5 * Audio::Mixer::kMaxChannelVolume / 120);
|
||||
g_engine->_sound->setActiveMusicVolume(5);
|
||||
break;
|
||||
|
||||
case FCUT_133:
|
||||
|
|
|
@ -66,11 +66,8 @@ void Sound::playSound(uint8 *data, uint32 size, uint channel, bool loop, uint16
|
|||
dispose),
|
||||
loop ? 0 : 1);
|
||||
|
||||
assert(volume >= 0 && volume < 64);
|
||||
assert(balance >= 0 && balance < 128);
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream, -1,
|
||||
volume * Audio::Mixer::kMaxChannelVolume / 63, MIN(127, (balance - 63) * 2));
|
||||
convertVolume(volume), convertBalance(balance));
|
||||
}
|
||||
|
||||
void Sound::pauseSound(uint channel) {
|
||||
|
@ -98,37 +95,24 @@ bool Sound::isSoundActive(uint channel) const {
|
|||
return _mixer->isSoundHandleActive(_soundHandle[channel]);
|
||||
}
|
||||
|
||||
void Sound::setSoundVolume(uint volume) {
|
||||
void Sound::setUserSoundVolume(uint volume) {
|
||||
_userSoundVolume = volume;
|
||||
if (soundEnabled())
|
||||
ConfMan.setInt("sfx_volume", volume);
|
||||
}
|
||||
|
||||
int Sound::getSoundVolume() const {
|
||||
int Sound::getUserSoundVolume() const {
|
||||
return _userSoundVolume;
|
||||
}
|
||||
|
||||
void Sound::pushVolume() {
|
||||
/* _soundVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType);
|
||||
_speechVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType);
|
||||
_musicVolume = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);*/
|
||||
}
|
||||
|
||||
void Sound::popVolume() {
|
||||
/* assert(_soundVolume >= 0 && _speechVolume >= 0 && _musicVolume >= 0);
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _soundVolume);
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _speechVolume);
|
||||
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicVolume);*/
|
||||
}
|
||||
|
||||
void Sound::setSoundChannelVolume(uint channel, uint volume) {
|
||||
assert(channel < MAX_SOUND_EFFECTS);
|
||||
_mixer->setChannelVolume(_soundHandle[channel], volume);
|
||||
_mixer->setChannelVolume(_soundHandle[channel], convertVolume(volume));
|
||||
}
|
||||
|
||||
void Sound::setSoundChannelBalance(uint channel, int8 balance) {
|
||||
assert(channel < MAX_SOUND_EFFECTS);
|
||||
_mixer->setChannelBalance(_soundHandle[channel], balance);
|
||||
_mixer->setChannelBalance(_soundHandle[channel], convertBalance(balance));
|
||||
}
|
||||
|
||||
void Sound::playMusic(int16 num, bool loop) {
|
||||
|
@ -142,11 +126,11 @@ void Sound::playMusic(int16 num, bool loop) {
|
|||
delete[] data;
|
||||
}
|
||||
|
||||
void Sound::playMusic(uint8 *data, uint32 size) {
|
||||
void Sound::playMusic(uint8 *data, uint32 size, uint8 volume) {
|
||||
TMFStream *stream = new TMFStream(new Common::MemoryReadStream(data, size), 0);
|
||||
_curMusic = -1;
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream);
|
||||
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream, -1, convertVolume(volume));
|
||||
}
|
||||
|
||||
void Sound::pauseMusic() {
|
||||
|
@ -166,16 +150,21 @@ bool Sound::isMusicActive() const {
|
|||
return _mixer->isSoundHandleActive(_musicHandle);
|
||||
}
|
||||
|
||||
void Sound::setMusicVolume(uint volume) {
|
||||
void Sound::setUserMusicVolume(uint volume) {
|
||||
_userMusicVolume = volume;
|
||||
if (musicEnabled())
|
||||
ConfMan.setInt("music_volume", volume);
|
||||
}
|
||||
|
||||
int Sound::getMusicVolume() const {
|
||||
int Sound::getUserMusicVolume() const {
|
||||
return _userMusicVolume;
|
||||
}
|
||||
|
||||
void Sound::setActiveMusicVolume(uint8 volume) {
|
||||
if (isMusicActive())
|
||||
_mixer->setChannelVolume(_musicHandle, convertVolume(volume));
|
||||
}
|
||||
|
||||
void Sound::playSpeech(int num, bool waitForFinish, uint16 balance) {
|
||||
if (isSpeechActive())
|
||||
stopSpeech();
|
||||
|
@ -194,10 +183,8 @@ void Sound::playSpeech(int num, bool waitForFinish, uint16 balance) {
|
|||
new Common::MemorySeekableReadWriteStream(data, size, DisposeAfterUse::YES),
|
||||
DisposeAfterUse::YES);
|
||||
|
||||
assert(balance >= 0 && balance < 128);
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream,
|
||||
-1 , 255, MIN(127, (balance - 63) * 2));
|
||||
-1, Audio::Mixer::kMaxChannelVolume, convertBalance(balance));
|
||||
|
||||
if (waitForFinish) {
|
||||
// Wait for speech to finish
|
||||
|
@ -237,7 +224,7 @@ void Sound::waitForSpeechToFinish() {
|
|||
|
||||
void Sound::setSpeechBalance(uint16 balance) {
|
||||
if (isSpeechActive()) {
|
||||
_mixer->setChannelBalance(_speechHandle, balance);
|
||||
_mixer->setChannelBalance(_speechHandle, convertBalance(balance));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,4 +333,14 @@ void Sound::playRoomMusic(int16 roomNum) {
|
|||
}
|
||||
}
|
||||
|
||||
uint8 Sound::convertVolume(uint16 volume) {
|
||||
assert(volume >= 0 && volume < 64);
|
||||
return volume * Audio::Mixer::kMaxChannelVolume / 63;
|
||||
}
|
||||
|
||||
int8 Sound::convertBalance(uint16 balance) {
|
||||
assert(balance >= 0 && balance < 128);
|
||||
return MIN(127, (balance - 63) * 2);
|
||||
}
|
||||
|
||||
} // namespace Chewy
|
||||
|
|
|
@ -50,21 +50,26 @@ public:
|
|||
void stopSound(uint channel = 0);
|
||||
void stopAllSounds();
|
||||
bool isSoundActive(uint channel) const;
|
||||
void setSoundVolume(uint volume);
|
||||
int getSoundVolume() const;
|
||||
void setUserSoundVolume(uint volume);
|
||||
int getUserSoundVolume() const;
|
||||
// Sets the volume of the sound effect curently active on the specified
|
||||
// channel. Does not affect the next sound effect played on the channel.
|
||||
void setSoundChannelVolume(uint channel, uint volume);
|
||||
// Sets the balance of the sound effect curently active on the specified
|
||||
// channel. Does not affect the next sound effect played on the channel.
|
||||
void setSoundChannelBalance(uint channel, int8 balance);
|
||||
void pushVolume();
|
||||
void popVolume();
|
||||
|
||||
void playMusic(int16 num, bool loop = false);
|
||||
void playMusic(uint8 *data, uint32 size);
|
||||
void playMusic(uint8 *data, uint32 size, uint8 volume = 63);
|
||||
void pauseMusic();
|
||||
void resumeMusic();
|
||||
void stopMusic();
|
||||
bool isMusicActive() const;
|
||||
void setMusicVolume(uint volume);
|
||||
int getMusicVolume() const;
|
||||
void setUserMusicVolume(uint volume);
|
||||
int getUserMusicVolume() const;
|
||||
// Sets the volume of the currently active music track. Does not affect the
|
||||
// next music track played.
|
||||
void setActiveMusicVolume(uint8 volume);
|
||||
void playRoomMusic(int16 roomNum);
|
||||
|
||||
void playSpeech(int num, bool waitForFinish, uint16 balance = 63);
|
||||
|
@ -72,6 +77,8 @@ public:
|
|||
void resumeSpeech();
|
||||
void stopSpeech();
|
||||
bool isSpeechActive() const;
|
||||
// Sets the balance of the currently playing speech sample. Does not affect
|
||||
// the next speech sample played.
|
||||
void setSpeechBalance(uint16 balance = 63);
|
||||
|
||||
void stopAll();
|
||||
|
@ -96,6 +103,13 @@ public:
|
|||
void syncSoundSettings();
|
||||
|
||||
private:
|
||||
// Converts volume from the scale used by the game data (0 - 63) to the
|
||||
// ScummVM mixer channel scale (0 - 255).
|
||||
uint8 convertVolume(uint16 volume);
|
||||
// Converts balance from the scale used by the game data (0 - 127) to the
|
||||
// ScummVM mixer channel scale (-127 - 127).
|
||||
int8 convertBalance(uint16 balance);
|
||||
|
||||
Audio::Mixer *_mixer;
|
||||
Audio::SoundHandle _soundHandle[MAX_SOUND_EFFECTS];
|
||||
Audio::SoundHandle _musicHandle;
|
||||
|
|
|
@ -83,6 +83,10 @@ CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uin
|
|||
|
||||
_musicData = nullptr;
|
||||
_musicSize = 0;
|
||||
|
||||
Common::fill(_sfxBalances, _sfxBalances + ARRAYSIZE(_sfxBalances), 63);
|
||||
_sfxGlobalVolume = 63;
|
||||
_musicVolume = 63;
|
||||
}
|
||||
|
||||
CfoDecoder::CfoVideoTrack::~CfoVideoTrack() {
|
||||
|
@ -219,7 +223,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
|
|||
break;
|
||||
case kChunkPlayMusic:
|
||||
// Used in videos 0, 18, 34, 71
|
||||
_sound->playMusic(_musicData, _musicSize);
|
||||
_sound->playMusic(_musicData, _musicSize, _musicVolume);
|
||||
break;
|
||||
case kChunkPlaySeq:
|
||||
error("Unused chunk kChunkPlaySeq found");
|
||||
|
@ -246,8 +250,10 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
|
|||
} while (_sound->isMusicActive() && musicLoops < 100);
|
||||
break;
|
||||
case kChunkSetMusicVolume:
|
||||
volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
|
||||
_sound->setMusicVolume(volume);
|
||||
volume = _fileStream->readUint16LE();
|
||||
|
||||
_musicVolume = volume;
|
||||
_sound->setActiveMusicVolume(volume);
|
||||
break;
|
||||
case kChunkSetLoopMode:
|
||||
error("Unused chunk kChunkSetLoopMode found");
|
||||
|
@ -262,18 +268,21 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
|
|||
repeat = _fileStream->readUint16LE();
|
||||
assert(number < MAX_SOUND_EFFECTS);
|
||||
|
||||
//_sound->setSoundVolume(volume);
|
||||
_sound->playSound(_soundEffects[number], _soundEffectSize[number], channel, repeat, volume, 63, DisposeAfterUse::NO);
|
||||
_sound->playSound(_soundEffects[number], _soundEffectSize[number], channel, repeat,
|
||||
volume * _sfxGlobalVolume / 63, _sfxBalances[channel], DisposeAfterUse::NO);
|
||||
break;
|
||||
case kChunkSetSoundVolume:
|
||||
volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
|
||||
_sound->setSoundVolume(volume);
|
||||
volume = _fileStream->readUint16LE();
|
||||
assert(volume >= 0 && volume < 64);
|
||||
_sfxGlobalVolume = volume;
|
||||
// This is only used once in the credits video, before any sounds
|
||||
// are played, so no need to update volume of active sounds.
|
||||
break;
|
||||
case kChunkSetChannelVolume:
|
||||
channel = _fileStream->readUint16LE();
|
||||
volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
|
||||
volume = _fileStream->readUint16LE();
|
||||
|
||||
_sound->setSoundChannelVolume(channel, volume);
|
||||
_sound->setSoundChannelVolume(channel, volume * _sfxGlobalVolume / 63);
|
||||
break;
|
||||
case kChunkFreeSoundEffect:
|
||||
number = _fileStream->readUint16LE();
|
||||
|
@ -293,7 +302,9 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
|
|||
break;
|
||||
case kChunkSetBalance:
|
||||
channel = _fileStream->readUint16LE();
|
||||
balance = (_fileStream->readUint16LE() * 2) - 127;
|
||||
balance = _fileStream->readUint16LE();
|
||||
|
||||
_sfxBalances[channel] = balance;
|
||||
_sound->setSoundChannelBalance(channel, balance);
|
||||
break;
|
||||
case kChunkSetSpeed:
|
||||
|
|
|
@ -62,6 +62,10 @@ private:
|
|||
uint32 _soundEffectSize[MAX_SOUND_EFFECTS];
|
||||
uint8 *_musicData;
|
||||
uint32 _musicSize;
|
||||
|
||||
uint8 _sfxBalances[MAX_SOUND_EFFECTS];
|
||||
uint8 _sfxGlobalVolume;
|
||||
uint8 _musicVolume;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ bool VideoPlayer::playVideo(uint num, bool stopMusic) {
|
|||
CfoDecoder *cfoDecoder = new CfoDecoder(g_engine->_sound);
|
||||
VideoResource *videoResource = new VideoResource("cut.tap");
|
||||
Common::SeekableReadStream *videoStream = videoResource->getVideoStream(num);
|
||||
g_engine->_sound->pushVolume();
|
||||
_playCount = 0;
|
||||
|
||||
if (stopMusic) {
|
||||
|
@ -102,7 +101,6 @@ bool VideoPlayer::playVideo(uint num, bool stopMusic) {
|
|||
|
||||
g_system->getPaletteManager()->setPalette(curPalette, 0, 256);
|
||||
_G(cur)->showCursor();
|
||||
g_engine->_sound->popVolume();
|
||||
|
||||
delete videoResource;
|
||||
delete cfoDecoder;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue