ASYLUM: NEW SOUND SUBSYSTEM! This is still sort of WIP though because it's not a "true" implementation (direct from disassembly). It also doesn't really do anything with the new ambient sound queue, but the functionality's there for when we make more progress on the AmbientSoundItem initializations.

Also started to re-write updateBarriers(). The original is there as updateBarriers2() for the time being.

git-svn-id: http://asylumengine.googlecode.com/svn/trunk@362 0bfb4aae-4ea4-11de-8d8d-752d95cf3e3c
This commit is contained in:
Alex Bevilacqua 2009-09-20 21:10:43 +00:00 committed by Eugene Sandulenko
parent 461ddd8dd0
commit 52206f1189
No known key found for this signature in database
GPG key ID: 014D387312D34F08
14 changed files with 471 additions and 69 deletions

View file

@ -611,10 +611,8 @@ int kEnableBarriers(ActionCommand *cmd, Scene *scn) {
uint32 v59 = cmd->param2; uint32 v59 = cmd->param2;
if (!scn->actions()->getScript()->counter && scn->getSceneIndex() != 13 && sndIdx != 0) { if (!scn->actions()->getScript()->counter && scn->getSceneIndex() != 13 && sndIdx != 0) {
ResourcePack *sfx = new ResourcePack(18); scn->vm()->sound()->playSound(((sndIdx != 0) & 5) + 0x80120001,
scn->vm()->sound()->playSfx(sfx, ((unsigned int)(sndIdx != 0) & 5) + 0x80120001); false, scn->vm()->soundVolume(), 0);
delete sfx;
//scn->vm()->sound()->playSfx(scn->getSpeechPack(),sndIdx + 86);
} }
if (scn->actions()->getScript()->counter >= 3 * v59 - 1) { if (scn->actions()->getScript()->counter >= 3 * v59 - 1) {
@ -805,7 +803,7 @@ int kPlayMovie(ActionCommand *cmd, Scene *scn) {
int kStopAllBarriersSounds(ActionCommand *cmd, Scene *scn) { int kStopAllBarriersSounds(ActionCommand *cmd, Scene *scn) {
// TODO: do this for all barriers that have sfx playing // TODO: do this for all barriers that have sfx playing
scn->vm()->sound()->stopSfx(); scn->vm()->sound()->stopAllSounds();
return -1; return -1;
} }
@ -934,9 +932,9 @@ int kPlaySpeech(ActionCommand *cmd, Scene *scn) {
if ((int)sndIdx >= 0) { if ((int)sndIdx >= 0) {
if (sndIdx >= 259) { if (sndIdx >= 259) {
sndIdx -= 9; sndIdx -= 9;
scn->vm()->sound()->playSfx(scn->getSpeechPack(), sndIdx - 0x7FFD0000); scn->vm()->sound()->playSpeech(sndIdx - 0x7FFD0000);
} else { } else {
scn->vm()->sound()->playSfx(scn->getSpeechPack(), sndIdx); scn->vm()->sound()->playSpeech(sndIdx);
} }
} else } else
debugC(kDebugLevelScripts, debugC(kDebugLevelScripts,

View file

@ -54,6 +54,10 @@ AsylumEngine::AsylumEngine(OSystem *system, Common::Language language)
g_eventRec.registerRandomSource(_rnd, "asylum"); g_eventRec.registerRandomSource(_rnd, "asylum");
memset(_gameFlags, 0, 1512); memset(_gameFlags, 0, 1512);
// initialize default configuration
_ambientVolume = 0;
_soundVolume = 0;
} }
AsylumEngine::~AsylumEngine() { AsylumEngine::~AsylumEngine() {
@ -149,22 +153,18 @@ void AsylumEngine::waitForTimer(int msec_delay) {
void AsylumEngine::playIntro() { void AsylumEngine::playIntro() {
_video->playVideo(1, kSubtitlesOn); _video->playVideo(1, kSubtitlesOn);
if (_scene->worldstats()->musicCurrentResId != 0xFFFFFD66) if (_scene->worldstats()->musicCurrentResId != 0xFFFFFD66)
_sound->playMusic(_scene->getMusicPack(), _sound->playMusic(_scene->worldstats()->musicCurrentResId);
_scene->worldstats()->musicCurrentResId);
_screen->clearScreen(); _screen->clearScreen();
setGameFlag(4); setGameFlag(4);
setGameFlag(12); setGameFlag(12);
ResourcePack *introRes = new ResourcePack(18); // Play the intro sound sample (the screen is blacked out, you hear
// an alarm sounding and men talking about.
_sound->playSfx(introRes, 7); _sound->playSound(0x8012007, false, _soundVolume, 0);
_introPlaying = true;
delete introRes;
} }
void AsylumEngine::checkForEvent(bool doUpdate) { // k_sub_40AE30 (0040AE30) void AsylumEngine::checkForEvent(bool doUpdate) { // k_sub_40AE30 (0040AE30)
@ -178,7 +178,7 @@ void AsylumEngine::checkForEvent(bool doUpdate) { // k_sub_40AE30 (0040AE30)
// by moving the logic to the event loop and checking whether a flag is // by moving the logic to the event loop and checking whether a flag is
// set to determine if control should be returned to the engine. // set to determine if control should be returned to the engine.
if (_introPlaying) { if (_introPlaying) {
if (!_sound->isSfxActive()) { if (!_sound->isPlaying(0x8012007)) {
_introPlaying = false; _introPlaying = false;
// TODO Since we've currently only got one sfx handle to play with in // TODO Since we've currently only got one sfx handle to play with in
@ -258,7 +258,7 @@ void AsylumEngine::processDelayedEvents() {
int videoIdx = _scene->actions()->delayedVideoIndex; int videoIdx = _scene->actions()->delayedVideoIndex;
if (videoIdx >= 0) { if (videoIdx >= 0) {
_sound->stopMusic(); _sound->stopMusic();
_sound->stopSfx(); _sound->stopAllSounds();
_video->playVideo(videoIdx, kSubtitlesOn); _video->playVideo(videoIdx, kSubtitlesOn);
_scene->actions()->delayedVideoIndex = -1; _scene->actions()->delayedVideoIndex = -1;
@ -272,7 +272,7 @@ void AsylumEngine::processDelayedEvents() {
int sceneIdx = _scene->actions()->delayedSceneIndex; int sceneIdx = _scene->actions()->delayedSceneIndex;
if (sceneIdx >=0 && !_scene->actions()->processing) { if (sceneIdx >=0 && !_scene->actions()->processing) {
_sound->stopMusic(); _sound->stopMusic();
_sound->stopSfx(); _sound->stopAllSounds();
if (_scene) if (_scene)
delete _scene; delete _scene;

View file

@ -39,6 +39,17 @@
namespace Asylum { namespace Asylum {
// XXX
// I'm not sure if system endian-ness would have any
// effect byte order of the data files, but I guess
// it won't hurt to keep this here until we can test
// on a big-endian system
#ifndef SCUMM_BIG_ENDIAN
#define LOBYTE(word) (word & 0xFF)
#else
#define LOBYTE(word) ((word >> 24) & 0xFF)
#endif
class Console; class Console;
class Scene; class Scene;
class MainMenu; class MainMenu;
@ -83,6 +94,9 @@ public:
Screen* screen() { return _screen; } Screen* screen() { return _screen; }
Scene* scene() { return _scene; } Scene* scene() { return _scene; }
int ambientVolume() { return _ambientVolume; }
int soundVolume() { return _soundVolume; }
private: private:
void checkForEvent(bool doUpdate); void checkForEvent(bool doUpdate);
void waitForTimer(int msec_delay); void waitForTimer(int msec_delay);
@ -93,6 +107,9 @@ private:
Common::Language _language; Common::Language _language;
Common::RandomSource _rnd; Common::RandomSource _rnd;
int _ambientVolume;
int _soundVolume;
bool _introPlaying; bool _introPlaying;
Console *_console; Console *_console;

View file

@ -111,6 +111,12 @@ void BlowUpPuzzleVCR::handleEvent(Common::Event *event, bool doUpdate) {
update(); update();
} }
void BlowUpPuzzle::playSound(uint resourceId) {
ResourceEntry *resource = _scene->getResourcePack()->getResource(resourceId);
int volume = _scene->vm()->soundVolume();
_scene->vm()->sound()->playSound(resource, false, volume, 0);
}
int BlowUpPuzzleVCR::inPolyRegion(int x, int y, int polyIdx) { int BlowUpPuzzleVCR::inPolyRegion(int x, int y, int polyIdx) {
return x >= BlowUpPuzzleVCRPolies[polyIdx].left && x <= BlowUpPuzzleVCRPolies[polyIdx].right && return x >= BlowUpPuzzleVCRPolies[polyIdx].left && x <= BlowUpPuzzleVCRPolies[polyIdx].right &&
y >= BlowUpPuzzleVCRPolies[polyIdx].top && y <= BlowUpPuzzleVCRPolies[polyIdx].bottom; y >= BlowUpPuzzleVCRPolies[polyIdx].top && y <= BlowUpPuzzleVCRPolies[polyIdx].bottom;
@ -318,13 +324,13 @@ int BlowUpPuzzleVCR::setJackOnHole(int jackType, JackState plugged) {
if(_jacksState[jackType-1] == kOnHand) { if(_jacksState[jackType-1] == kOnHand) {
_jacksState[jackType-1] = plugged; _jacksState[jackType-1] = plugged;
_holesState[plugged-1] = jackType; // set jack on red _holesState[plugged-1] = jackType; // set jack on red
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[44]); playSound(_scene->worldstats()->grResId[44]);
} }
} else if(jackType == 0) { } else if(jackType == 0) {
jackType = _holesState[plugged-1]; jackType = _holesState[plugged-1];
_jacksState[jackType-1] = kOnHand; _jacksState[jackType-1] = kOnHand;
_holesState[plugged-1] = 0; _holesState[plugged-1] = 0;
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[43]); playSound(_scene->worldstats()->grResId[43]);
return 0; return 0;
} }
return 1; return 1;
@ -500,7 +506,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
if (_cursor->x() >= (uint32)BlowUpPuzzleVCRPolies[kBlackJack].left && _cursor->x() <= (uint32)BlowUpPuzzleVCRPolies[kYellowJack].right && if (_cursor->x() >= (uint32)BlowUpPuzzleVCRPolies[kBlackJack].left && _cursor->x() <= (uint32)BlowUpPuzzleVCRPolies[kYellowJack].right &&
_cursor->y() >= (uint32)BlowUpPuzzleVCRPolies[kBlackJack].top && _cursor->y() <= (uint32)BlowUpPuzzleVCRPolies[kYellowJack].bottom) { _cursor->y() >= (uint32)BlowUpPuzzleVCRPolies[kBlackJack].top && _cursor->y() <= (uint32)BlowUpPuzzleVCRPolies[kYellowJack].bottom) {
_jacksState[jackType-1] = kOnTable; _jacksState[jackType-1] = kOnTable;
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[50]); playSound(_scene->worldstats()->grResId[50]);
_cursor->show(); _cursor->show();
} }
return; return;
@ -517,7 +523,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
// TODO: VCR button regions // TODO: VCR button regions
if (inPolyRegion(_cursor->x(), _cursor->y(), kRewindButton)) { if (inPolyRegion(_cursor->x(), _cursor->y(), kRewindButton)) {
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[39]); playSound(_scene->worldstats()->grResId[39]);
if(!_buttonsState[kRewind]) { if(!_buttonsState[kRewind]) {
_buttonsState[kRewind] = kDownON; _buttonsState[kRewind] = kDownON;
return; return;
@ -527,7 +533,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
return; return;
} }
} else if (inPolyRegion(_cursor->x(), _cursor->y(), kPlayButton)) { } else if (inPolyRegion(_cursor->x(), _cursor->y(), kPlayButton)) {
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[39]); playSound(_scene->worldstats()->grResId[39]);
if(!_buttonsState[kPlay]) { if(!_buttonsState[kPlay]) {
_buttonsState[kPlay] = kDownON; _buttonsState[kPlay] = kDownON;
return; return;
@ -537,7 +543,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
return; return;
} }
} else if (inPolyRegion(_cursor->x(), _cursor->y(), kStopButton)) { } else if (inPolyRegion(_cursor->x(), _cursor->y(), kStopButton)) {
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[39]); playSound(_scene->worldstats()->grResId[39]);
if(_buttonsState[kStop]) { if(_buttonsState[kStop]) {
if(_buttonsState[kStop] == kON) { if(_buttonsState[kStop] == kON) {
_buttonsState[kStop] = kDownOFF; _buttonsState[kStop] = kDownOFF;
@ -548,7 +554,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
return; return;
} }
} else if (inPolyRegion(_cursor->x(), _cursor->y(), kPowerButton)) { } else if (inPolyRegion(_cursor->x(), _cursor->y(), kPowerButton)) {
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[39]); playSound(_scene->worldstats()->grResId[39]);
if(!_buttonsState[kPower] && _holesState[kPluggedOnBlack-1] == kBlack+1 && _holesState[kPluggedOnRed-1] && _holesState[kPluggedOnYellow-1]) { if(!_buttonsState[kPower] && _holesState[kPluggedOnBlack-1] == kBlack+1 && _holesState[kPluggedOnRed-1] && _holesState[kPluggedOnYellow-1]) {
_buttonsState[kPower] = kDownON; _buttonsState[kPower] = kDownON;
@ -564,7 +570,7 @@ void BlowUpPuzzleVCR::handleMouseUp() {
if(_buttonsState[kPower] == kDownON) { if(_buttonsState[kPower] == kDownON) {
// TODO: check if next sound is already playing // TODO: check if next sound is already playing
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[47]); playSound(_scene->worldstats()->grResId[47]);
_buttonsState[kPower] = kON; _buttonsState[kPower] = kON;
_buttonsState[kStop] = kON; _buttonsState[kStop] = kON;
_buttonsState[kPlay] = kON; _buttonsState[kPlay] = kON;
@ -579,7 +585,7 @@ void BlowUpPuzzleVCR::handleMouseUp() {
if(_buttonsState[kRewind] == kDownOFF) { if(_buttonsState[kRewind] == kDownOFF) {
_buttonsState[kRewind] = kON; _buttonsState[kRewind] = kON;
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[46]); playSound(_scene->worldstats()->grResId[46]);
} else if(_buttonsState[kRewind] == kDownON) { } else if(_buttonsState[kRewind] == kDownON) {
_buttonsState[kRewind] = kOFF; _buttonsState[kRewind] = kOFF;
} }

View file

@ -66,6 +66,7 @@ protected:
GraphicResource *_bgResource; GraphicResource *_bgResource;
virtual void update() {}; virtual void update() {};
void playSound(uint resourceId);
}; // end of class BlowUpPuzzle }; // end of class BlowUpPuzzle

View file

@ -82,7 +82,12 @@ void MainMenu::openMenu() {
_vm->screen()->setPalette(_resPack, 17); _vm->screen()->setPalette(_resPack, 17);
// Copy the bright background to the back buffer // Copy the bright background to the back buffer
GraphicFrame *bg = _bgResource->getFrame(1); GraphicFrame *bg = _bgResource->getFrame(1);
_vm->screen()->copyToBackBuffer((byte *)bg->surface.pixels, bg->surface.w, 0, 0, bg->surface.w, bg->surface.h); _vm->screen()->copyToBackBuffer((byte *)bg->surface.pixels,
bg->surface.w,
0,
0,
bg->surface.w,
bg->surface.h);
// Set mouse cursor // Set mouse cursor
_cursor->load(2); _cursor->load(2);
@ -90,7 +95,7 @@ void MainMenu::openMenu() {
// Stop all sounds // Stop all sounds
_vm->sound()->stopMusic(); _vm->sound()->stopMusic();
_vm->sound()->stopSfx(); _vm->sound()->stopSound();
// Start playing music // Start playing music
_vm->sound()->playMusic(_resPack, 39); _vm->sound()->playMusic(_resPack, 39);
@ -105,7 +110,7 @@ void MainMenu::closeMenu() {
_vm->scene()->activate(); _vm->scene()->activate();
// Stop menu sounds and menu music // Stop menu sounds and menu music
_vm->sound()->stopSfx(); _vm->sound()->stopSound();
_vm->sound()->stopMusic(); _vm->sound()->stopMusic();
} }
@ -284,8 +289,8 @@ void MainMenu::updateMainMenu() {
_text->drawResTextCentered(MenuIconFixedXpos[iconNum], iconFrame->y + 50, _text->getResTextWidth(iconNum + 1309), iconNum + 1309); _text->drawResTextCentered(MenuIconFixedXpos[iconNum], iconFrame->y + 50, _text->getResTextWidth(iconNum + 1309), iconNum + 1309);
// Play creepy voice // Play creepy voice
if (!_vm->sound()->isSfxActive() && _activeIcon != _previousActiveIcon) { if (_activeIcon != _previousActiveIcon) {
_vm->sound()->playSfx(_resPack, iconNum + 44); _vm->sound()->playSound(_resPack, iconNum + 44, _vm->soundVolume());
_previousActiveIcon = _activeIcon; _previousActiveIcon = _activeIcon;
} }

View file

@ -72,7 +72,7 @@ void ResourcePack::init(const char *resourceFile) {
} }
ResourceEntry *ResourcePack::getResource(uint32 resourceId) { ResourceEntry *ResourcePack::getResource(uint32 resourceId) {
uint16 index = resourceId & 0xFFFF; uint16 index = RESIDX(resourceId);
if (!_resources[index].data) { if (!_resources[index].data) {
// Load the requested resource if it's not loaded already // Load the requested resource if it's not loaded already
_packFile.seek(_resources[index].offset, SEEK_SET); _packFile.seek(_resources[index].offset, SEEK_SET);

View file

@ -31,6 +31,9 @@
namespace Asylum { namespace Asylum {
#define RESID(id) ((id >> 16) & 0x7FFF)
#define RESIDX(id) (id & 0XFFFF)
struct ResourceEntry { struct ResourceEntry {
byte *data; byte *data;
uint32 size; uint32 size;

View file

@ -69,7 +69,6 @@ Scene::Scene(uint8 sceneIdx, AsylumEngine *vm): _vm(vm) {
_text = new Text(_vm->screen()); _text = new Text(_vm->screen());
_resPack = new ResourcePack(sceneIdx); _resPack = new ResourcePack(sceneIdx);
_speechPack = new ResourcePack(3); // FIXME are all scene speech packs the same?
// FIXME // FIXME
// Is there EVER more than one actor enabled for a scene? I can't // Is there EVER more than one actor enabled for a scene? I can't
@ -139,6 +138,12 @@ Scene::Scene(uint8 sceneIdx, AsylumEngine *vm): _vm(vm) {
} }
} }
// XXX
// This is a hack for the moment to test out
// the new sound queuing functionality
for (uint i = 0; i < _ws->numAmbientSound; i++)
_vm->sound()->addToSoundBuffer(_ws->ambientSounds[i].resId);
// TODO: init action list // TODO: init action list
} }
@ -150,7 +155,6 @@ Scene::~Scene() {
delete _cursor; delete _cursor;
delete _bgResource; delete _bgResource;
delete _musPack; delete _musPack;
delete _speechPack;
delete _resPack; delete _resPack;
delete _text; delete _text;
delete _blowUp; delete _blowUp;
@ -267,7 +271,7 @@ int Scene::updateScene() {
// Barriers // Barriers
startTick = _vm->_system->getMillis(); startTick = _vm->_system->getMillis();
updateBarriers(); updateBarriers2();
debugC(kDebugLevelScene, "UpdateBarriers Time: %d", _vm->_system->getMillis() - startTick); debugC(kDebugLevelScene, "UpdateBarriers Time: %d", _vm->_system->getMillis() - startTick);
// Ambient Sounds // Ambient Sounds
@ -528,7 +532,38 @@ void Scene::updateActor(uint32 actorIdx) {
} }
} }
// XXX WIP
void Scene::updateBarriers() { void Scene::updateBarriers() {
int v1, v0, v32, v33, v34, tickVal, tickVal05, tickVal06;
v1 = v0 = v32 = v33 = v34 = tickVal = tickVal05 = tickVal06 = 0;
uint32 start, v2, v31;
bool done = false;
//if (_ws->barriers.size() > 0);
v2 = _ws->barriers[0].tickCount2;
for (uint32 idx = 0; idx < _ws->numBarriers; idx++) {
Barrier *b = &_ws->barriers[idx];
start = _vm->_system->getMillis();
if (v2 - 32 != 4)
done = true;
if (!done && !_ws->checkBarrierFlagsCondition(idx)) {
v31 = _vm->_system->getMillis();
}
/*
* TODO
*/
v2 += 426;
v1 = 0;
done = false;
}
}
void Scene::updateBarriers2() {
Screen *screen = _vm->screen(); Screen *screen = _vm->screen();
uint barriersCount = _ws->barriers.size(); uint barriersCount = _ws->barriers.size();
@ -669,6 +704,95 @@ void Scene::updateBarriers() {
} }
void Scene::updateAmbientSounds() { void Scene::updateAmbientSounds() {
// if (cfgGameQualityValue > 3)
int v2 = 1;
int v15, v11, v10, v16;
int panning, volume;
for (uint32 i = 0; i < _ws->numAmbientSound; i++) {
AmbientSoundItem *snd = &_ws->ambientSounds[i];
for (uint32 f = 0; f < 6; f++) {
uint gameFlag = snd->flagNum[f];
if (gameFlag >= 0) {
if (_vm->isGameFlagNotSet(gameFlag)) {
v2 = 0;
break;
}
} else {
if (_vm->isGameFlagSet(-gameFlag)) {
// XXX Looks like this just jumps back to
// the top of the loop, so not sure if this
// is somehow important
}
}
}
if (v2) {
if (_vm->sound()->isPlaying(snd->resId)) {
if (snd->field_0) {
; // TODO volume calculation
}
} else {
if (snd->field_0) {
; // TODO calculate panning at point
} else {
panning = 0;
}
if (snd->field_0 == 0) {
volume = -(snd->field_C ^ 2);
} else {
; // TODO calculate volume increase
}
if (LOBYTE(snd->flags) & 2) {
if (rand() % 10000 < 10) {
if (snd->field_0) {
_vm->sound()->playSound(_resPack, snd->resId, false, _vm->ambientVolume() + volume, panning);
} else {
v15 = rand() % 500;
v11 = v15 * ((((rand() % 100 >= 50) - 1) & 2) - 1) + volume;
v10 = v11;
if ( v11 <= -10000 )
v10 = -10000;
if ( v10 >= 0 )
v11 = 0;
else
if ( v11 <= -10000 )
v11 = -10000;
v16 = rand();
_vm->sound()->playSound(_resPack, snd->resId, false, v11, v16 % 20001 - 10000);
}
} else {
if (LOBYTE(snd->flags) & 4) {
/*
if ( (unsigned int)*ambientPanningArray < getTickCount() )
{
if ( v1->field_14 >= 0 )
v12 = 60000 * v1->field_14 + getTickCount();
else
v12 = getTickCount() - 1000 * v1->field_14;
*ambientPanningArray = v12;
playSound(v7, 0, v9, panning);
}
*/
} else {
if (LOBYTE(snd->flags) & 8) {
/*
if ( !*(ambientPanningArray - 15) )
{
playSound(v7, 0, v9, panning);
*(ambientPanningArray - 15) = 1;
}
*/
}
}
}
}
}
}
}
} }
void Scene::updateMusic() { void Scene::updateMusic() {

View file

@ -69,7 +69,6 @@ public:
Cursor* getCursor() { return _cursor; } Cursor* getCursor() { return _cursor; }
ResourcePack* getResourcePack() { return _resPack; } ResourcePack* getResourcePack() { return _resPack; }
ResourcePack* getMusicPack() { return _musPack; } ResourcePack* getMusicPack() { return _musPack; }
ResourcePack* getSpeechPack() { return _speechPack; }
GraphicResource* getGraphicResource(uint32 entry) { return new GraphicResource(_resPack, entry); } GraphicResource* getGraphicResource(uint32 entry) { return new GraphicResource(_resPack, entry); }
BlowUpPuzzle* getBlowUpPuzzle() { return _blowUp; } BlowUpPuzzle* getBlowUpPuzzle() { return _blowUp; }
@ -110,6 +109,7 @@ private:
void updateMouse(); void updateMouse();
void updateActor(uint32 actorIdx); void updateActor(uint32 actorIdx);
void updateBarriers(); void updateBarriers();
void updateBarriers2(); // XXX Alexandre's version
void updateAmbientSounds(); void updateAmbientSounds();
void updateMusic(); void updateMusic();
void updateAdjustScreen(); void updateAdjustScreen();

View file

@ -24,32 +24,240 @@
*/ */
#include "asylum/sound.h" #include "asylum/sound.h"
#include "asylum/asylum.h"
#include "common/stream.h" #include "common/stream.h"
#include "sound/audiostream.h"
#include "sound/adpcm.h"
#include "sound/wave.h" #include "sound/wave.h"
namespace Asylum { namespace Asylum {
Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer) { Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer) {
_speechPack = new ResourcePack(3);
_soundPack = new ResourcePack(18);
} }
Sound::~Sound() { Sound::~Sound() {
delete _speechPack;
delete _soundPack;
clearSoundBuffer();
} }
void Sound::playSfx(byte *data, uint32 size) { // from engines/agos/sound.cpp
Common::MemoryReadStream *mem = new Common::MemoryReadStream(data, size); void convertVolume(int &vol) {
// DirectSound was orginally used, which specifies volume
// and panning differently than ScummVM does, using a logarithmic scale
// rather than a linear one.
//
// Volume is a value between -10,000 and 0.
//
// In both cases, the -10,000 represents -100 dB. When panning, only
// one speaker's volume is affected - just like in ScummVM - with
// negative values affecting the left speaker, and positive values
// affecting the right speaker. Thus -10,000 means the left speaker is
// silent.
// Now create the audio stream and play it (it's just a regular WAVE file) int v = CLIP(vol, -10000, 0);
Audio::AudioStream *sfx = Audio::makeWAVStream(mem, true); if (v) {
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, sfx); vol = (int)((double)Audio::Mixer::kMaxChannelVolume * pow(10.0, (double)v / 2000.0) + 0.5);
} else {
vol = Audio::Mixer::kMaxChannelVolume;
}
} }
void Sound::playMusic(byte *data, uint32 size) { // from engines/agos/sound.cpp
Common::MemoryReadStream *mem = new Common::MemoryReadStream(data, size); void convertPan(int &pan) {
// DirectSound was orginally used, which specifies volume
// and panning differently than ScummVM does, using a logarithmic scale
// rather than a linear one.
//
// Panning is a value between -10,000 and 10,000.
//
// In both cases, the -10,000 represents -100 dB. When panning, only
// one speaker's volume is affected - just like in ScummVM - with
// negative values affecting the left speaker, and positive values
// affecting the right speaker. Thus -10,000 means the left speaker is
// silent.
// Now create the audio stream and play it (it's just a regular WAVE file) int p = CLIP(pan, -10000, 10000);
Audio::AudioStream *mus = Audio::makeWAVStream(mem, true); if (p < 0) {
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, mus); pan = (int)(255.0 * pow(10.0, (double)p / 2000.0) + 127.5);
} else if (p > 0) {
pan = (int)(255.0 * pow(10.0, (double)p / -2000.0) - 127.5);
} else {
pan = 0;
}
}
int Sound::getBufferPosition(uint32 resId) {
int pos = -1;
for (uint i = 0; i < _soundBuffer.size(); i++) {
if (resId == _soundBuffer[i].resId) {
pos = i;
break;
}
}
return pos;
}
bool Sound::addToSoundBuffer(uint resId) {
int exists = getBufferPosition(resId);
if (exists >= 0) {
SoundBufferItem sound;
sound.resId = resId;
_soundBuffer.push_back(sound);
}
return (exists < 0) ? true : false;
}
void Sound::clearSoundBuffer() {
_soundBuffer.clear();
}
bool Sound::isPlaying(uint resId) {
int pos = getBufferPosition(resId);
if (pos < 0) {
warning("isPlaying: resId %d not currently bufferred", resId);
} else {
SoundBufferItem snd = _soundBuffer[pos];
if (_mixer->isSoundHandleActive(snd.handle)) {
return true;
}
}
return false;
}
void Sound::playSound(ResourcePack *pack, uint resId, int volume, bool looping, int panning, bool overwrite) {
ResourceEntry *resource = pack->getResource(resId);
if (_mixer->isSoundHandleActive(_soundHandle)) {
if (overwrite) {
_mixer->stopHandle(_soundHandle);
playSound(resource, looping, volume, panning);
}
// if the current handle isn't active, play the sound
playSound(resource, looping, volume, panning);
}
}
void Sound::playSound(ResourceEntry *resource, bool looping, int volume, int panning) {
playSoundData(&_soundHandle, resource->data, resource->size, looping, volume, panning);
}
void Sound::playSound(ResourcePack *pack, uint resId, bool looping, int volume, int panning) {
int pos = getBufferPosition(resId);
if (pos < 0) {
warning("isPlaying: resId %d not currently bufferred", resId);
} else {
SoundBufferItem snd = _soundBuffer[pos];
if (_mixer->isSoundHandleActive(snd.handle)) {
debugC(kDebugLevelSound, "playSound: handle for resId %d already active", resId);
} else {
ResourceEntry *ent = _soundPack->getResource(resId);
playSoundData(&snd.handle, ent->data, ent->size, looping, volume, panning);
}
}
}
void Sound::playSound(uint resId, bool looping, int volume, int panning, bool fromBuffer) {
if (fromBuffer) {
playSound(_soundPack, resId, looping, volume, panning);
} else {
if (_mixer->isSoundHandleActive(_soundHandle)) {
debugC(kDebugLevelSound, "playSound: temporary sound handle is active");
} else {
ResourceEntry *ent = _soundPack->getResource(resId);
playSound(ent, looping, volume, panning);
}
}
}
void Sound::stopSound() {
if (_mixer->isSoundHandleActive(_soundHandle))
_mixer->stopHandle(_soundHandle);
}
void Sound::stopSound(uint resId) {
int pos = getBufferPosition(resId);
if (pos < 0) {
warning("isPlaying: resId %d not currently bufferred", resId);
} else {
_mixer->stopHandle(_soundBuffer[pos].handle);
}
}
void Sound::stopAllSounds() {
_mixer->stopHandle(_soundHandle);
for (uint i = 0; i < _soundBuffer.size(); i++)
_mixer->stopHandle(_soundBuffer[i].handle);
}
void Sound::playSpeech(uint resId) {
ResourceEntry *ent = _speechPack->getResource(resId);
_mixer->stopHandle(_speechHandle);
playSoundData(&_speechHandle, ent->data, ent->size, false, 0, 0);
}
void Sound::playMusic(uint resId) {
stopMusic();
// TODO Play music :P
}
void Sound::playMusic(ResourcePack *pack, uint resId) {
stopMusic();
ResourceEntry *resource = pack->getResource(resId);
playSoundData(&_musicHandle, resource->data, resource->size, true, 0, 0);
}
void Sound::stopMusic() {
_mixer->stopHandle(_musicHandle);
}
// from engines/agos/sound.cpp
void Sound::playSoundData(Audio::SoundHandle *handle, byte *soundData, uint soundDataLength, bool loop, int vol, int pan) {
byte *buffer, flags;
uint16 compType;
int blockAlign, rate;
// TODO: Use makeWAVStream() in future, when makeADPCMStream() allows sound looping
int size = soundDataLength;
Common::MemoryReadStream stream(soundData, size);
if (!Audio::loadWAVFromStream(stream, size, rate, flags, &compType, &blockAlign))
error("playSound: Not valid WAV data");
convertVolume(vol);
convertPan(pan);
if (loop == true)
flags |= Audio::Mixer::FLAG_LOOP;
if (compType == 2) {
Audio::AudioStream *sndStream = Audio::makeADPCMStream(&stream, false, size, Audio::kADPCMMS, rate, (flags & Audio::Mixer::FLAG_STEREO) ? 2 : 1, blockAlign);
buffer = (byte *)malloc(size * 4);
size = sndStream->readBuffer((int16*)buffer, size * 2);
size *= 2; // 16bits.
delete sndStream;
} else {
buffer = (byte *)malloc(size);
memcpy(buffer, soundData + stream.pos(), size);
}
_mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer, size, rate, flags | Audio::Mixer::FLAG_AUTOFREE, -1, vol, pan);
} }
} // end of namespace Asylum } // end of namespace Asylum

View file

@ -27,6 +27,7 @@
#define ASYLUM_SOUND_H_ #define ASYLUM_SOUND_H_
#include "sound/mixer.h" #include "sound/mixer.h"
#include "asylum/respack.h" #include "asylum/respack.h"
namespace Asylum { namespace Asylum {
@ -62,35 +63,55 @@ typedef struct AmbientSoundItem {
} AmbientSoundItem; } AmbientSoundItem;
typedef struct SoundBufferItem {
uint32 resId;
Audio::SoundHandle handle;
uint32 unknown;
} SoundBufferItem;
class Sound { class Sound {
public: public:
Sound(Audio::Mixer *mixer); Sound(Audio::Mixer *mixer);
~Sound(); ~Sound();
void playSfx(byte *data, uint32 size); bool addToSoundBuffer(uint resId);
void playSfx(ResourcePack *resPack, uint32 resourceId) { void clearSoundBuffer();
ResourceEntry *resEntry = resPack->getResource(resourceId);
playSfx(resEntry->data, resEntry->size);
}
bool isSfxActive() { return _mixer->isSoundHandleActive(_sfxHandle); }
void pauseSfx() { _mixer->pauseHandle(_sfxHandle, true); }
void resumeSfx() { _mixer->pauseHandle(_sfxHandle, false); }
void stopSfx() { _mixer->stopHandle(_sfxHandle); }
void playMusic(byte *data, uint32 size); /**
void playMusic(ResourcePack *resPack, uint32 resourceId) { * Play a sound resource from the supplied resource pack.
ResourceEntry *resEntry = resPack->getResource(resourceId); *
playMusic(resEntry->data, resEntry->size); * @param overwrite determine if _soundHandle should be overwritten if still active
} */
bool isMusicActive() { return _mixer->isSoundHandleActive(_musicHandle); } void playSound(ResourcePack *pack, uint resId, int volume, bool looping = false, int panning = 0, bool overwrite = false);
void pauseMusic() { _mixer->pauseHandle(_musicHandle, true); } void playSound(ResourcePack *pack, uint resId, bool looping, int volume, int panning);
void resumeMusic() { _mixer->pauseHandle(_musicHandle, false); } void playSound(ResourceEntry *resource, bool looping, int volume, int panning);
void stopMusic() { _mixer->stopHandle(_musicHandle); } void playSound(uint resId, bool looping, int volume, int panning, bool fromBuffer = false);
void stopSound(uint resId);
void stopSound();
void stopAllSounds();
void playSpeech(uint resId);
void playMusic(ResourcePack *pack, uint resId);
void playMusic(uint resId);
void stopMusic();
bool isPlaying(uint resId);
private: private:
Audio::SoundHandle _sfxHandle;
Audio::SoundHandle _musicHandle;
Audio::Mixer *_mixer; Audio::Mixer *_mixer;
Audio::SoundHandle _speechHandle;
Audio::SoundHandle _musicHandle;
Audio::SoundHandle _soundHandle;
ResourcePack *_speechPack;
ResourcePack *_soundPack;
Common::Array<SoundBufferItem> _soundBuffer;
int getBufferPosition(uint32 resId);
void playSoundData(Audio::SoundHandle *handle, byte *soundData, uint32 soundDataLength, bool loop = false, int vol = 0, int pan = 0);
}; };
} // end of namespace Asylum } // end of namespace Asylum

View file

@ -98,6 +98,24 @@ bool WorldStats::isBarrierVisible(uint32 idx) {
return false; return false;
} }
bool WorldStats::checkBarrierFlagsCondition(uint32 idx) {
Barrier *b = getBarrierByIndex(idx);
bool result;
if (LOBYTE(b->flags) & 1) {
for (int i = 0; i < 10; i++) {
result = _scene->vm()->isGameFlagSet(b->gameFlags[i]);
if (result)
return result;
}
result = true;
} else {
result = false;
}
return result;
}
// FIXME: load necessary World Stats content // FIXME: load necessary World Stats content
void WorldStats::load(Common::SeekableReadStream *stream) { void WorldStats::load(Common::SeekableReadStream *stream) {
size = stream->readUint32LE(); size = stream->readUint32LE();

View file

@ -154,7 +154,8 @@ public:
bool isBarrierOnScreen(uint32 idx); bool isBarrierOnScreen(uint32 idx);
bool isBarrierVisible(uint32 idx); bool isBarrierVisible(uint32 idx);
// TODO this needs a better name
bool checkBarrierFlagsCondition(uint32 idx);
private: private:
Scene *_scene; Scene *_scene;