scummvm/engines/bladerunner/ambient_sounds.cpp
2016-10-24 19:40:18 +02:00

217 lines
5.5 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "bladerunner/ambient_sounds.h"
#include "bladerunner/audio_player.h"
#include "bladerunner/bladerunner.h"
#include "bladerunner/gameinfo.h"
#include "common/debug.h"
#include "common/system.h"
namespace BladeRunner {
#define NON_LOOPING_SOUNDS 25
#define LOOPING_SOUNDS 3
AmbientSounds::AmbientSounds(BladeRunnerEngine *vm) : _vm(vm) {
_nonLoopingSounds = new NonLoopingSound[NON_LOOPING_SOUNDS];
_loopingSounds = new LoopingSound[LOOPING_SOUNDS];
_ambientVolume = 65;
for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
NonLoopingSound &track = _nonLoopingSounds[i];
track.isActive = false;
}
for (int i = 0; i != LOOPING_SOUNDS; ++i) {
LoopingSound &track = _loopingSounds[i];
track.isActive = false;
}
}
AmbientSounds::~AmbientSounds() {
delete[] _nonLoopingSounds;
delete[] _loopingSounds;
}
static inline void sort(int &a, int &b) {
if (a > b) {
int t = a;
a = b;
b = t;
}
}
void AmbientSounds::addSound(
int id,
int timeRangeBegin, int timeRangeEnd,
int volumeRangeBegin, int volumeRangeEnd,
int unk1RangeBegin, int unk1RangeEnd,
int unk2RangeBegin, int unk2RangeEnd,
int priority, int unk3) {
const char *name = _vm->_gameInfo->getSfxTrack(id);
sort(volumeRangeBegin, volumeRangeEnd);
sort(unk1RangeBegin, unk1RangeEnd);
sort(unk2RangeBegin, unk2RangeEnd);
addSoundByName(
name,
timeRangeBegin, timeRangeEnd,
volumeRangeBegin, volumeRangeEnd,
unk1RangeBegin, unk1RangeEnd,
unk2RangeBegin, unk2RangeEnd,
priority, unk3
);
}
void AmbientSounds::addLoopingSound(int sfx_id, int volume, int unk, int fadeInTime) {
const char *name = _vm->_gameInfo->getSfxTrack(sfx_id);
int32 hash = mix_id(name);
if (findLoopingTrackByHash(hash) >= 0)
return;
int i = findAvailableLoopingTrack();
if (i == -1)
return;
int actualVolume = volume * _ambientVolume / 100;
int balance = 0;
_vm->_audioPlayer->playAud(name, actualVolume, balance, balance, 100, AudioPlayer::LOOP | AudioPlayer::OVERRIDE_VOLUME);
}
void AmbientSounds::tick() {
uint32 now = g_system->getMillis();
for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
NonLoopingSound &track = _nonLoopingSounds[i];
if (!track.isActive || track.nextPlayTime > now)
continue;
int pan1, pan2;
pan1 = _vm->_rnd.getRandomNumberRng(track.pan1begin, track.pan1end);
if (track.pan2begin == -101) {
pan2 = pan1;
} else {
pan2 = _vm->_rnd.getRandomNumberRng(track.pan2begin, track.pan2end);
}
track.volume = _vm->_rnd.getRandomNumberRng(track.volume1, track.volume2);
track.audio_player_track = _vm->_audioPlayer->playAud(
track.name,
track.volume * _ambientVolume / 100,
pan1, pan2,
track.priority,
AudioPlayer::OVERRIDE_VOLUME
);
track.nextPlayTime = now + _vm->_rnd.getRandomNumberRng(track.time1, track.time2);
}
}
int AmbientSounds::findAvailableNonLoopingTrack() {
for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
if (!_nonLoopingSounds[i].isActive)
return i;
}
return -1;
}
int AmbientSounds::findNonLoopingTrackByHash(int32 hash) {
for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
NonLoopingSound &track = _nonLoopingSounds[i];
if (track.isActive && track.hash == hash)
return i;
}
return -1;
}
int AmbientSounds::findAvailableLoopingTrack() {
for (int i = 0; i != LOOPING_SOUNDS; ++i) {
if (!_loopingSounds[i].isActive)
return i;
}
return -1;
}
int AmbientSounds::findLoopingTrackByHash(int32 hash) {
for (int i = 0; i != LOOPING_SOUNDS; ++i) {
LoopingSound &track = _loopingSounds[i];
if (track.isActive && track.hash == hash)
return i;
}
return -1;
}
void AmbientSounds::addSoundByName(
const char *name,
int timeRangeBegin, int timeRangeEnd,
int volumeRangeBegin, int volumeRangeEnd,
int pan1begin, int pan1end,
int pan2begin, int pan2end,
int priority, int unk3) {
if (strlen(name) > 12) {
error("AmbientSounds::addSoundByName: Overlong name '%s'", name);
}
int i = findAvailableNonLoopingTrack();
if (i < 0)
return;
NonLoopingSound &track = _nonLoopingSounds[i];
uint32 now = g_system->getMillis();
track.isActive = true;
strcpy(track.name, name);
track.hash = mix_id(name);
track.time1 = 1000 * timeRangeBegin;
track.time2 = 1000 * timeRangeEnd;
track.nextPlayTime = now + _vm->_rnd.getRandomNumberRng(track.time1, track.time2);
track.volume1 = volumeRangeBegin;
track.volume2 = volumeRangeEnd;
track.volume = 0;
track.pan1begin = pan1begin;
track.pan1end = pan1end;
track.pan2begin = pan2begin;
track.pan2end = pan2end;
track.priority = priority;
}
} // End of namespace BladeRunner