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:
parent
461ddd8dd0
commit
52206f1189
14 changed files with 471 additions and 69 deletions
|
@ -611,10 +611,8 @@ int kEnableBarriers(ActionCommand *cmd, Scene *scn) {
|
|||
uint32 v59 = cmd->param2;
|
||||
|
||||
if (!scn->actions()->getScript()->counter && scn->getSceneIndex() != 13 && sndIdx != 0) {
|
||||
ResourcePack *sfx = new ResourcePack(18);
|
||||
scn->vm()->sound()->playSfx(sfx, ((unsigned int)(sndIdx != 0) & 5) + 0x80120001);
|
||||
delete sfx;
|
||||
//scn->vm()->sound()->playSfx(scn->getSpeechPack(),sndIdx + 86);
|
||||
scn->vm()->sound()->playSound(((sndIdx != 0) & 5) + 0x80120001,
|
||||
false, scn->vm()->soundVolume(), 0);
|
||||
}
|
||||
|
||||
if (scn->actions()->getScript()->counter >= 3 * v59 - 1) {
|
||||
|
@ -805,7 +803,7 @@ int kPlayMovie(ActionCommand *cmd, Scene *scn) {
|
|||
|
||||
int kStopAllBarriersSounds(ActionCommand *cmd, Scene *scn) {
|
||||
// TODO: do this for all barriers that have sfx playing
|
||||
scn->vm()->sound()->stopSfx();
|
||||
scn->vm()->sound()->stopAllSounds();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -934,9 +932,9 @@ int kPlaySpeech(ActionCommand *cmd, Scene *scn) {
|
|||
if ((int)sndIdx >= 0) {
|
||||
if (sndIdx >= 259) {
|
||||
sndIdx -= 9;
|
||||
scn->vm()->sound()->playSfx(scn->getSpeechPack(), sndIdx - 0x7FFD0000);
|
||||
scn->vm()->sound()->playSpeech(sndIdx - 0x7FFD0000);
|
||||
} else {
|
||||
scn->vm()->sound()->playSfx(scn->getSpeechPack(), sndIdx);
|
||||
scn->vm()->sound()->playSpeech(sndIdx);
|
||||
}
|
||||
} else
|
||||
debugC(kDebugLevelScripts,
|
||||
|
|
|
@ -54,6 +54,10 @@ AsylumEngine::AsylumEngine(OSystem *system, Common::Language language)
|
|||
g_eventRec.registerRandomSource(_rnd, "asylum");
|
||||
|
||||
memset(_gameFlags, 0, 1512);
|
||||
|
||||
// initialize default configuration
|
||||
_ambientVolume = 0;
|
||||
_soundVolume = 0;
|
||||
}
|
||||
|
||||
AsylumEngine::~AsylumEngine() {
|
||||
|
@ -149,22 +153,18 @@ void AsylumEngine::waitForTimer(int msec_delay) {
|
|||
|
||||
void AsylumEngine::playIntro() {
|
||||
_video->playVideo(1, kSubtitlesOn);
|
||||
|
||||
if (_scene->worldstats()->musicCurrentResId != 0xFFFFFD66)
|
||||
_sound->playMusic(_scene->getMusicPack(),
|
||||
_scene->worldstats()->musicCurrentResId);
|
||||
_sound->playMusic(_scene->worldstats()->musicCurrentResId);
|
||||
|
||||
_screen->clearScreen();
|
||||
|
||||
setGameFlag(4);
|
||||
setGameFlag(12);
|
||||
|
||||
ResourcePack *introRes = new ResourcePack(18);
|
||||
|
||||
_sound->playSfx(introRes, 7);
|
||||
|
||||
_introPlaying = true;
|
||||
|
||||
delete introRes;
|
||||
// Play the intro sound sample (the screen is blacked out, you hear
|
||||
// an alarm sounding and men talking about.
|
||||
_sound->playSound(0x8012007, false, _soundVolume, 0);
|
||||
}
|
||||
|
||||
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
|
||||
// set to determine if control should be returned to the engine.
|
||||
if (_introPlaying) {
|
||||
if (!_sound->isSfxActive()) {
|
||||
if (!_sound->isPlaying(0x8012007)) {
|
||||
_introPlaying = false;
|
||||
|
||||
// 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;
|
||||
if (videoIdx >= 0) {
|
||||
_sound->stopMusic();
|
||||
_sound->stopSfx();
|
||||
_sound->stopAllSounds();
|
||||
_video->playVideo(videoIdx, kSubtitlesOn);
|
||||
_scene->actions()->delayedVideoIndex = -1;
|
||||
|
||||
|
@ -272,7 +272,7 @@ void AsylumEngine::processDelayedEvents() {
|
|||
int sceneIdx = _scene->actions()->delayedSceneIndex;
|
||||
if (sceneIdx >=0 && !_scene->actions()->processing) {
|
||||
_sound->stopMusic();
|
||||
_sound->stopSfx();
|
||||
_sound->stopAllSounds();
|
||||
|
||||
if (_scene)
|
||||
delete _scene;
|
||||
|
|
|
@ -39,6 +39,17 @@
|
|||
|
||||
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 Scene;
|
||||
class MainMenu;
|
||||
|
@ -83,6 +94,9 @@ public:
|
|||
Screen* screen() { return _screen; }
|
||||
Scene* scene() { return _scene; }
|
||||
|
||||
int ambientVolume() { return _ambientVolume; }
|
||||
int soundVolume() { return _soundVolume; }
|
||||
|
||||
private:
|
||||
void checkForEvent(bool doUpdate);
|
||||
void waitForTimer(int msec_delay);
|
||||
|
@ -93,6 +107,9 @@ private:
|
|||
Common::Language _language;
|
||||
Common::RandomSource _rnd;
|
||||
|
||||
int _ambientVolume;
|
||||
int _soundVolume;
|
||||
|
||||
bool _introPlaying;
|
||||
|
||||
Console *_console;
|
||||
|
|
|
@ -111,6 +111,12 @@ void BlowUpPuzzleVCR::handleEvent(Common::Event *event, bool doUpdate) {
|
|||
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) {
|
||||
return x >= BlowUpPuzzleVCRPolies[polyIdx].left && x <= BlowUpPuzzleVCRPolies[polyIdx].right &&
|
||||
y >= BlowUpPuzzleVCRPolies[polyIdx].top && y <= BlowUpPuzzleVCRPolies[polyIdx].bottom;
|
||||
|
@ -318,13 +324,13 @@ int BlowUpPuzzleVCR::setJackOnHole(int jackType, JackState plugged) {
|
|||
if(_jacksState[jackType-1] == kOnHand) {
|
||||
_jacksState[jackType-1] = plugged;
|
||||
_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) {
|
||||
jackType = _holesState[plugged-1];
|
||||
_jacksState[jackType-1] = kOnHand;
|
||||
_holesState[plugged-1] = 0;
|
||||
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[43]);
|
||||
playSound(_scene->worldstats()->grResId[43]);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
@ -500,7 +506,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
|
|||
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) {
|
||||
_jacksState[jackType-1] = kOnTable;
|
||||
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[50]);
|
||||
playSound(_scene->worldstats()->grResId[50]);
|
||||
_cursor->show();
|
||||
}
|
||||
return;
|
||||
|
@ -517,7 +523,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
|
|||
|
||||
// TODO: VCR button regions
|
||||
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]) {
|
||||
_buttonsState[kRewind] = kDownON;
|
||||
return;
|
||||
|
@ -527,7 +533,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
|
|||
return;
|
||||
}
|
||||
} 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]) {
|
||||
_buttonsState[kPlay] = kDownON;
|
||||
return;
|
||||
|
@ -537,7 +543,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
|
|||
return;
|
||||
}
|
||||
} 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] == kON) {
|
||||
_buttonsState[kStop] = kDownOFF;
|
||||
|
@ -548,7 +554,7 @@ void BlowUpPuzzleVCR::handleMouseDown() {
|
|||
return;
|
||||
}
|
||||
} 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]) {
|
||||
_buttonsState[kPower] = kDownON;
|
||||
|
@ -564,7 +570,7 @@ void BlowUpPuzzleVCR::handleMouseUp() {
|
|||
|
||||
if(_buttonsState[kPower] == kDownON) {
|
||||
// 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[kStop] = kON;
|
||||
_buttonsState[kPlay] = kON;
|
||||
|
@ -579,7 +585,7 @@ void BlowUpPuzzleVCR::handleMouseUp() {
|
|||
|
||||
if(_buttonsState[kRewind] == kDownOFF) {
|
||||
_buttonsState[kRewind] = kON;
|
||||
_scene->vm()->sound()->playSfx(_scene->getResourcePack(), _scene->worldstats()->grResId[46]);
|
||||
playSound(_scene->worldstats()->grResId[46]);
|
||||
} else if(_buttonsState[kRewind] == kDownON) {
|
||||
_buttonsState[kRewind] = kOFF;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,7 @@ protected:
|
|||
GraphicResource *_bgResource;
|
||||
|
||||
virtual void update() {};
|
||||
void playSound(uint resourceId);
|
||||
|
||||
}; // end of class BlowUpPuzzle
|
||||
|
||||
|
|
|
@ -82,7 +82,12 @@ void MainMenu::openMenu() {
|
|||
_vm->screen()->setPalette(_resPack, 17);
|
||||
// Copy the bright background to the back buffer
|
||||
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
|
||||
_cursor->load(2);
|
||||
|
@ -90,7 +95,7 @@ void MainMenu::openMenu() {
|
|||
|
||||
// Stop all sounds
|
||||
_vm->sound()->stopMusic();
|
||||
_vm->sound()->stopSfx();
|
||||
_vm->sound()->stopSound();
|
||||
|
||||
// Start playing music
|
||||
_vm->sound()->playMusic(_resPack, 39);
|
||||
|
@ -105,7 +110,7 @@ void MainMenu::closeMenu() {
|
|||
_vm->scene()->activate();
|
||||
|
||||
// Stop menu sounds and menu music
|
||||
_vm->sound()->stopSfx();
|
||||
_vm->sound()->stopSound();
|
||||
_vm->sound()->stopMusic();
|
||||
}
|
||||
|
||||
|
@ -284,8 +289,8 @@ void MainMenu::updateMainMenu() {
|
|||
_text->drawResTextCentered(MenuIconFixedXpos[iconNum], iconFrame->y + 50, _text->getResTextWidth(iconNum + 1309), iconNum + 1309);
|
||||
|
||||
// Play creepy voice
|
||||
if (!_vm->sound()->isSfxActive() && _activeIcon != _previousActiveIcon) {
|
||||
_vm->sound()->playSfx(_resPack, iconNum + 44);
|
||||
if (_activeIcon != _previousActiveIcon) {
|
||||
_vm->sound()->playSound(_resPack, iconNum + 44, _vm->soundVolume());
|
||||
_previousActiveIcon = _activeIcon;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ void ResourcePack::init(const char *resourceFile) {
|
|||
}
|
||||
|
||||
ResourceEntry *ResourcePack::getResource(uint32 resourceId) {
|
||||
uint16 index = resourceId & 0xFFFF;
|
||||
uint16 index = RESIDX(resourceId);
|
||||
if (!_resources[index].data) {
|
||||
// Load the requested resource if it's not loaded already
|
||||
_packFile.seek(_resources[index].offset, SEEK_SET);
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
|
||||
namespace Asylum {
|
||||
|
||||
#define RESID(id) ((id >> 16) & 0x7FFF)
|
||||
#define RESIDX(id) (id & 0XFFFF)
|
||||
|
||||
struct ResourceEntry {
|
||||
byte *data;
|
||||
uint32 size;
|
||||
|
|
|
@ -69,7 +69,6 @@ Scene::Scene(uint8 sceneIdx, AsylumEngine *vm): _vm(vm) {
|
|||
|
||||
_text = new Text(_vm->screen());
|
||||
_resPack = new ResourcePack(sceneIdx);
|
||||
_speechPack = new ResourcePack(3); // FIXME are all scene speech packs the same?
|
||||
|
||||
// FIXME
|
||||
// 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
|
||||
}
|
||||
|
||||
|
@ -150,7 +155,6 @@ Scene::~Scene() {
|
|||
delete _cursor;
|
||||
delete _bgResource;
|
||||
delete _musPack;
|
||||
delete _speechPack;
|
||||
delete _resPack;
|
||||
delete _text;
|
||||
delete _blowUp;
|
||||
|
@ -267,7 +271,7 @@ int Scene::updateScene() {
|
|||
|
||||
// Barriers
|
||||
startTick = _vm->_system->getMillis();
|
||||
updateBarriers();
|
||||
updateBarriers2();
|
||||
debugC(kDebugLevelScene, "UpdateBarriers Time: %d", _vm->_system->getMillis() - startTick);
|
||||
|
||||
// Ambient Sounds
|
||||
|
@ -528,7 +532,38 @@ void Scene::updateActor(uint32 actorIdx) {
|
|||
}
|
||||
}
|
||||
|
||||
// XXX WIP
|
||||
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();
|
||||
|
||||
uint barriersCount = _ws->barriers.size();
|
||||
|
@ -669,6 +704,95 @@ void Scene::updateBarriers() {
|
|||
}
|
||||
|
||||
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() {
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
Cursor* getCursor() { return _cursor; }
|
||||
ResourcePack* getResourcePack() { return _resPack; }
|
||||
ResourcePack* getMusicPack() { return _musPack; }
|
||||
ResourcePack* getSpeechPack() { return _speechPack; }
|
||||
GraphicResource* getGraphicResource(uint32 entry) { return new GraphicResource(_resPack, entry); }
|
||||
BlowUpPuzzle* getBlowUpPuzzle() { return _blowUp; }
|
||||
|
||||
|
@ -110,6 +109,7 @@ private:
|
|||
void updateMouse();
|
||||
void updateActor(uint32 actorIdx);
|
||||
void updateBarriers();
|
||||
void updateBarriers2(); // XXX Alexandre's version
|
||||
void updateAmbientSounds();
|
||||
void updateMusic();
|
||||
void updateAdjustScreen();
|
||||
|
|
|
@ -24,32 +24,240 @@
|
|||
*/
|
||||
|
||||
#include "asylum/sound.h"
|
||||
#include "asylum/asylum.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "sound/audiostream.h"
|
||||
#include "sound/adpcm.h"
|
||||
#include "sound/wave.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
||||
Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer) {
|
||||
_speechPack = new ResourcePack(3);
|
||||
_soundPack = new ResourcePack(18);
|
||||
}
|
||||
|
||||
Sound::~Sound() {
|
||||
delete _speechPack;
|
||||
delete _soundPack;
|
||||
|
||||
clearSoundBuffer();
|
||||
}
|
||||
|
||||
void Sound::playSfx(byte *data, uint32 size) {
|
||||
Common::MemoryReadStream *mem = new Common::MemoryReadStream(data, size);
|
||||
// from engines/agos/sound.cpp
|
||||
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)
|
||||
Audio::AudioStream *sfx = Audio::makeWAVStream(mem, true);
|
||||
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_sfxHandle, sfx);
|
||||
int v = CLIP(vol, -10000, 0);
|
||||
if (v) {
|
||||
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) {
|
||||
Common::MemoryReadStream *mem = new Common::MemoryReadStream(data, size);
|
||||
// from engines/agos/sound.cpp
|
||||
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)
|
||||
Audio::AudioStream *mus = Audio::makeWAVStream(mem, true);
|
||||
_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, mus);
|
||||
int p = CLIP(pan, -10000, 10000);
|
||||
if (p < 0) {
|
||||
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
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define ASYLUM_SOUND_H_
|
||||
|
||||
#include "sound/mixer.h"
|
||||
|
||||
#include "asylum/respack.h"
|
||||
|
||||
namespace Asylum {
|
||||
|
@ -62,35 +63,55 @@ typedef struct AmbientSoundItem {
|
|||
|
||||
} AmbientSoundItem;
|
||||
|
||||
typedef struct SoundBufferItem {
|
||||
uint32 resId;
|
||||
Audio::SoundHandle handle;
|
||||
uint32 unknown;
|
||||
} SoundBufferItem;
|
||||
|
||||
class Sound {
|
||||
public:
|
||||
Sound(Audio::Mixer *mixer);
|
||||
~Sound();
|
||||
|
||||
void playSfx(byte *data, uint32 size);
|
||||
void playSfx(ResourcePack *resPack, uint32 resourceId) {
|
||||
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); }
|
||||
bool addToSoundBuffer(uint resId);
|
||||
void clearSoundBuffer();
|
||||
|
||||
void playMusic(byte *data, uint32 size);
|
||||
void playMusic(ResourcePack *resPack, uint32 resourceId) {
|
||||
ResourceEntry *resEntry = resPack->getResource(resourceId);
|
||||
playMusic(resEntry->data, resEntry->size);
|
||||
}
|
||||
bool isMusicActive() { return _mixer->isSoundHandleActive(_musicHandle); }
|
||||
void pauseMusic() { _mixer->pauseHandle(_musicHandle, true); }
|
||||
void resumeMusic() { _mixer->pauseHandle(_musicHandle, false); }
|
||||
void stopMusic() { _mixer->stopHandle(_musicHandle); }
|
||||
/**
|
||||
* Play a sound resource from the supplied resource pack.
|
||||
*
|
||||
* @param overwrite determine if _soundHandle should be overwritten if still active
|
||||
*/
|
||||
void playSound(ResourcePack *pack, uint resId, int volume, bool looping = false, int panning = 0, bool overwrite = false);
|
||||
void playSound(ResourcePack *pack, uint resId, bool looping, int volume, int panning);
|
||||
void playSound(ResourceEntry *resource, bool looping, int volume, int panning);
|
||||
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:
|
||||
Audio::SoundHandle _sfxHandle;
|
||||
Audio::SoundHandle _musicHandle;
|
||||
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
|
||||
|
|
|
@ -98,6 +98,24 @@ bool WorldStats::isBarrierVisible(uint32 idx) {
|
|||
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
|
||||
void WorldStats::load(Common::SeekableReadStream *stream) {
|
||||
size = stream->readUint32LE();
|
||||
|
|
|
@ -154,7 +154,8 @@ public:
|
|||
|
||||
bool isBarrierOnScreen(uint32 idx);
|
||||
bool isBarrierVisible(uint32 idx);
|
||||
|
||||
// TODO this needs a better name
|
||||
bool checkBarrierFlagsCondition(uint32 idx);
|
||||
private:
|
||||
Scene *_scene;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue