mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 13:50:13 +00:00
NANCY: Implement PlaySoundPanFrameAnchorAndDie action record
Implemented the PlaySoundPanFrameAnchorAndDie action record type and added support for panning audio to the sound manager.
This commit is contained in:
parent
5b58e92270
commit
3013d07e81
@ -516,7 +516,15 @@ void PlayDigiSoundAndDie::execute() {
|
||||
}
|
||||
|
||||
void PlaySoundPanFrameAnchorAndDie::readData(Common::SeekableReadStream &stream) {
|
||||
stream.skip(0x20);
|
||||
_sound.read(stream, SoundDescription::kDIGI);
|
||||
stream.skip(2);
|
||||
}
|
||||
|
||||
void PlaySoundPanFrameAnchorAndDie::execute() {
|
||||
g_nancy->_sound->loadSound(_sound, true);
|
||||
g_nancy->_sound->playSound(_sound);
|
||||
g_nancy->_sound->calculatePanForAllSounds();
|
||||
_isDone = true;
|
||||
}
|
||||
|
||||
void PlaySoundMultiHS::readData(Common::SeekableReadStream &stream) {
|
||||
|
@ -457,10 +457,12 @@ protected:
|
||||
virtual Common::String getRecordTypeName() const override { return "PlayDigiSoundAndDie"; }
|
||||
};
|
||||
|
||||
class PlaySoundPanFrameAnchorAndDie : public Unimplemented {
|
||||
class PlaySoundPanFrameAnchorAndDie : public ActionRecord {
|
||||
public:
|
||||
virtual void readData(Common::SeekableReadStream &stream) override;
|
||||
virtual void execute() override;
|
||||
|
||||
SoundDescription _sound;
|
||||
protected:
|
||||
virtual Common::String getRecordTypeName() const override { return "PlaySoundPanFrameAnchorAndDie"; }
|
||||
};
|
||||
|
@ -97,7 +97,9 @@ void SoundDescription::read(Common::SeekableReadStream &stream, Type type) {
|
||||
}
|
||||
stream.skip(2);
|
||||
volume = stream.readUint16LE();
|
||||
stream.skip(6);
|
||||
stream.skip(2);
|
||||
panAnchorFrame = stream.readUint16LE();
|
||||
stream.skip(2);
|
||||
}
|
||||
|
||||
} // End of namespace Nancy
|
||||
|
@ -118,6 +118,7 @@ struct SoundDescription {
|
||||
uint16 channelID = 0;
|
||||
uint16 numLoops = 0;
|
||||
uint16 volume = 0;
|
||||
uint16 panAnchorFrame = 0;
|
||||
|
||||
void read(Common::SeekableReadStream &stream, Type type);
|
||||
};
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "engines/nancy/nancy.h"
|
||||
#include "engines/nancy/sound.h"
|
||||
|
||||
#include "engines/nancy/state/scene.h"
|
||||
|
||||
namespace Nancy {
|
||||
|
||||
enum SoundType {
|
||||
@ -284,7 +286,7 @@ SoundManager::~SoundManager() {
|
||||
stopAllSounds();
|
||||
}
|
||||
|
||||
void SoundManager::loadSound(const SoundDescription &description) {
|
||||
void SoundManager::loadSound(const SoundDescription &description, bool panning) {
|
||||
if (description.name == "NO SOUND") {
|
||||
return;
|
||||
}
|
||||
@ -293,13 +295,16 @@ void SoundManager::loadSound(const SoundDescription &description) {
|
||||
_mixer->stopHandle(_channels[description.channelID].handle);
|
||||
}
|
||||
|
||||
delete _channels[description.channelID].stream;
|
||||
_channels[description.channelID].stream = nullptr;
|
||||
Channel &chan = _channels[description.channelID];
|
||||
|
||||
_channels[description.channelID].name = description.name;
|
||||
_channels[description.channelID].numLoops = description.numLoops;
|
||||
_channels[description.channelID].volume = description.volume;
|
||||
delete chan.stream;
|
||||
chan.stream = nullptr;
|
||||
|
||||
chan.name = description.name;
|
||||
chan.numLoops = description.numLoops;
|
||||
chan.volume = description.volume;
|
||||
chan.panAnchorFrame = description.panAnchorFrame;
|
||||
chan.isPanning = panning;
|
||||
|
||||
Common::SeekableReadStream *file = SearchMan.createReadStreamForMember(description.name + (g_nancy->getGameType() == kGameTypeVampire ? ".dwd" : ".his"));
|
||||
if (file) {
|
||||
@ -404,6 +409,28 @@ void SoundManager::stopAllSounds() {
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::calculatePanForAllSounds() {
|
||||
uint16 viewportFrameID = NancySceneState.getSceneInfo().frameID;
|
||||
const State::Scene::SceneSummary &sceneSummary = NancySceneState.getSceneSummary();
|
||||
for (uint i = 0; i < 31; ++i) {
|
||||
Channel &chan = _channels[i];
|
||||
if (chan.isPanning) {
|
||||
switch (sceneSummary.totalViewAngle) {
|
||||
case 180:
|
||||
_mixer->setChannelBalance(chan.handle, CLIP<int32>((viewportFrameID - chan.panAnchorFrame) * sceneSummary.soundPanPerFrame * 364, -32768, 32767) / 256);
|
||||
break;
|
||||
case 360:
|
||||
// TODO
|
||||
_mixer->setChannelBalance(chan.handle, 0);
|
||||
break;
|
||||
default:
|
||||
_mixer->setChannelBalance(chan.handle, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::stopAndUnloadSpecificSounds() {
|
||||
// TODO missing if
|
||||
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
void loadCommonSounds();
|
||||
|
||||
// Load a sound into a channel without starting it
|
||||
void loadSound(const SoundDescription &description);
|
||||
void loadSound(const SoundDescription &description, bool panning = false);
|
||||
|
||||
void playSound(uint16 channelID);
|
||||
void playSound(const SoundDescription &description);
|
||||
@ -65,6 +65,8 @@ public:
|
||||
void stopSound(const SoundDescription &description);
|
||||
void stopSound(const Common::String &chunkName);
|
||||
void stopAllSounds();
|
||||
|
||||
void calculatePanForAllSounds();
|
||||
|
||||
// Used when changing scenes
|
||||
void stopAndUnloadSpecificSounds();
|
||||
@ -77,6 +79,8 @@ protected:
|
||||
Audio::Mixer::SoundType type;
|
||||
uint16 numLoops = 0;
|
||||
uint volume = 0;
|
||||
uint16 panAnchorFrame = 0;
|
||||
bool isPanning = false;
|
||||
Audio::SeekableAudioStream *stream = nullptr;
|
||||
Audio::SoundHandle handle;
|
||||
};
|
||||
|
@ -70,8 +70,11 @@ void Scene::SceneSummary::read(Common::SeekableReadStream &stream) {
|
||||
sound.read(stream, SoundDescription::kScene);
|
||||
|
||||
ser.skip(6);
|
||||
ser.syncAsByte(dontWrap);
|
||||
ser.skip(9);
|
||||
ser.syncAsUint16LE(dontWrap);
|
||||
ser.syncAsUint16LE(soundWrapAroundPan);
|
||||
ser.syncAsUint16LE(soundPanPerFrame);
|
||||
ser.syncAsUint16LE(totalViewAngle);
|
||||
ser.syncAsUint16LE(horizontalScrollDelta);
|
||||
ser.syncAsUint16LE(verticalScrollDelta);
|
||||
ser.syncAsUint16LE(horizontalEdgeSize);
|
||||
ser.syncAsUint16LE(verticalEdgeSize);
|
||||
@ -567,6 +570,14 @@ void Scene::run() {
|
||||
// Update the UI elements and handle input
|
||||
NancyInput input = g_nancy->_input->getInput();
|
||||
_viewport.handleInput(input);
|
||||
|
||||
_sceneState.currentScene.verticalOffset = _viewport.getCurVerticalScroll();
|
||||
|
||||
if (_sceneState.currentScene.frameID != _viewport.getCurFrame()) {
|
||||
_sceneState.currentScene.frameID = _viewport.getCurFrame();
|
||||
g_nancy->_sound->calculatePanForAllSounds();
|
||||
}
|
||||
|
||||
_actionManager.handleInput(input);
|
||||
_menuButton->handleInput(input);
|
||||
_helpButton->handleInput(input);
|
||||
@ -585,9 +596,6 @@ void Scene::run() {
|
||||
requestStateChange(NancyState::kHelp);
|
||||
}
|
||||
|
||||
_sceneState.currentScene.frameID = _viewport.getCurFrame();
|
||||
_sceneState.currentScene.verticalOffset = _viewport.getCurVerticalScroll();
|
||||
|
||||
// Handle invisible map button
|
||||
for (uint i = 0; i < ARRAYSIZE(g_nancy->getConstants().mapAccessSceneIDs); ++i) {
|
||||
if (g_nancy->getConstants().mapAccessSceneIDs[i] == -1) {
|
||||
|
@ -95,7 +95,10 @@ public:
|
||||
SoundDescription sound;
|
||||
//
|
||||
NancyFlag dontWrap;
|
||||
//
|
||||
uint16 soundWrapAroundPan;
|
||||
uint16 soundPanPerFrame;
|
||||
uint16 totalViewAngle;
|
||||
uint16 horizontalScrollDelta;
|
||||
uint16 verticalScrollDelta;
|
||||
uint16 horizontalEdgeSize;
|
||||
uint16 verticalEdgeSize;
|
||||
|
Loading…
Reference in New Issue
Block a user