From f2b2fe560f650a941b050084adc2e6d756096f6c Mon Sep 17 00:00:00 2001 From: Nicolay Korslund Date: Mon, 16 Aug 2010 18:06:27 +0200 Subject: [PATCH] Mangle update: Implemented streaming, fixed various bugs. --- apps/openmw/mwsound/soundmanager.cpp | 323 +++++++++++++-------------- libs/mangle | 2 +- libs/openengine | 2 +- 3 files changed, 158 insertions(+), 169 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 03a118edaf..98c62ed465 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -16,7 +16,7 @@ using namespace std; /* Set up the sound manager to use Audiere, FFMPEG or MPG123/libsndfile for input. The OPENMW_USE_x macros are set in CMakeLists.txt. - */ +*/ #ifdef OPENMW_USE_AUDIERE #include #define SOUND_FACTORY OpenAL_Audiere_Factory @@ -36,203 +36,192 @@ using namespace Mangle::Sound; typedef OEngine::Sound::SoundManager OEManager; typedef OEngine::Sound::SoundManagerPtr OEManagerPtr; -/* Set the position on a sound based on a Ptr. TODO: We do not support - tracking moving objects yet, once a sound is started it stays in - the same place until it finishes. - - This obviously has to be fixed at some point for player/npc - footstep sounds and the like. However, updating all sounds each - frame is expensive, so there should be a special flag for sounds - that need to track their attached object. - */ +// Set the position on a sound based on a Ptr. static void setPos(SoundPtr &snd, const MWWorld::Ptr ref) { - // Get sound position from the reference - const float *pos = ref.getCellRef().pos.pos; + // Get sound position from the reference + const float *pos = ref.getCellRef().pos.pos; - // Move the sound, converting from MW coordinates to Ogre - // coordinates. - snd->setPos(pos[0], pos[2], -pos[1]); + // Move the sound, converting from MW coordinates to Ogre + // coordinates. + snd->setPos(pos[0], pos[2], -pos[1]); } namespace MWSound { - struct SoundManager::SoundImpl + struct SoundManager::SoundImpl + { + /* This is the sound manager. It loades, stores and deletes + sounds based on the sound factory it is given. + */ + OEManagerPtr mgr; + + /* This class calls update() on the sound manager each frame + using and Ogre::FrameListener + */ + Mangle::Sound::OgreOutputUpdater updater; + + /* This class tracks the movement of an Ogre::Camera and moves + a sound listener automatically to follow it. + */ + Mangle::Sound::OgreListenerMover cameraTracker; + + const ESMS::ESMStore &store; + std::string dir; + + SoundImpl(Ogre::Root *root, Ogre::Camera *camera, + const ESMS::ESMStore &str, + const std::string &soundDir) + : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) + , updater(mgr) + , cameraTracker(mgr) + , store(str) { - /* This is the sound manager. It loades, stores and deletes - sounds based on the sound factory it is given. - */ - OEManagerPtr mgr; - - /* This class calls update() on the sound manager each frame - using and Ogre::FrameListener - */ - Mangle::Sound::OgreOutputUpdater updater; - - /* This class tracks the movement of an Ogre::Camera and moves - a sound listener automatically to follow it. - */ - Mangle::Sound::OgreListenerMover cameraTracker; - - const ESMS::ESMStore &store; - std::string dir; - - SoundImpl(Ogre::Root *root, Ogre::Camera *camera, - const ESMS::ESMStore &str, - const std::string &soundDir) - : mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) - , updater(mgr) - , cameraTracker(mgr) - , store(str) - { - // Attach the camera to the camera tracker - cameraTracker.followCamera(camera); - - // Tell Ogre to update the sound system each frame - root->addFrameListener(&updater); + // Attach the camera to the camera tracker + cameraTracker.followCamera(camera); - dir = soundDir + "/"; - } + // Tell Ogre to update the sound system each frame + root->addFrameListener(&updater); - // Convert a soundId to file name, and modify the volume - // according to the sounds local volume setting, minRange and - // maxRange. - std::string lookup(const std::string &soundId, - float &volume, float &min, float &max) - { - const ESM::Sound *snd = store.sounds.search(soundId); - if(snd == NULL) return ""; - - volume *= snd->data.volume / 255.0; - // These factors are not very fine tuned. - min = snd->data.minRange * 7; - max = snd->data.maxRange * 2000; - std::string file = dir + snd->sound; - std::replace(file.begin(), file.end(), '\\', '/'); - return file; - } - - // Add a sound to the list and play it - void add(const std::string &file, - MWWorld::Ptr reference, - const std::string &id, - float volume, float pitch, - float min, float max, - bool loop) - { - try - { - SoundPtr snd = mgr->load(file); - snd->setRepeat(loop); - snd->setVolume(volume); - snd->setPitch(pitch); - snd->setRange(min,max); - setPos(snd, reference); - snd->play(); - } - catch(...) - { - cout << "Error loading " << file << ", skipping.\n"; - } - } - - // Stop a sound and remove it from the list. If id="" then - // remove the entire object and stop all its sounds. - void remove(MWWorld::Ptr reference, const std::string &id = "") - { - } - - bool isPlaying(MWWorld::Ptr reference, const std::string &id) const - { - return true; - } - - void removeCell(const MWWorld::Ptr::CellStore *cell) - { - // Note to Nico: You can get the cell of a Ptr via the getCell - // function. Just iterate over all sounds and remove those - // with matching cell. - } - - void updatePositions(MWWorld::Ptr reference) - { - } - }; - - SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, - const ESMS::ESMStore &store, - const std::string &soundDir) - { - mData = new SoundImpl(root, camera, store, soundDir); - } - - SoundManager::~SoundManager() - { - delete mData; - } - - void SoundManager::say (MWWorld::Ptr reference, const std::string& filename) - { - // The range values are not tested - mData->add(filename, reference, "_say_sound", 1, 1, 100, 10000, false); - } - - bool SoundManager::sayDone (MWWorld::Ptr reference) const - { - return !mData->isPlaying(reference, "_say_sound"); + dir = soundDir + "/"; } - void SoundManager::streamMusic (const std::string& filename) + // Convert a soundId to file name, and modify the volume + // according to the sounds local volume setting, minRange and + // maxRange. + std::string lookup(const std::string &soundId, + float &volume, float &min, float &max) { - // Play the sound and tell it to stream, if possible. TODO: - // Store the reference, the jukebox will need to check status, - // control volume etc. - SoundPtr music = mData->mgr->play(filename); - music->setStreaming(true); - music->setVolume(0.4); + const ESM::Sound *snd = store.sounds.search(soundId); + if(snd == NULL) return ""; + + volume *= snd->data.volume / 255.0; + // These factors are not very fine tuned. + min = snd->data.minRange * 7; + max = snd->data.maxRange * 2000; + std::string file = dir + snd->sound; + std::replace(file.begin(), file.end(), '\\', '/'); + return file; } - void SoundManager::playSound (const std::string& soundId, float volume, float pitch) + // Add a sound to the list and play it + void add(const std::string &file, + MWWorld::Ptr ptr, + const std::string &id, + float volume, float pitch, + float min, float max, + bool loop) { - // Play and forget - float min, max; - const std::string &file = mData->lookup(soundId, volume, min, max); - if(file != "") + try { - SoundPtr snd = mData->mgr->play(file); + SoundPtr snd = mgr->load(file); + snd->setRepeat(loop); snd->setVolume(volume); - snd->setRange(min,max); snd->setPitch(pitch); + snd->setRange(min,max); + setPos(snd, ptr); + snd->play(); + } + catch(...) + { + cout << "Error loading " << file << ", skipping.\n"; } } - void SoundManager::playSound3D (MWWorld::Ptr reference, const std::string& soundId, - float volume, float pitch, bool loop) - { - // Look up the sound in the ESM data - float min, max; - const std::string &file = mData->lookup(soundId, volume, min, max); - if(file != "") - mData->add(file, reference, soundId, volume, pitch, min, max, loop); - } - - void SoundManager::stopSound3D (MWWorld::Ptr reference, const std::string& soundId) + // Stop a sound and remove it from the list. If id="" then + // remove the entire object and stop all its sounds. + void remove(MWWorld::Ptr ptr, const std::string &id = "") { - mData->remove(reference, soundId); } - void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) + bool isPlaying(MWWorld::Ptr ptr, const std::string &id) const { - mData->removeCell(cell); + return true; } - bool SoundManager::getSoundPlaying (MWWorld::Ptr reference, const std::string& soundId) const + void removeCell(const MWWorld::Ptr::CellStore *cell) { - return mData->isPlaying(reference, soundId); } - void SoundManager::updateObject(MWWorld::Ptr reference) + void updatePositions(MWWorld::Ptr ptr) { - mData->updatePositions(reference); } + }; + + SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera, + const ESMS::ESMStore &store, + const std::string &soundDir) + { + mData = new SoundImpl(root, camera, store, soundDir); + } + + SoundManager::~SoundManager() + { + delete mData; + } + + void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) + { + // The range values are not tested + mData->add(filename, ptr, "_say_sound", 1, 1, 100, 10000, false); + } + + bool SoundManager::sayDone (MWWorld::Ptr ptr) const + { + return !mData->isPlaying(ptr, "_say_sound"); + } + + void SoundManager::streamMusic (const std::string& filename) + { + // Play the sound and tell it to stream, if possible. TODO: + // Store the reference, the jukebox will need to check status, + // control volume etc. + SoundPtr music = mData->mgr->play(filename); + music->setStreaming(true); + music->setVolume(0.4); + } + + void SoundManager::playSound (const std::string& soundId, float volume, float pitch) + { + // Play and forget + float min, max; + const std::string &file = mData->lookup(soundId, volume, min, max); + if(file != "") + { + SoundPtr snd = mData->mgr->play(file); + snd->setVolume(volume); + snd->setRange(min,max); + snd->setPitch(pitch); + } + } + + void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, + float volume, float pitch, bool loop) + { + // Look up the sound in the ESM data + float min, max; + const std::string &file = mData->lookup(soundId, volume, min, max); + if(file != "") + mData->add(file, ptr, soundId, volume, pitch, min, max, loop); + } + + void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId) + { + mData->remove(ptr, soundId); + } + + void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) + { + mData->removeCell(cell); + } + + bool SoundManager::getSoundPlaying (MWWorld::Ptr ptr, const std::string& soundId) const + { + return mData->isPlaying(ptr, soundId); + } + + void SoundManager::updateObject(MWWorld::Ptr ptr) + { + mData->updatePositions(ptr); + } } diff --git a/libs/mangle b/libs/mangle index c982f701ca..cd4ed4e6bf 160000 --- a/libs/mangle +++ b/libs/mangle @@ -1 +1 @@ -Subproject commit c982f701cacdd2932bfdc22b168f54221a549b62 +Subproject commit cd4ed4e6bfb23d736c4b1f30d6096ec164ba937b diff --git a/libs/openengine b/libs/openengine index b9d4dc448b..2e2f8e9725 160000 --- a/libs/openengine +++ b/libs/openengine @@ -1 +1 @@ -Subproject commit b9d4dc448bc3be908653f9dea3c3450fb85ed107 +Subproject commit 2e2f8e9725fd1a27a82d0ad5c6c0e296e715eb60