diff --git a/CMakeLists.txt b/CMakeLists.txt index 6dbd27a68c..d06085322a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -120,10 +120,6 @@ set(OENGINE_BULLET # Sound setup if (USE_AUDIERE) - set(MANGLE_SOUND_OUTPUT - ${LIBDIR}/mangle/sound/sources/audiere_source.cpp - ${LIBDIR}/mangle/sound/sources/sample_reader.cpp - ${LIBDIR}/mangle/stream/clients/audiere_file.cpp) find_package(Audiere REQUIRED) set(SOUND_INPUT_INCLUDES ${AUDIERE_INCLUDE_DIR}) set(SOUND_INPUT_LIBRARY ${AUDIERE_LIBRARY}) @@ -131,8 +127,6 @@ if (USE_AUDIERE) endif (USE_AUDIERE) if (USE_FFMPEG) - set(MANGLE_SOUND_OUTPUT - ${LIBDIR}/mangle/sound/sources/ffmpeg_source.cpp) find_package(FFMPEG REQUIRED) set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIR}) set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) @@ -140,10 +134,6 @@ if (USE_FFMPEG) endif (USE_FFMPEG) if (USE_MPG123) - set(MANGLE_SOUND_OUTPUT - ${LIBDIR}/mangle/sound/sources/mpg123_source.cpp - ${LIBDIR}/mangle/sound/sources/libsndfile.cpp - ${LIBDIR}/mangle/sound/sources/sample_reader.cpp) find_package(MPG123 REQUIRED) find_package(SNDFILE REQUIRED) set(SOUND_INPUT_INCLUDES ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR}) @@ -151,14 +141,7 @@ if (USE_MPG123) set(SOUND_DEFINE -DOPENMW_USE_MPG123) endif (USE_MPG123) -set(OENGINE_SOUND - # Mangle and OEngine sound files are sort of intertwined, so put - # them together here - ${LIBDIR}/openengine/sound/sndmanager.cpp - ${LIBDIR}/mangle/sound/outputs/openal_out.cpp - ${MANGLE_SOUND_OUTPUT} -) -set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_SOUND} ${OENGINE_BULLET}) +set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET}) source_group(libs\\openengine FILES ${OENGINE_ALL}) set(OPENMW_LIBS ${MANGLE_ALL} ${OENGINE_ALL}) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index a5ba04e261..e0d7167de8 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -6,10 +6,6 @@ #include -#include -#include -#include - #include #include "../mwworld/environment.hpp" @@ -21,39 +17,23 @@ CMakeLists.txt. */ #ifdef OPENMW_USE_AUDIERE -#include #define SOUND_FACTORY OpenAL_Audiere_Factory #define SOUND_OUT "OpenAL" #define SOUND_IN "Audiere" #endif #ifdef OPENMW_USE_FFMPEG -#include #define SOUND_FACTORY OpenAL_FFMpeg_Factory #define SOUND_OUT "OpenAL" #define SOUND_IN "FFmpeg" #endif #ifdef OPENMW_USE_MPG123 -#include #define SOUND_FACTORY OpenAL_SndFile_Mpg123_Factory #define SOUND_OUT "OpenAL" #define SOUND_IN "mpg123,sndfile" #endif -using namespace Mangle::Sound; -typedef OEngine::Sound::SoundManager OEManager; - -// 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; - - // Move the sound, converting from MW coordinates to Ogre - // coordinates. - snd->setPos(pos[0], pos[2], -pos[1]); -} namespace MWSound { @@ -63,50 +43,36 @@ namespace MWSound bool useSound, bool fsstrict, MWWorld::Environment& environment) : mFSStrict(fsstrict) , mEnvironment(environment) - , mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY))) - , updater(mgr) - , cameraTracker(mgr) , mCurrentPlaylist(NULL) { - if(useSound) - { - // The music library will accept these filetypes - // If none is given then it will accept all filetypes - std::vector acceptableExtensions; - acceptableExtensions.push_back(".mp3"); - acceptableExtensions.push_back(".wav"); - acceptableExtensions.push_back(".ogg"); - acceptableExtensions.push_back(".flac"); + if(!useSound) + return; - // Makes a list of all sound files, searches in reverse for priority reasons - for (Files::PathContainer::const_reverse_iterator it = dataDirs.rbegin(); it != dataDirs.rend(); ++it) - { - Files::FileLister(*it / std::string("Sound"), mSoundFiles, true); - } + // The music library will accept these filetypes + // If none is given then it will accept all filetypes + std::vector acceptableExtensions; + acceptableExtensions.push_back(".mp3"); + acceptableExtensions.push_back(".wav"); + acceptableExtensions.push_back(".ogg"); + acceptableExtensions.push_back(".flac"); - // Makes a FileLibrary of all music files, searches in reverse for priority reasons - for (Files::PathContainer::const_reverse_iterator it = dataDirs.rbegin(); it != dataDirs.rend(); ++it) - { - mMusicLibrary.add(*it / std::string("Music"), true, mFSStrict, acceptableExtensions); - } + // Makes a list of all sound files, searches in reverse for priority reasons + for(Files::PathContainer::const_reverse_iterator it = dataDirs.rbegin(); it != dataDirs.rend(); ++it) + Files::FileLister(*it / std::string("Sound"), mSoundFiles, true); - std::string anything = "anything"; // anything is better that a segfault - mCurrentPlaylist = mMusicLibrary.section(anything, mFSStrict); // now points to an empty path + // Makes a FileLibrary of all music files, searches in reverse for priority reasons + for(Files::PathContainer::const_reverse_iterator it = dataDirs.rbegin(); it != dataDirs.rend(); ++it) + mMusicLibrary.add(*it / std::string("Music"), true, mFSStrict, acceptableExtensions); - std::cout << "Sound output: " << SOUND_OUT << std::endl; - std::cout << "Sound decoder: " << SOUND_IN << std::endl; - // Attach the camera to the camera tracker - cameraTracker.followCamera(camera); + std::string anything = "anything"; // anything is better that a segfault + mCurrentPlaylist = mMusicLibrary.section(anything, mFSStrict); // now points to an empty path - // Tell Ogre to update the sound system each frame - root->addFrameListener(&updater); - } - } + std::cout << "Sound output: " << SOUND_OUT << std::endl; + std::cout << "Sound decoder: " << SOUND_IN << std::endl; + } SoundManager::~SoundManager() { - Ogre::Root::getSingleton().removeFrameListener(&updater); - cameraTracker.unfollowCamera(); } // Convert a soundId to file name, and modify the volume @@ -115,28 +81,28 @@ namespace MWSound std::string SoundManager::lookup(const std::string &soundId, float &volume, float &min, float &max) { - const ESM::Sound *snd = mEnvironment.mWorld->getStore().sounds.search(soundId); - if(snd == NULL) return ""; + const ESM::Sound *snd = mEnvironment.mWorld->getStore().sounds.search(soundId); + if(snd == NULL) return ""; - if(snd->data.volume == 0) - volume = 0.0f; - else - volume *= pow(10.0, (snd->data.volume/255.0f*3348.0 - 3348.0) / 2000.0); + if(snd->data.volume == 0) + volume = 0.0f; + else + volume *= pow(10.0, (snd->data.volume/255.0f*3348.0 - 3348.0) / 2000.0); - if(snd->data.minRange == 0 && snd->data.maxRange == 0) - { - min = 100.0f; - max = 2000.0f; - } - else - { - min = snd->data.minRange * 20.0f; - max = snd->data.maxRange * 50.0f; - min = std::max(min, 1.0f); - max = std::max(min, max); - } + if(snd->data.minRange == 0 && snd->data.maxRange == 0) + { + min = 100.0f; + max = 2000.0f; + } + else + { + min = snd->data.minRange * 20.0f; + max = snd->data.maxRange * 50.0f; + min = std::max(min, 1.0f); + max = std::max(min, max); + } - return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict, false); + return Files::FileListLocator(mSoundFiles, snd->sound, mFSStrict, false); } // Add a sound to the list and play it @@ -147,190 +113,79 @@ namespace MWSound float min, float max, bool loop, bool untracked) { - try - { - SoundPtr snd = mgr->load(file); - snd->setRepeat(loop); - snd->setVolume(volume); - snd->setPitch(pitch); - snd->setRange(min,max); - setPos(snd, ptr); - snd->play(); - - if (!untracked) - { - sounds[ptr][id] = WSoundPtr(snd); - } - } - catch(...) - { - std::cout << "Error loading " << file << ", skipping.\n"; - } - } - - // Clears all the sub-elements of a given iterator, and then - // removes it from 'sounds'. - void SoundManager::clearAll(PtrMap::iterator& it) - { - IDMap::iterator sit = it->second.begin(); - - while(sit != it->second.end()) - { - // Get sound pointer, if any - SoundPtr snd = sit->second.lock(); - - // Stop the sound - if(snd) snd->stop(); - - sit++; - } - - // Remove the ptr reference - sounds.erase(it); + //std::cout << "Cannot load " << 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 SoundManager::remove(MWWorld::Ptr ptr, const std::string &id) { - PtrMap::iterator it = sounds.find(ptr); - if(it != sounds.end()) - { - if(id == "") - // Kill all references to 'ptr' - clearAll(it); - else - { - // Only find the id we're looking for - IDMap::iterator it2 = it->second.find(id); - if(it2 != it->second.end()) - { - // Stop the sound and remove it from the list - SoundPtr snd = it2->second.lock(); - if(snd) snd->stop(); - it->second.erase(it2); - } - } - } } bool SoundManager::isPlaying(MWWorld::Ptr ptr, const std::string &id) const { - PtrMap::const_iterator it = sounds.find(ptr); - if(it != sounds.end()) - { - IDMap::const_iterator it2 = it->second.find(id); - if(it2 != it->second.end()) - { - // Get a shared_ptr from the weak_ptr - SoundPtr snd = it2->second.lock();; - - // Is it still alive? - if(snd) - { - // Then return its status! - return snd->isPlaying(); - } - } - } - // Nothing found, sound is not playing - return false; + // HACK: Return true to prevent the engine from trying to keep playing + // sounds and tanking the framerate. + return true; } // Remove all references to objects belonging to a given cell void SoundManager::removeCell(const MWWorld::Ptr::CellStore *cell) { - PtrMap::iterator it2, it = sounds.begin(); - while(it != sounds.end()) - { - // Make sure to increase the iterator before we erase it. - it2 = it++; - if(it2->first.getCell() == cell) - clearAll(it2); - } } void SoundManager::updatePositions(MWWorld::Ptr ptr) { - // Find the reference (if any) - PtrMap::iterator it = sounds.find(ptr); - if(it != sounds.end()) - { - // Then find all sounds in it (if any) - IDMap::iterator it2 = it->second.begin(); - for(;it2 != it->second.end(); it2++) - { - // Get the sound (if it still exists) - SoundPtr snd = it2->second.lock(); - if(snd) - // Update position - setPos(snd, ptr); - } - } } void SoundManager::stopMusic() { - if (music) - music->stop(); setPlaylist(); } - void SoundManager::streamMusicFull(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. - if (music) - music->stop(); - music = mgr->load(filename); - music->setStreaming(true); - music->setVolume(0.4); - music->play(); - - } + void SoundManager::streamMusicFull(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. + } void SoundManager::streamMusic(const std::string& filename) { std::string filePath = mMusicLibrary.locate(filename, mFSStrict, true).string(); if(!filePath.empty()) - { streamMusicFull(filePath); - } } - void SoundManager::startRandomTitle() - { - if(mCurrentPlaylist && !mCurrentPlaylist->empty()) + void SoundManager::startRandomTitle() { - Files::PathContainer::const_iterator fileIter = mCurrentPlaylist->begin(); - srand( time(NULL) ); - int r = rand() % mCurrentPlaylist->size() + 1; //old random code - - std::advance(fileIter, r - 1); - std::string music = fileIter->string(); - std::cout << "Playing " << music << "\n"; - - try + if(mCurrentPlaylist && !mCurrentPlaylist->empty()) { - streamMusicFull(music); - } - catch (std::exception &e) - { - std::cout << " Music Error: " << e.what() << "\n"; + Files::PathContainer::const_iterator fileIter = mCurrentPlaylist->begin(); + srand( time(NULL) ); + int r = rand() % mCurrentPlaylist->size() + 1; //old random code + + std::advance(fileIter, r - 1); + std::string music = fileIter->string(); + //std::cout << "Playing " << music << "\n"; + + try + { + streamMusicFull(music); + } + catch (std::exception &e) + { + std::cout << "Music Error: " << e.what() << "\n"; + } } } - } bool SoundManager::isMusicPlaying() { - bool test = false; - if(music) - { - test = music->isPlaying(); - } - return test; + // HACK: Return true to prevent the engine from trying to keep playing + // music and tanking the framerate. + return true; } bool SoundManager::setPlaylist(std::string playlist) @@ -373,154 +228,122 @@ namespace MWSound } } - void SoundManager::say (MWWorld::Ptr ptr, const std::string& filename) - { - // The range values are not tested - std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true); - if(!filePath.empty()) - add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false); - else - std::cout << "Sound file " << filename << " not found, skipping.\n"; - } - - bool SoundManager::sayDone (MWWorld::Ptr ptr) const - { - return !isPlaying(ptr, "_say_sound"); - } - - - void SoundManager::playSound(const std::string& soundId, float volume, float pitch, bool loop) - { - float min, max; - const std::string &file = lookup(soundId, volume, min, max); - if (file != "") + void SoundManager::say(MWWorld::Ptr ptr, const std::string& filename) { - SoundPtr snd = mgr->load(file); - snd->setRepeat(loop); - snd->setVolume(volume); - snd->setRange(min,max); - snd->setPitch(pitch); - snd->setRelative(true); - snd->play(); - - if (loop) - { - // Only add the looping sound once - IDMap::iterator it = mLoopedSounds.find(soundId); - if(it == mLoopedSounds.end()) - { - mLoopedSounds[soundId] = WSoundPtr(snd); - } - } + // The range values are not tested + std::string filePath = Files::FileListLocator(mSoundFiles, filename, mFSStrict, true); + if(!filePath.empty()) + add(filePath, ptr, "_say_sound", 1, 1, 100, 20000, false); + else + std::cout << "Sound file " << filename << " not found, skipping.\n"; } - } - void SoundManager::playSound3D (MWWorld::Ptr ptr, const std::string& soundId, - float volume, float pitch, bool loop, bool untracked) - { - // Look up the sound in the ESM data - float min, max; - const std::string &file = lookup(soundId, volume, min, max); - if (file != "") - add(file, ptr, soundId, volume, pitch, min, max, loop, untracked); - } + bool SoundManager::sayDone(MWWorld::Ptr ptr) const + { + return !isPlaying(ptr, "_say_sound"); + } - void SoundManager::stopSound3D (MWWorld::Ptr ptr, const std::string& soundId) - { - remove(ptr, soundId); - } - void SoundManager::stopSound (MWWorld::Ptr::CellStore *cell) - { - removeCell(cell); - } + void SoundManager::playSound(const std::string& soundId, float volume, float pitch, bool loop) + { + float min, max; + const std::string &file = lookup(soundId, volume, min, max); + std::cout << "Cannot play " << file << ", skipping.\n"; + } + + void SoundManager::playSound3D(MWWorld::Ptr ptr, const std::string& soundId, + float volume, float pitch, bool loop, bool untracked) + { + // Look up the sound in the ESM data + float min, max; + const std::string &file = lookup(soundId, volume, min, max); + if(file != "") + add(file, ptr, soundId, volume, pitch, min, max, loop, untracked); + } + + void SoundManager::stopSound3D(MWWorld::Ptr ptr, const std::string& soundId) + { + remove(ptr, soundId); + } + + void SoundManager::stopSound(MWWorld::Ptr::CellStore *cell) + { + removeCell(cell); + } void SoundManager::stopSound(const std::string& soundId) { - IDMap::iterator it = mLoopedSounds.find(soundId); - if(it != mLoopedSounds.end()) - { - SoundPtr snd = it->second.lock(); - if(snd) snd->stop(); - mLoopedSounds.erase(it); - } } - bool SoundManager::getSoundPlaying (MWWorld::Ptr ptr, const std::string& soundId) const - { - // Mark all sounds as playing, otherwise the scripts will just - // keep trying to play them every frame. + bool SoundManager::getSoundPlaying(MWWorld::Ptr ptr, const std::string& soundId) const + { + // Mark all sounds as playing, otherwise the scripts will just + // keep trying to play them every frame. - return isPlaying(ptr, soundId); - } + return isPlaying(ptr, soundId); + } - void SoundManager::updateObject(MWWorld::Ptr ptr) - { - updatePositions(ptr); - } + void SoundManager::updateObject(MWWorld::Ptr ptr) + { + updatePositions(ptr); + } - void SoundManager::update (float duration) - { + void SoundManager::update(float duration) + { MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); static int total = 0; static std::string regionName = ""; static float timePassed = 0.0; - timePassed += duration; //If the region has changed - if(!(current->cell->data.flags & current->cell->Interior) && timePassed >= 10) + timePassed += duration; + if((current->cell->data.flags & current->cell->Interior) || timePassed < 10) + return; + + ESM::Region test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); + + timePassed = 0; + if(regionName != current->cell->region) { - - ESM::Region test = (ESM::Region) *(mEnvironment.mWorld->getStore().regions.find(current->cell->region)); - - timePassed = 0; - if (regionName != current->cell->region) - { - regionName = current->cell->region; - total = 0; - } - - if(test.soundList.size() > 0) - { - std::vector::iterator soundIter = test.soundList.begin(); - //mEnvironment.mSoundManager - if(total == 0) - { - while (soundIter != test.soundList.end()) - { - int chance = (int) soundIter->chance; - //ESM::NAME32 go = soundIter->sound; - //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - soundIter++; - total += chance; - } - } - - int r = rand() % total; //old random code - int pos = 0; - soundIter = test.soundList.begin(); - while (soundIter != test.soundList.end()) - { - const std::string go = soundIter->sound.toString(); - int chance = (int) soundIter->chance; - //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; - soundIter++; - if( r - pos < chance) - { - //play sound - std::cout << "Sound: " << go <<" Chance:" << chance << "\n"; - mEnvironment.mSoundManager->playSound(go, 20.0, 1.0); - - break; - } - pos += chance; - } - } - } - else if(current->cell->data.flags & current->cell->Interior) - { - regionName = ""; + regionName = current->cell->region; + total = 0; } - } + if(test.soundList.size() == 0) + return; + + std::vector::iterator soundIter; + if(total == 0) + { + soundIter = test.soundList.begin(); + while(soundIter != test.soundList.end()) + { + int chance = (int) soundIter->chance; + //ESM::NAME32 go = soundIter->sound; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + total += chance; + } + } + + int r = rand() % total; //old random code + int pos = 0; + + soundIter = test.soundList.begin(); + while(soundIter != test.soundList.end()) + { + const std::string go = soundIter->sound.toString(); + int chance = (int) soundIter->chance; + //std::cout << "Sound: " << go.name <<" Chance:" << chance << "\n"; + soundIter++; + if(r - pos < chance) + { + //play sound + std::cout << "Sound: " << go <<" Chance:" << chance << "\n"; + playSound(go, 20.0, 1.0); + break; + } + pos += chance; + } + } } diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index bd3b676797..9db7fe1b70 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -3,11 +3,6 @@ #include -#include -#include - -#include - #include #include "../mwworld/ptr.hpp" @@ -19,16 +14,6 @@ namespace Ogre class Camera; } -namespace Mangle -{ - namespace Sound - { - typedef boost::shared_ptr SoundPtr; - } -} - -typedef OEngine::Sound::SoundManagerPtr OEManagerPtr; - namespace MWWorld { struct Environment; @@ -51,26 +36,6 @@ namespace MWSound ///< Play a soundifle /// \param absolute filename - /* This is the sound manager. It loades, stores and deletes - sounds based on the sound factory it is given. - */ - OEManagerPtr mgr; - Mangle::Sound::SoundPtr music; - - /* 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; - - typedef std::map IDMap; - typedef std::map PtrMap; - PtrMap sounds; - // A list of all sound files used to lookup paths Files::PathContainer mSoundFiles; @@ -80,15 +45,12 @@ namespace MWSound // Points to the current playlist of music files stored in the music library const Files::PathContainer* mCurrentPlaylist; - IDMap mLoopedSounds; - std::string lookup(const std::string &soundId, float &volume, float &min, float &max); void add(const std::string &file, MWWorld::Ptr ptr, const std::string &id, float volume, float pitch, float min, float max, bool loop, bool untracked=false); - void clearAll(PtrMap::iterator& it); void remove(MWWorld::Ptr ptr, const std::string &id = ""); bool isPlaying(MWWorld::Ptr ptr, const std::string &id) const; void removeCell(const MWWorld::Ptr::CellStore *cell); diff --git a/libs/mangle/sound/.gitignore b/libs/mangle/sound/.gitignore deleted file mode 100644 index 8b13789179..0000000000 --- a/libs/mangle/sound/.gitignore +++ /dev/null @@ -1 +0,0 @@ - diff --git a/libs/mangle/sound/clients/ogre_listener_mover.hpp b/libs/mangle/sound/clients/ogre_listener_mover.hpp deleted file mode 100644 index 74c21db32a..0000000000 --- a/libs/mangle/sound/clients/ogre_listener_mover.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef MANGLE_SOUND_OGRELISTENERMOVER_H -#define MANGLE_SOUND_OGRELISTENERMOVER_H - -#include -#include -#include "../output.hpp" - -namespace Mangle { -namespace Sound { - - /** This class lets a sound listener (ie. the SoundFactory) track a - given camera in Ogre3D. The position and orientation of the - listener will be updated to match the camera whenever the camera - is moved. - */ - struct OgreListenerMover : Ogre::Camera::Listener - { - OgreListenerMover(Mangle::Sound::SoundFactoryPtr snd) - : soundFact(snd), camera(NULL) - {} - - /// Follow a camera. WARNING: This will OVERRIDE any other - /// MovableObject::Listener you may have attached to the camera. - void followCamera(Ogre::Camera *cam) - { - camera = cam; - camera->addListener(this); - } - - void unfollowCamera() - { - // If the camera is null, this object wasn't following a camera. - // It doesn't make sense to call unfollow - assert(camera != NULL); - - camera->removeListener(this); - camera = NULL; - } - - private: - Mangle::Sound::SoundFactoryPtr soundFact; - Ogre::Camera *camera; - Ogre::Vector3 pos, dir, up; - - /// From Camera::Listener. This is called once per - /// frame. Unfortunately, Ogre doesn't allow us to be notified - /// only when the camera itself has moved, so we must poll every - /// frame. - void cameraPreRenderScene(Ogre::Camera *cam) - { - assert(cam == camera); - - Ogre::Vector3 nPos, nDir, nUp; - - nPos = camera->getRealPosition(); - nDir = camera->getRealDirection(); - nUp = camera->getRealUp(); - - // Don't bother the sound system needlessly - if(nDir != dir || nPos != pos || nUp != up) - { - pos = nPos; - dir = nDir; - up = nUp; - - soundFact->setListenerPos(pos.x, pos.y, pos.z, - dir.x, dir.y, dir.z, - up.x, up.y, up.z); - } - } - - void cameraDestroyed(Ogre::Camera *cam) - { - assert(cam == camera); - camera = NULL; - } - }; -}} -#endif diff --git a/libs/mangle/sound/clients/ogre_output_updater.hpp b/libs/mangle/sound/clients/ogre_output_updater.hpp deleted file mode 100644 index b73168c759..0000000000 --- a/libs/mangle/sound/clients/ogre_output_updater.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef MANGLE_SOUND_OGREUPDATER_H -#define MANGLE_SOUND_OGREUPDATER_H - -/* - This Ogre FrameListener calls update on a SoundFactory - */ - -#include -#include "../output.hpp" -#include - -namespace Mangle { -namespace Sound { - - struct OgreOutputUpdater : Ogre::FrameListener - { - Mangle::Sound::SoundFactoryPtr driver; - - OgreOutputUpdater(Mangle::Sound::SoundFactoryPtr drv) - : driver(drv) - { assert(drv->needsUpdate); } - - bool frameStarted(const Ogre::FrameEvent &evt) - { - driver->update(); - return true; - } - }; -}} - -#endif diff --git a/libs/mangle/sound/filters/input_filter.hpp b/libs/mangle/sound/filters/input_filter.hpp deleted file mode 100644 index 00ee187660..0000000000 --- a/libs/mangle/sound/filters/input_filter.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef MANGLE_INPUT_FILTER_H -#define MANGLE_INPUT_FILTER_H - -#include "../output.hpp" - -#include - -namespace Mangle { -namespace Sound { - -/** - @brief This filter class adds file loading capabilities to a - Sound::SoundFactory class, by associating a SampleSourceLoader with - it. - - The class takes an existing SoundFactory able to load streams, and - associates a SampleSourceLoader with it. The combined class is able - to load files directly. */ -class InputFilter : public SoundFactory -{ - protected: - SoundFactoryPtr snd; - SampleSourceLoaderPtr inp; - - public: - /// Empty constructor - InputFilter() {} - - /// Assign an input manager and a sound manager to this object - InputFilter(SoundFactoryPtr _snd, SampleSourceLoaderPtr _inp) - { set(_snd, _inp); } - - /// Assign an input manager and a sound manager to this object - void set(SoundFactoryPtr _snd, SampleSourceLoaderPtr _inp) - { - inp = _inp; - snd = _snd; - - // Set capabilities - needsUpdate = snd->needsUpdate; - has3D = snd->has3D; - canLoadStream = inp->canLoadStream; - - // Both these should be true, or the use of this class is pretty - // pointless - canLoadSource = snd->canLoadSource; - canLoadFile = inp->canLoadFile; - assert(canLoadSource && canLoadFile); - } - - virtual SoundPtr load(const std::string &file) - { return loadRaw(inp->load(file)); } - - virtual SoundPtr load(Stream::StreamPtr input) - { return loadRaw(inp->load(input)); } - - virtual SoundPtr loadRaw(SampleSourcePtr input) - { return snd->loadRaw(input); } - - virtual void update() { snd->update(); } - virtual void setListenerPos(float x, float y, float z, - float fx, float fy, float fz, - float ux, float uy, float uz) - { snd->setListenerPos(x,y,z,fx,fy,fz,ux,uy,uz); } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/openal_audiere.hpp b/libs/mangle/sound/filters/openal_audiere.hpp deleted file mode 100644 index 5b9b518249..0000000000 --- a/libs/mangle/sound/filters/openal_audiere.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MANGLE_AUDIERE_OPENAL_H -#define MANGLE_AUDIERE_OPENAL_H - -#include "input_filter.hpp" -#include "../sources/audiere_source.hpp" -#include "../outputs/openal_out.hpp" - -namespace Mangle { -namespace Sound { - -/// A InputFilter that adds audiere decoding to OpenAL. Audiere has -/// it's own output, but OpenAL sports 3D and other advanced features. -class OpenAL_Audiere_Factory : public InputFilter -{ - public: - OpenAL_Audiere_Factory() - { - set(SoundFactoryPtr(new OpenAL_Factory), - SampleSourceLoaderPtr(new AudiereLoader)); - } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/openal_ffmpeg.hpp b/libs/mangle/sound/filters/openal_ffmpeg.hpp deleted file mode 100644 index 42c76af0cd..0000000000 --- a/libs/mangle/sound/filters/openal_ffmpeg.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MANGLE_FFMPEG_OPENAL_H -#define MANGLE_FFMPEG_OPENAL_H - -#include "input_filter.hpp" -#include "../sources/ffmpeg_source.hpp" -#include "../outputs/openal_out.hpp" - -namespace Mangle { -namespace Sound { - -/// A InputFilter that adds ffmpeg decoding to OpenAL. -class OpenAL_FFMpeg_Factory : public InputFilter -{ - public: - OpenAL_FFMpeg_Factory() - { - set(SoundFactoryPtr(new OpenAL_Factory), - SampleSourceLoaderPtr(new FFMpegLoader)); - } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/openal_mpg123.hpp b/libs/mangle/sound/filters/openal_mpg123.hpp deleted file mode 100644 index bfd926c0bb..0000000000 --- a/libs/mangle/sound/filters/openal_mpg123.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MANGLE_MPG123_OPENAL_H -#define MANGLE_MPG123_OPENAL_H - -#include "input_filter.hpp" -#include "../sources/mpg123_source.hpp" -#include "../outputs/openal_out.hpp" - -namespace Mangle { -namespace Sound { - -/// A InputFilter that adds mpg123 decoding to OpenAL. Only supports -/// MP3 files. -class OpenAL_Mpg123_Factory : public InputFilter -{ - public: - OpenAL_Mpg123_Factory() - { - set(SoundFactoryPtr(new OpenAL_Factory), - SampleSourceLoaderPtr(new Mpg123Loader)); - } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/openal_sndfile.hpp b/libs/mangle/sound/filters/openal_sndfile.hpp deleted file mode 100644 index fd7e780259..0000000000 --- a/libs/mangle/sound/filters/openal_sndfile.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef MANGLE_SNDFILE_OPENAL_H -#define MANGLE_SNDFILE_OPENAL_H - -#include "input_filter.hpp" -#include "../sources/libsndfile.hpp" -#include "../outputs/openal_out.hpp" - -namespace Mangle { -namespace Sound { - -/// A InputFilter that adds libsnd decoding to OpenAL. libsndfile -/// supports most formats except MP3. -class OpenAL_SndFile_Factory : public InputFilter -{ - public: - OpenAL_SndFile_Factory() - { - set(SoundFactoryPtr(new OpenAL_Factory), - SampleSourceLoaderPtr(new SndFileLoader)); - } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/openal_sndfile_mpg123.hpp b/libs/mangle/sound/filters/openal_sndfile_mpg123.hpp deleted file mode 100644 index 6e5db4d0e1..0000000000 --- a/libs/mangle/sound/filters/openal_sndfile_mpg123.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MANGLE_SNDFILE_MPG123_OPENAL_H -#define MANGLE_SNDFILE_MPG123_OPENAL_H - -#include "input_filter.hpp" -#include "source_splicer.hpp" -#include "../sources/mpg123_source.hpp" -#include "../sources/libsndfile.hpp" -#include "../outputs/openal_out.hpp" - -namespace Mangle { -namespace Sound { - -/// A InputFilter that uses OpenAL for output, and mpg123 (for MP3) + -/// libsndfile (for everything else) to decode files. Can only load -/// from the file system, and uses the file name to differentiate -/// between mp3 and non-mp3 types. -class OpenAL_SndFile_Mpg123_Factory : public InputFilter -{ - public: - OpenAL_SndFile_Mpg123_Factory() - { - SourceSplicer *splice = new SourceSplicer; - - splice->add("mp3", SampleSourceLoaderPtr(new Mpg123Loader)); - splice->setDefault(SampleSourceLoaderPtr(new SndFileLoader)); - - set(SoundFactoryPtr(new OpenAL_Factory), - SampleSourceLoaderPtr(splice)); - } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/openal_various.hpp b/libs/mangle/sound/filters/openal_various.hpp deleted file mode 100644 index 945b3dabda..0000000000 --- a/libs/mangle/sound/filters/openal_various.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef MANGLE_VARIOUS_OPENAL_H -#define MANGLE_VARIOUS_OPENAL_H - -#include "input_filter.hpp" -#include "source_splicer.hpp" -#include "../sources/mpg123_source.hpp" -#include "../sources/wav_source.hpp" -#include "../outputs/openal_out.hpp" - -namespace Mangle { -namespace Sound { - -/** A InputFilter that uses OpenAL for output, and load input from - various individual sources, depending on file extension. Currently - supports: - - MP3: mpg123 - WAV: custom wav loader (PCM only) - - This could be an alternative to using eg. 3rd party decoder - libraries like libsndfile. - */ -class OpenAL_Various_Factory : public InputFilter -{ - public: - OpenAL_Various_Factory() - { - SourceSplicer *splice = new SourceSplicer; - - splice->add("mp3", SampleSourceLoaderPtr(new Mpg123Loader)); - splice->add("wav", SampleSourceLoaderPtr(new WavLoader)); - - set(SoundFactoryPtr(new OpenAL_Factory), - SampleSourceLoaderPtr(splice)); - } -}; - -}} -#endif diff --git a/libs/mangle/sound/filters/pure_filter.hpp b/libs/mangle/sound/filters/pure_filter.hpp deleted file mode 100644 index fc5e625744..0000000000 --- a/libs/mangle/sound/filters/pure_filter.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef MANGLE_SOUND_OUTPUT_PUREFILTER_H -#define MANGLE_SOUND_OUTPUT_PUREFILTER_H - -#include "../output.hpp" - -namespace Mangle -{ - namespace Sound - { - // For use in writing other filters - class SoundFilter : public Sound - { - protected: - SoundPtr client; - - public: - SoundFilter(SoundPtr c) : client(c) {} - void play() { client->play(); } - void stop() { client->stop(); } - void pause() { client->pause(); } - bool isPlaying() const { return client->isPlaying(); } - void setVolume(float f) { client->setVolume(f); } - void setPan(float f) { client->setPan(f); } - void setPos(float x, float y, float z) - { client->setPos(x,y,z); } - void setPitch(float p) { client->setPitch(p); } - void setRepeat(bool b) { client->setRepeat(b); } - void setRange(float a, float b=0, float c=0) - { client->setRange(a,b,c); } - void setStreaming(bool b) { client->setStreaming(b); } - void setRelative(bool b) { client->setRelative(b); } - - // The clone() function is not implemented here, as you will - // almost certainly want to override it yourself - }; - - class FactoryFilter : public SoundFactory - { - protected: - SoundFactoryPtr client; - - public: - FactoryFilter(SoundFactoryPtr c) : client(c) - { - needsUpdate = client->needsUpdate; - has3D = client->has3D; - canLoadFile = client->canLoadFile; - canLoadStream = client->canLoadStream; - canLoadSource = client->canLoadSource; - } - - SoundPtr loadRaw(SampleSourcePtr input) - { return client->loadRaw(input); } - - SoundPtr load(Stream::StreamPtr input) - { return client->load(input); } - - SoundPtr load(const std::string &file) - { return client->load(file); } - - void update() - { client->update(); } - - void setListenerPos(float x, float y, float z, - float fx, float fy, float fz, - float ux, float uy, float uz) - { - client->setListenerPos(x,y,z,fx,fy,fz,ux,uy,uz); - } - }; - } -} -#endif diff --git a/libs/mangle/sound/filters/source_splicer.hpp b/libs/mangle/sound/filters/source_splicer.hpp deleted file mode 100644 index 9c76230865..0000000000 --- a/libs/mangle/sound/filters/source_splicer.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef MANGLE_SOUND_SOURCE_SPLICE_H -#define MANGLE_SOUND_SOURCE_SPLICE_H - -#include "../source.hpp" -#include -#include -#include -#include - -namespace Mangle -{ - namespace Sound - { - class SourceSplicer : public SampleSourceLoader - { - struct SourceType - { - std::string type; - SampleSourceLoaderPtr loader; - }; - - typedef std::list TypeList; - TypeList list; - SampleSourceLoaderPtr catchAll; - - static bool isMatch(char a, char b) - { - if(a >= 'A' && a <= 'Z') - a += 'a' - 'A'; - if(b >= 'A' && b <= 'Z') - b += 'a' - 'A'; - return a == b; - } - - public: - SourceSplicer() - { - canLoadStream = false; - canLoadFile = true; - } - - void add(const std::string &type, SampleSourceLoaderPtr fact) - { - SourceType tp; - tp.type = type; - tp.loader = fact; - list.push_back(tp); - } - - void setDefault(SampleSourceLoaderPtr def) - { - catchAll = def; - } - - SampleSourcePtr load(const std::string &file) - { - // Search the list for this file type. - for(TypeList::iterator it = list.begin(); - it != list.end(); it++) - { - const std::string &t = it->type; - - int diff = file.size() - t.size(); - if(diff < 0) continue; - - bool match = true; - for(unsigned i=0; iloader->load(file); - } - // If not found, use the catch-all - if(catchAll) - return catchAll->load(file); - - throw std::runtime_error("No handler for sound file " + file); - } - - SampleSourcePtr load(Stream::StreamPtr input) { assert(0); } - }; - } -} - -#endif diff --git a/libs/mangle/sound/output.hpp b/libs/mangle/sound/output.hpp deleted file mode 100644 index e30bf21e27..0000000000 --- a/libs/mangle/sound/output.hpp +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef MANGLE_SOUND_OUTPUT_H -#define MANGLE_SOUND_OUTPUT_H - -#include -#include - -#include "source.hpp" -#include "../stream/stream.hpp" - -namespace Mangle { -namespace Sound { - -/// Abstract interface for a single playable sound -/** This class represents one sound outlet, which may be played, - stopped, paused and so on. - - Sound instances are created from the SoundFactory class. Sounds - may be connected to a SampleSource or read directly from a file, - and they may support 3d sounds, looping and other features - depending on the capabilities of the backend system. - - To create multiple instances of one sound, it is recommended to - 'clone' an existing instance instead of reloading it from - file. Cloned sounds will often (depending on the back-end) use - less memory due to shared buffers. -*/ -class Sound; -typedef boost::shared_ptr SoundPtr; -typedef boost::weak_ptr WSoundPtr; - -class Sound -{ - public: - /// Play or resume the sound - virtual void play() = 0; - - /// Stop the sound - virtual void stop() = 0; - - /// Pause the sound, may be resumed later - virtual void pause() = 0; - - /// Check if the sound is still playing - virtual bool isPlaying() const = 0; - - /// Set the volume. The parameter must be between 0.0 and 1.0. - virtual void setVolume(float) = 0; - - /// Set left/right pan. -1.0 is left, 0.0 is center and 1.0 is right. - virtual void setPan(float) = 0; - - /// Set pitch (1.0 is normal speed) - virtual void setPitch(float) = 0; - - /// Set range factors for 3D sounds. The meaning of the fields - /// depend on implementation. - virtual void setRange(float a, float b=0.0, float c=0.0) = 0; - - /// Set the position. May not work with all backends. - virtual void setPos(float x, float y, float z) = 0; - - /// Set loop mode - virtual void setRepeat(bool) = 0; - - /// If set to true the sound will not be affected by player movement - virtual void setRelative(bool) = 0; - - /// Set streaming mode. - /** This may be used by implementations to optimize for very large - files. If streaming mode is off (default), most implementations - will load the entire file into memory before starting playback. - */ - virtual void setStreaming(bool) = 0; - - /// Create a new instance of this sound. - /** Playback status is not cloned, only the sound data - itself. Back-ends can use this as a means of sharing data and - saving memory. */ - virtual SoundPtr clone() = 0; - - /// Virtual destructor - virtual ~Sound() {} -}; - -/// Factory interface for creating Sound objects -/** The SoundFactory is the main entry point to a given sound output - system. It is used to create Sound objects, which may be connected - to a sound file or stream, and which may be individually played, - paused, and so on. - - The class also contains a set of public bools which describe the - capabilities the particular system. These should be set by - implementations (base classes) in their respective constructors. - */ -class SoundFactory -{ - public: - /// Virtual destructor - virtual ~SoundFactory() {} - - /** @brief If set to true, you should call update() regularly (every frame - or so) on this sound manager. If false, update() should not be - called. - */ - bool needsUpdate; - - /** @brief true if 3D functions are available. If false, all use of - 3D sounds and calls to setPos / setListenerPos will result in - undefined behavior. - */ - bool has3D; - - /// true if we can load sounds directly from file (containing encoded data) - bool canLoadFile; - - /// If true, we can lound sound files from a Stream (containing encoded data) - bool canLoadStream; - - /// true if we can load sounds from a SampleSource (containing raw data) - bool canLoadSource; - - /** - @brief Load a sound from a sample source. Only valid if - canLoadSource is true. - - This function loads a sound from a given stream as defined by - SampleSource. - - @param input the input source - @param stream true if the file should be streamed. - Implementations may use this for optimizing playback of - large files, but they are not required to. - @return a new Sound object - */ - virtual SoundPtr loadRaw(SampleSourcePtr input) = 0; - - /** - @brief Load a sound file from stream. Only valid if canLoadStream - is true. - - @param input audio file stream - @param stream true if the file should be streamed - @see load(InputSource*,bool) - */ - virtual SoundPtr load(Stream::StreamPtr input) = 0; - - /** - @brief Load a sound directly from file. Only valid if canLoadFile - is true. - - @param file filename - @param stream true if the file should be streamed - @see load(InputSource*,bool) - */ - virtual SoundPtr load(const std::string &file) = 0; - - /// Call this every frame if needsUpdate is true - /** - This should be called regularly (about every frame in a normal - game setting.) Implementions may use this for filling streaming - buffers and similar tasks. Implementations that do not need this - should set needsUpdate to false. - */ - virtual void update() { assert(0); } - - /// Set listener position (coordinates, front and up vectors) - /** - Only valid if has3D is true. - - @param x,y,z listener position - @param fx,fy,fz listener's looking direction - @param ux,uy,uz listener's up direction - */ - virtual void setListenerPos(float x, float y, float z, - float fx, float fy, float fz, - float ux, float uy, float uz) = 0; -}; - -typedef boost::shared_ptr SoundFactoryPtr; - -}} // Namespaces - -#endif diff --git a/libs/mangle/sound/outputs/openal_out.cpp b/libs/mangle/sound/outputs/openal_out.cpp deleted file mode 100644 index 2056b4f602..0000000000 --- a/libs/mangle/sound/outputs/openal_out.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#include "openal_out.hpp" -#include -#include - -#include "../../stream/filters/buffer_stream.hpp" - -#ifdef _WIN32 -#include -#include -#elif defined(__APPLE__) -#include -#include -#else -#include -#include -#endif - -using namespace Mangle::Sound; - -// ---- Helper functions and classes ---- - -// Static buffer used to shuffle sound data from the input into -// OpenAL. The data is only stored temporarily and then immediately -// shuffled off to the library. This is not thread safe, but it works -// fine with multiple sounds in one thread. It could be made thread -// safe simply by using thread local storage. -const size_t BSIZE = 32*1024; -static char tmp_buffer[BSIZE]; - -// Number of buffers used (per sound) for streaming sounds. Each -// buffer is of size BSIZE. Increasing this will make streaming sounds -// more fault tolerant against temporary lapses in call to update(), -// but will also increase memory usage. -// This was changed from 4 to 150 for an estimated 30 seconds tolerance. -// At some point we should replace it with a more multithreading-ish -// solution. -const int STREAM_BUF_NUM = 150; - -static void fail(const std::string &msg) -{ throw std::runtime_error("OpenAL exception: " + msg); } - -/* - Check for AL error. Since we're always calling this with string - literals, and it only makes sense to optimize for the non-error - case, the parameter is const char* rather than std::string. - - This way we don't force the compiler to create a string object each - time we're called (since the string is never used unless there's an - error), although a good compiler might have optimized that away in - any case. - */ -static void checkALError(const char *where) -{ - ALenum err = alGetError(); - if(err != AL_NO_ERROR) - { - std::string msg = where; - - const ALchar* errmsg = alGetString(err); - if(errmsg) - fail("\"" + std::string(alGetString(err)) + "\" while " + msg); - else - fail("non-specified error while " + msg + " (did you forget to initialize OpenAL?)"); - } -} - -static void getALFormat(SampleSourcePtr inp, int &fmt, int &rate) -{ - boost::int32_t rate_, ch, bits; - inp->getInfo(&rate_, &ch, &bits); - rate = rate_; - - fmt = 0; - - if(bits == 8) - { - if(ch == 1) fmt = AL_FORMAT_MONO8; - if(ch == 2) fmt = AL_FORMAT_STEREO8; - if(alIsExtensionPresent("AL_EXT_MCFORMATS")) - { - if(ch == 4) fmt = alGetEnumValue("AL_FORMAT_QUAD8"); - if(ch == 6) fmt = alGetEnumValue("AL_FORMAT_51CHN8"); - } - } - if(bits == 16) - { - if(ch == 1) fmt = AL_FORMAT_MONO16; - if(ch == 2) fmt = AL_FORMAT_STEREO16; - if(ch == 4) fmt = alGetEnumValue("AL_FORMAT_QUAD16"); - if(alIsExtensionPresent("AL_EXT_MCFORMATS")) - { - if(ch == 4) fmt = alGetEnumValue("AL_FORMAT_QUAD16"); - if(ch == 6) fmt = alGetEnumValue("AL_FORMAT_51CHN16"); - } - } - - if(fmt == 0) - fail("Unsupported input format"); -} - -/// OpenAL sound output -class Mangle::Sound::OpenAL_Sound : public Sound -{ - ALuint inst; - - // Buffers. Only the first is used for non-streaming sounds. - ALuint bufferID[STREAM_BUF_NUM]; - - // Number of buffers used - int bufNum; - - // Parameters used for filling buffers - int fmt, rate; - - // Poor mans reference counting. Might improve this later. When - // NULL, the buffer has not been set up yet. - int *refCnt; - - bool streaming; - - // Input stream - SampleSourcePtr input; - - OpenAL_Factory *owner; - bool ownerAlive; - - // Used for streamed sound list - OpenAL_Sound *next, *prev; - - void setupBuffer(); - - // Fill data into the given buffer and queue it, if there is any - // data left to queue. Assumes the buffer is already unqueued, if - // necessary. - void queueBuffer(ALuint buf) - { - // If there is no more data, do nothing - if(!input) return; - if(input->eof()) - { - input.reset(); - return; - } - - // Get some new data - size_t bytes = input->read(tmp_buffer, BSIZE); - if(bytes == 0) - { - input.reset(); - return; - } - - // Move data into the OpenAL buffer - alBufferData(buf, fmt, tmp_buffer, bytes, rate); - // Queue it - alSourceQueueBuffers(inst, 1, &buf); - checkALError("Queueing buffer data"); - } - - public: - /// Read samples from the given input buffer - OpenAL_Sound(SampleSourcePtr input, OpenAL_Factory *fact); - - /// Play an existing buffer, with a given ref counter. Used - /// internally for cloning. - OpenAL_Sound(ALuint buf, int *ref, OpenAL_Factory *fact); - - ~OpenAL_Sound(); - - // Must be called regularly on streamed sounds - void update() - { - if(!streaming) return; - if(!input) return; - - // Get the number of processed buffers - ALint count; - alGetSourcei(inst, AL_BUFFERS_PROCESSED, &count); - checkALError("getting number of unprocessed buffers"); - - for(int i=0; iupdate(); -} - -void OpenAL_Factory::notifyStreaming(OpenAL_Sound *snd) -{ - // Add the sound to the streaming list - streaming.push_back(snd); -} - -void OpenAL_Factory::notifyDelete(OpenAL_Sound *snd) -{ - // Remove the sound from the stream list - streaming.remove(snd); -} - -OpenAL_Factory::~OpenAL_Factory() -{ - // Notify remaining streamed sounds that we're dying - StreamList::iterator it = streaming.begin(); - for(;it != streaming.end(); it++) - (*it)->notifyOwnerDeath(); - - // Deinitialize sound system - if(didSetup) - { - alcMakeContextCurrent(NULL); - if(context) alcDestroyContext((ALCcontext*)context); - if(device) alcCloseDevice((ALCdevice*)device); - } -} - -// ---- OpenAL_Sound ---- - -void OpenAL_Sound::play() -{ - setupBuffer(); - alSourcePlay(inst); - checkALError("starting playback"); -} - -void OpenAL_Sound::stop() -{ - alSourceStop(inst); - checkALError("stopping"); -} - -void OpenAL_Sound::pause() -{ - alSourcePause(inst); - checkALError("pausing"); -} - -bool OpenAL_Sound::isPlaying() const -{ - ALint state; - alGetSourcei(inst, AL_SOURCE_STATE, &state); - - return state == AL_PLAYING; -} - -void OpenAL_Sound::setVolume(float volume) -{ - if(volume > 1.0) volume = 1.0; - if(volume < 0.0) volume = 0.0; - alSourcef(inst, AL_GAIN, volume); - checkALError("setting volume"); -} - -void OpenAL_Sound::setRange(float a, float b, float) -{ - alSourcef(inst, AL_REFERENCE_DISTANCE, a); - alSourcef(inst, AL_MAX_DISTANCE, b); - checkALError("setting sound ranges"); -} - -void OpenAL_Sound::setPos(float x, float y, float z) -{ - alSource3f(inst, AL_POSITION, x, y, z); - checkALError("setting position"); -} - -void OpenAL_Sound::setPitch(float pitch) -{ - alSourcef(inst, AL_PITCH, pitch); - checkALError("setting pitch"); -} - -void OpenAL_Sound::setRepeat(bool rep) -{ - alSourcei(inst, AL_LOOPING, rep?AL_TRUE:AL_FALSE); -} - -void OpenAL_Sound::setRelative(bool rel) -{ - alSourcei(inst, AL_SOURCE_RELATIVE, rel?AL_TRUE:AL_FALSE); - checkALError("setting relative"); -} - -SoundPtr OpenAL_Sound::clone() -{ - setupBuffer(); - assert(!streaming && "cloning streamed sounds not supported"); - return SoundPtr(new OpenAL_Sound(bufferID[0], refCnt, owner)); -} - -// Constructor used for cloned sounds -OpenAL_Sound::OpenAL_Sound(ALuint buf, int *ref, OpenAL_Factory *fact) - : refCnt(ref), streaming(false), owner(fact), ownerAlive(false) -{ - // Increase the reference count - assert(ref != NULL); - (*refCnt)++; - - // Set up buffer - bufferID[0] = buf; - bufNum = 1; - - // Create a source - alGenSources(1, &inst); - checkALError("creating instance (clone)"); - alSourcei(inst, AL_BUFFER, bufferID[0]); - checkALError("assigning buffer (clone)"); -} - -// Constructor used for original (non-cloned) sounds -OpenAL_Sound::OpenAL_Sound(SampleSourcePtr _input, OpenAL_Factory *fact) - : refCnt(NULL), streaming(false), input(_input), owner(fact), ownerAlive(false) -{ - // Create a source - alGenSources(1, &inst); - checkALError("creating source"); - - // By default, the sound starts out in a buffer-less mode. We don't - // create a buffer until the sound is played. This gives the user - // the chance to call setStreaming(true) first. -} - -void OpenAL_Sound::setupBuffer() -{ - if(refCnt != NULL) return; - - assert(input); - - // Get the format - getALFormat(input, fmt, rate); - - // Create a cheap reference counter for the buffer - refCnt = new int; - *refCnt = 1; - - if(streaming) bufNum = STREAM_BUF_NUM; - else bufNum = 1; - - // Set up the OpenAL buffer(s) - alGenBuffers(bufNum, bufferID); - checkALError("generating buffer(s)"); - assert(bufferID[0] != 0); - - // STREAMING. - if(streaming) - { - // Just queue all the buffers with data and exit. queueBuffer() - // will work correctly also in the case where there is not - // enough data to fill all the buffers. - for(int i=0; inotifyStreaming(this); - ownerAlive = true; - - return; - } - - // NON-STREAMING. We have to load all the data and shove it into the - // buffer. - - // Does the stream support pointer operations? - if(input->hasPtr) - { - // If so, we can read the data directly from the stream - alBufferData(bufferID[0], fmt, input->getPtr(), input->size(), rate); - } - else - { - // Read the entire stream into a temporary buffer first - Mangle::Stream::BufferStream buf(input, 128*1024); - - // Then copy that into OpenAL - alBufferData(bufferID[0], fmt, buf.getPtr(), buf.size(), rate); - } - checkALError("loading sound data"); - - // We're done with the input stream, release the pointer - input.reset(); - - alSourcei(inst, AL_BUFFER, bufferID[0]); - checkALError("assigning buffer"); -} - -OpenAL_Sound::~OpenAL_Sound() -{ - // Stop - alSourceStop(inst); - - // Return sound - alDeleteSources(1, &inst); - - // Notify the factory that we quit. You will hear from our union - // rep. The bool check is to handle cases where the manager goes out - // of scope before the sounds do. In that case, don't try to contact - // the factory. - if(ownerAlive) - owner->notifyDelete(this); - - // Decrease the reference counter - if((-- (*refCnt)) == 0) - { - // We're the last owner. Delete the buffer(s) and the counter - // itself. - alDeleteBuffers(bufNum, bufferID); - checkALError("deleting buffer"); - delete refCnt; - } -} diff --git a/libs/mangle/sound/outputs/openal_out.hpp b/libs/mangle/sound/outputs/openal_out.hpp deleted file mode 100644 index 44d03ecf81..0000000000 --- a/libs/mangle/sound/outputs/openal_out.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MANGLE_SOUND_OPENAL_OUT_H -#define MANGLE_SOUND_OPENAL_OUT_H - -#include "../output.hpp" -#include - -namespace Mangle { -namespace Sound { - -class OpenAL_Sound; - -class OpenAL_Factory : public SoundFactory -{ - void *device; - void *context; - bool didSetup; - - // List of streaming sounds that need to be updated every frame. - typedef std::list StreamList; - StreamList streaming; - - friend class OpenAL_Sound; - void notifyStreaming(OpenAL_Sound*); - void notifyDelete(OpenAL_Sound*); - - public: - /// Initialize object. Pass true (default) if you want the - /// constructor to set up the current ALCdevice and ALCcontext for - /// you. - OpenAL_Factory(bool doSetup = true); - ~OpenAL_Factory(); - - SoundPtr load(const std::string &file) { assert(0); return SoundPtr(); } - SoundPtr load(Stream::StreamPtr input) { assert(0); return SoundPtr(); } - SoundPtr loadRaw(SampleSourcePtr input); - - void update(); - void setListenerPos(float x, float y, float z, - float fx, float fy, float fz, - float ux, float uy, float uz); -}; - -}} // namespaces -#endif diff --git a/libs/mangle/sound/source.hpp b/libs/mangle/sound/source.hpp deleted file mode 100644 index fbe7cf958b..0000000000 --- a/libs/mangle/sound/source.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef MANGLE_SOUND_SOURCE_H -#define MANGLE_SOUND_SOURCE_H - -#include -#include -#include - -#include "../stream/stream.hpp" - -namespace Mangle { -namespace Sound { - -typedef boost::int32_t int32_t; - -/// A stream containing raw sound data and information about the format -class SampleSource : public Stream::Stream -{ - protected: - bool isEof; - - public: - SampleSource() : isEof(false) {} - - /// Get the sample rate, number of channels, and bits per - /// sample. NULL parameters are ignored. - virtual void getInfo(int32_t *rate, int32_t *channels, int32_t *bits) = 0; - - bool eof() const { return isEof; } - - // Disabled functions by default. You can still override them in - // subclasses. - void seek(size_t pos) { assert(0); } - size_t tell() const { assert(0); return 0; } - size_t size() const { assert(0); return 0; } -}; - -typedef boost::shared_ptr SampleSourcePtr; - -/// A factory interface for loading SampleSources from file or stream -class SampleSourceLoader -{ - public: - /// If true, the stream version of load() works - bool canLoadStream; - - /// If true, the file version of load() works - bool canLoadFile; - - /// Load a sound input source from file (if canLoadFile is true) - virtual SampleSourcePtr load(const std::string &file) = 0; - - /// Load a sound input source from stream (if canLoadStream is true) - virtual SampleSourcePtr load(Stream::StreamPtr input) = 0; - - /// Virtual destructor - virtual ~SampleSourceLoader() {} -}; - -typedef boost::shared_ptr SampleSourceLoaderPtr; - -}} // namespaces -#endif diff --git a/libs/mangle/sound/sources/audiere_source.cpp b/libs/mangle/sound/sources/audiere_source.cpp deleted file mode 100644 index faaa3c8c5b..0000000000 --- a/libs/mangle/sound/sources/audiere_source.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "audiere_source.hpp" - -#include "../../stream/clients/audiere_file.hpp" - -#include - -using namespace Mangle::Stream; - -static void fail(const std::string &msg) -{ throw std::runtime_error("Audiere exception: " + msg); } - -using namespace audiere; -using namespace Mangle::Sound; - -// --- SampleSource --- - -void AudiereSource::getInfo(Mangle::Sound::int32_t *rate, - Mangle::Sound::int32_t *channels, Mangle::Sound::int32_t *bits) -{ - SampleFormat fmt; - int channels_, rate_; - sample->getFormat(channels_, rate_, fmt); - *channels = channels_; - *rate = rate_; - if(bits) - { - if(fmt == SF_U8) - *bits = 8; - else if(fmt == SF_S16) - *bits = 16; - else assert(0); - } -} - -// --- Constructors --- - -AudiereSource::AudiereSource(const std::string &file) -{ - sample = OpenSampleSource(file.c_str()); - - if(!sample) - fail("Couldn't load file " + file); - - doSetup(); -} - -AudiereSource::AudiereSource(StreamPtr input) -{ - // Use our Stream::AudiereFile implementation to convert a Mangle - // 'Stream' to an Audiere 'File' - sample = OpenSampleSource(new AudiereFile(input)); - if(!sample) - fail("Couldn't load stream"); - - doSetup(); -} - -AudiereSource::AudiereSource(audiere::SampleSourcePtr src) - : sample(src) -{ assert(sample); doSetup(); } - -// Common function called from all constructors -void AudiereSource::doSetup() -{ - assert(sample); - - SampleFormat fmt; - int channels, rate; - sample->getFormat(channels, rate, fmt); - - // Calculate the size of one frame, and pass it to SampleReader. - setup(GetSampleSize(fmt) * channels); - - isSeekable = sample->isSeekable(); - hasPosition = true; - hasSize = true; -} diff --git a/libs/mangle/sound/sources/audiere_source.hpp b/libs/mangle/sound/sources/audiere_source.hpp deleted file mode 100644 index d797c55c86..0000000000 --- a/libs/mangle/sound/sources/audiere_source.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef MANGLE_SOUND_AUDIERE_SOURCE_H -#define MANGLE_SOUND_AUDIERE_SOURCE_H - -#include "sample_reader.hpp" - -// audiere.h from 1.9.4 (latest) release uses -// cstring routines like strchr() and strlen() without -// including cstring itself. -#include -#include - -namespace Mangle { -namespace Sound { - -/// A sample source that decodes files using Audiere -class AudiereSource : public SampleReader -{ - audiere::SampleSourcePtr sample; - - size_t readSamples(void *data, size_t length) - { return sample->read(length, data); } - - void doSetup(); - - public: - /// Decode the given sound file - AudiereSource(const std::string &file); - - /// Decode the given sound stream - AudiereSource(Mangle::Stream::StreamPtr src); - - /// Read directly from an existing audiere::SampleSource - AudiereSource(audiere::SampleSourcePtr src); - - void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); - - void seek(size_t pos) { sample->setPosition(pos/frameSize); } - size_t tell() const { return sample->getPosition()*frameSize; } - size_t size() const { return sample->getLength()*frameSize; } -}; - -#include "loadertemplate.hpp" - -/// A factory that loads AudiereSources from file and stream -typedef SSL_Template AudiereLoader; - -}} // Namespace -#endif diff --git a/libs/mangle/sound/sources/ffmpeg_source.cpp b/libs/mangle/sound/sources/ffmpeg_source.cpp deleted file mode 100644 index 6349be6913..0000000000 --- a/libs/mangle/sound/sources/ffmpeg_source.cpp +++ /dev/null @@ -1,189 +0,0 @@ -#include "ffmpeg_source.hpp" - -#include - -using namespace Mangle::Sound; - -// Static output buffer. Not thread safe, but supports multiple -// streams operated from the same thread. -static uint8_t outBuf[AVCODEC_MAX_AUDIO_FRAME_SIZE]; - -static void fail(const std::string &msg) -{ throw std::runtime_error("FFMpeg exception: " + msg); } - -// --- Loader --- - -static bool init = false; - -FFMpegLoader::FFMpegLoader(bool setup) -{ - if(setup && !init) - { - av_register_all(); - av_log_set_level(AV_LOG_ERROR); - init = true; - } -} - -// --- Source --- - -FFMpegSource::FFMpegSource(const std::string &file) -{ - std::string msg; - AVCodec *codec; - - if(av_open_input_file(&FmtCtx, file.c_str(), NULL, 0, NULL) != 0) - fail("Error loading audio file " + file); - - if(av_find_stream_info(FmtCtx) < 0) - { - msg = "Error in file stream " + file; - goto err; - } - - // Pick the first audio stream, if any - for(StreamNum = 0; StreamNum < FmtCtx->nb_streams; StreamNum++) - { - // Pick the first audio stream - if(FmtCtx->streams[StreamNum]->codec->codec_type == CODEC_TYPE_AUDIO) - break; - } - - if(StreamNum == FmtCtx->nb_streams) - fail("File '" + file + "' didn't contain any audio streams"); - - // Open the decoder - CodecCtx = FmtCtx->streams[StreamNum]->codec; - codec = avcodec_find_decoder(CodecCtx->codec_id); - - if(!codec || avcodec_open(CodecCtx, codec) < 0) - { - msg = "Error loading '" + file + "': "; - if(codec) - msg += "coded error"; - else - msg += "no codec found"; - goto err; - } - - // No errors, we're done - return; - - // Handle errors - err: - av_close_input_file(FmtCtx); - fail(msg); -} - -FFMpegSource::~FFMpegSource() -{ - avcodec_close(CodecCtx); - av_close_input_file(FmtCtx); -} - -void FFMpegSource::getInfo(int32_t *rate, int32_t *channels, int32_t *bits) -{ - if(rate) *rate = CodecCtx->sample_rate; - if(channels) *channels = CodecCtx->channels; - if(bits) *bits = 16; -} - -size_t FFMpegSource::read(void *data, size_t length) -{ - if(isEof) return 0; - - size_t left = length; - uint8_t *outPtr = (uint8_t*)data; - - // First, copy over any stored data we might be sitting on - { - size_t s = storage.size(); - size_t copy = s; - if(s) - { - // Make sure there's room - if(copy > left) - copy = left; - - // Copy - memcpy(outPtr, &storage[0], copy); - outPtr += copy; - left -= copy; - - // Is there anything left in the storage? - assert(s>= copy); - s -= copy; - if(s) - { - assert(left == 0); - - // Move it to the start and resize - memmove(&storage[0], &storage[copy], s); - storage.resize(s); - } - } - } - - // Next, get more input data from stream, and decode it - while(left) - { - AVPacket packet; - - // Get the next packet, if any - if(av_read_frame(FmtCtx, &packet) < 0) - break; - - // We only allow one stream per file at the moment - assert((int)StreamNum == packet.stream_index); - - // Decode the packet - int len = AVCODEC_MAX_AUDIO_FRAME_SIZE; - int tmp = avcodec_decode_audio2(CodecCtx, (int16_t*)outBuf, - &len, packet.data, packet.size); - assert(tmp < 0 || tmp == packet.size); - - // We don't need the input packet any longer - av_free_packet(&packet); - - if(tmp < 0) - fail("Error decoding audio stream"); - - // Copy whatever data we got, and advance the pointer - if(len > 0) - { - // copy = how many bytes do we copy now - size_t copy = len; - if(copy > left) - copy = left; - - // len = how many bytes are left uncopied - len -= copy; - - // copy data - memcpy(outPtr, outBuf, copy); - - // left = how much space is left in the caller output - // buffer. This loop repeats as long left is > 0 - left -= copy; - outPtr += copy; - assert(left >= 0); - - if(len > 0) - { - // There were uncopied bytes. Store them for later. - assert(left == 0); - storage.resize(len); - memcpy(&storage[0], outBuf, len); - } - } - } - - // End of loop. Return the number of bytes copied. - assert(left <= length); - - // If we're returning less than asked for, then we're done - if(left > 0) - isEof = true; - - return length - left; -} diff --git a/libs/mangle/sound/sources/ffmpeg_source.hpp b/libs/mangle/sound/sources/ffmpeg_source.hpp deleted file mode 100644 index d422b98090..0000000000 --- a/libs/mangle/sound/sources/ffmpeg_source.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MANGLE_SOUND_FFMPEG_H -#define MANGLE_SOUND_FFMPEG_H - -#include "../source.hpp" -#include -#include - -extern "C" -{ -#include -#include -} - -namespace Mangle { -namespace Sound { - -class FFMpegSource : public SampleSource -{ - AVFormatContext *FmtCtx; - AVCodecContext *CodecCtx; - unsigned int StreamNum; - - std::vector storage; - - public: - /// Decode the given sound file - FFMpegSource(const std::string &file); - - /// Decode the given sound stream (not supported by FFmpeg) - FFMpegSource(Mangle::Stream::StreamPtr src) { assert(0); } - - ~FFMpegSource(); - - // Overrides - void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); - size_t read(void *data, size_t length); -}; - -#include "loadertemplate.hpp" - -/// A factory that loads FFMpegSources from file -class FFMpegLoader : public SSL_Template -{ - public: - - /// Sets up the libavcodec library. If you want to do your own - /// setup, send a setup=false parameter. - FFMpegLoader(bool setup=true); -}; - -}} // namespaces -#endif diff --git a/libs/mangle/sound/sources/libsndfile.cpp b/libs/mangle/sound/sources/libsndfile.cpp deleted file mode 100644 index b69a2d4368..0000000000 --- a/libs/mangle/sound/sources/libsndfile.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "libsndfile.hpp" - -#include -#include - -using namespace Mangle::Stream; - -static void fail(const std::string &msg) -{ throw std::runtime_error("Mangle::libsndfile: " + msg); } - -using namespace Mangle::Sound; - -void SndFileSource::getInfo(int32_t *_rate, int32_t *_channels, int32_t *_bits) -{ - *_rate = rate; - *_channels = channels; - *_bits = bits; -} - -size_t SndFileSource::readSamples(void *data, size_t length) -{ - // readf_* reads entire frames, including channels - return sf_readf_short((SNDFILE*)handle, (short*)data, length); -} - -SndFileSource::SndFileSource(const std::string &file) -{ - SF_INFO info; - info.format = 0; - handle = sf_open(file.c_str(), SFM_READ, &info); - if(handle == NULL) - fail("Failed to open " + file); - - // I THINK that using sf_read_short forces the library to convert to - // 16 bits no matter what, but the libsndfile docs aren't exactly - // very clear on this point. - channels = info.channels; - rate = info.samplerate; - bits = 16; - - // 16 bits per sample times number of channels - setup(2*channels); -} - -SndFileSource::~SndFileSource() -{ - sf_close((SNDFILE*)handle); -} diff --git a/libs/mangle/sound/sources/libsndfile.hpp b/libs/mangle/sound/sources/libsndfile.hpp deleted file mode 100644 index 7286cf0fe4..0000000000 --- a/libs/mangle/sound/sources/libsndfile.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef MANGLE_SOUND_SNDFILE_SOURCE_H -#define MANGLE_SOUND_SNDFILE_SOURCE_H - -#include "sample_reader.hpp" - -namespace Mangle { -namespace Sound { - -/// A sample source that decodes files using libsndfile. Supports most -/// formats except mp3. -class SndFileSource : public SampleReader -{ - void *handle; - int channels, rate, bits; - - size_t readSamples(void *data, size_t length); - - public: - /// Decode the given sound file - SndFileSource(const std::string &file); - - /// Decode the given sound stream (not supported) - SndFileSource(Mangle::Stream::StreamPtr src) { assert(0); } - - ~SndFileSource(); - - void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); -}; - -#include "loadertemplate.hpp" - -/// A factory that loads SndFileSources from file and stream -typedef SSL_Template SndFileLoader; - -}} // Namespace -#endif diff --git a/libs/mangle/sound/sources/loadertemplate.hpp b/libs/mangle/sound/sources/loadertemplate.hpp deleted file mode 100644 index a27a77d106..0000000000 --- a/libs/mangle/sound/sources/loadertemplate.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SSL_TEMPL_H -#define SSL_TEMPL_H - -template -class SSL_Template : public SampleSourceLoader -{ - public: - - SSL_Template() - { - canLoadStream = stream; - canLoadFile = file; - } - - SampleSourcePtr load(const std::string &filename) - { - assert(canLoadFile); - return SampleSourcePtr(new SourceT(filename)); - } - - SampleSourcePtr load(Stream::StreamPtr input) - { - assert(canLoadStream); - return SampleSourcePtr(new SourceT(input)); - } -}; - -#endif diff --git a/libs/mangle/sound/sources/mpg123_source.cpp b/libs/mangle/sound/sources/mpg123_source.cpp deleted file mode 100644 index 24d6ecce1c..0000000000 --- a/libs/mangle/sound/sources/mpg123_source.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "mpg123_source.hpp" - -#include - -#include - -using namespace Mangle::Stream; - -/* - TODOs: - - - mpg123 impressively enough supports custom stream reading. Which - means we could (and SHOULD!) support reading from Mangle::Streams - as well. But I'll save it til I need it. - - An alternative way to do this is through feeding (which they also - support), but that's more messy. - - - the library also supports output, via various other sources, - including ALSA, OSS, PortAudio, PulseAudio and SDL. Using this - library as a pure output library (if that is possible) would be a - nice shortcut over using those libraries - OTOH it's another - dependency. - - - we could implement seek(), tell() and size(), but they aren't - really necessary. Furthermore, since the returned size is only a - guess, it is not safe to rely on it. - */ - -static void fail(const std::string &msg) -{ throw std::runtime_error("Mangle::Mpg123 exception: " + msg); } - -static void checkError(int err, void *mh = NULL) -{ - if(err != MPG123_OK) - { - std::string msg; - if(mh) msg = mpg123_strerror((mpg123_handle*)mh); - else msg = mpg123_plain_strerror(err); - fail(msg); - } -} - -using namespace Mangle::Sound; - -void Mpg123Source::getInfo(int32_t *pRate, int32_t *pChannels, int32_t *pBits) -{ - // Use the values we found in the constructor - *pRate = rate; - *pChannels = channels; - *pBits = bits; -} - -size_t Mpg123Source::read(void *data, size_t length) -{ - size_t done; - // This is extraordinarily nice. I like this library. - int err = mpg123_read((mpg123_handle*)mh, (unsigned char*)data, length, &done); - assert(done <= length); - if(err == MPG123_DONE) - isEof = true; - else - checkError(err, mh); - return done; -} - -Mpg123Loader::Mpg123Loader(bool setup) -{ - // Do as we're told - if(setup) - { - int err = mpg123_init(); - checkError(err); - } - didSetup = setup; -} - -Mpg123Loader::~Mpg123Loader() -{ - // Deinitialize the library on exit - if(didSetup) - mpg123_exit(); -} - -Mpg123Source::Mpg123Source(const std::string &file) -{ - int err; - - // Create a new handle - mh = mpg123_new(NULL, &err); - if(mh == NULL) - checkError(err, mh); - - mpg123_handle *mhh = (mpg123_handle*)mh; - - // Open the file (hack around constness) - err = mpg123_open(mhh, (char*)file.c_str()); - checkError(err, mh); - - // Get the format - int encoding; - err = mpg123_getformat(mhh, &rate, &channels, &encoding); - checkError(err, mh); - if(encoding != MPG123_ENC_SIGNED_16) - fail("Unsupported encoding in " + file); - - // This is the only bit size we support. - bits = 16; -} - -Mpg123Source::~Mpg123Source() -{ - mpg123_close((mpg123_handle*)mh); - mpg123_delete((mpg123_handle*)mh); -} diff --git a/libs/mangle/sound/sources/mpg123_source.hpp b/libs/mangle/sound/sources/mpg123_source.hpp deleted file mode 100644 index 1ac16b5306..0000000000 --- a/libs/mangle/sound/sources/mpg123_source.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MANGLE_SOUND_MPG123_SOURCE_H -#define MANGLE_SOUND_MPG123_SOURCE_H - -#include "../source.hpp" -#include - -namespace Mangle { -namespace Sound { - -/// A sample source that decodes files using libmpg123. Only supports -/// MP3 files. -class Mpg123Source : public SampleSource -{ - void *mh; - long int rate; - int channels, bits; - - public: - /// Decode the given sound file - Mpg123Source(const std::string &file); - - /// Needed by SSL_Template but not yet supported - Mpg123Source(Mangle::Stream::StreamPtr data) - { assert(0); } - - ~Mpg123Source(); - - void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); - size_t read(void *data, size_t length); -}; - -#include "loadertemplate.hpp" - -/// A factory that loads Mpg123Sources from file and stream -struct Mpg123Loader : SSL_Template -{ - /** Sets up libmpg123 for you, and closes it on destruction. If you - want to do this yourself, send setup=false. - */ - Mpg123Loader(bool setup=true); - ~Mpg123Loader(); -private: - bool didSetup; -}; - -}} // Namespace -#endif diff --git a/libs/mangle/sound/sources/sample_reader.cpp b/libs/mangle/sound/sources/sample_reader.cpp deleted file mode 100644 index c30de654a5..0000000000 --- a/libs/mangle/sound/sources/sample_reader.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "sample_reader.hpp" - -#include - -using namespace Mangle::Sound; - -void SampleReader::setup(int size) -{ - pullSize = 0; - frameSize = size; - pullOver = new char[size]; -} - -SampleReader::~SampleReader() -{ - if(pullOver) - delete[] pullOver; -} - -size_t SampleReader::read(void *_data, size_t length) -{ - if(isEof) return 0; - char *data = (char*)_data; - - // Pullsize holds the number of bytes that were copied "extra" at - // the end of LAST round. If non-zero, it also means there is data - // left in the pullOver buffer. - if(pullSize) - { - // Amount of data left - size_t doRead = frameSize - pullSize; - assert(doRead > 0); - - // Make sure we don't read more than we're supposed to - if(doRead > length) doRead = length; - - memcpy(data, pullOver+pullSize, doRead); - - // Update the number of bytes now copied - pullSize += doRead; - assert(pullSize <= frameSize); - - if(pullSize < frameSize) - { - // There is STILL data left in the pull buffer, and we've - // done everything we were supposed to. Leave it and return. - assert(doRead == length); - return doRead; - } - - // Set up variables for further reading below. No need to update - // pullSize, it is overwritten anyway. - length -= doRead; - data += doRead; - } - - // Number of whole frames - size_t frames = length / frameSize; - - // Read the data - size_t res = readSamples(data, frames); - assert(res <= frames); - - // Total bytes read - size_t num = res*frameSize; - data += num; - - if(res < frames) - { - // End of stream. - isEof = true; - // Determine how much we read - return data-(char*)_data; - } - - // Determine the overshoot - pullSize = length - num; - assert(pullSize < frameSize && pullSize >= 0); - - // Are we missing data? - if(pullSize) - { - // Fill in one sample - res = readSamples(pullOver,1); - assert(res == 1 || res == 0); - if(res) - { - // Move as much as we can into the output buffer - memcpy(data, pullOver, pullSize); - data += pullSize; - } - else - // Failed reading, we're out of data - isEof = true; - } - - // Return the total number of bytes stored - return data-(char*)_data; -} diff --git a/libs/mangle/sound/sources/sample_reader.hpp b/libs/mangle/sound/sources/sample_reader.hpp deleted file mode 100644 index 89ddf1f652..0000000000 --- a/libs/mangle/sound/sources/sample_reader.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef MANGLE_SOUND_SAMPLE_READER_H -#define MANGLE_SOUND_SAMPLE_READER_H - -#include "../source.hpp" - -namespace Mangle { -namespace Sound { - - /* This is a helper base class for other SampleSource - implementations. Certain sources (like Audiere and libsndfile) - insist on reading whole samples rather than bytes. This class - compensates for that, and allows you to read bytes rather than - samples. - - There are two ways for subclasses to use this class. EITHER call - setup() with the size of frameSize. This will allocate a buffer, - which the destructor frees. OR set frameSize manually and - manipulate the pullOver pointer yourself. In that case you MUST - reset it to NULL if you don't want the destructor to call - delete[] on it. - */ -class SampleReader : public SampleSource -{ - // How much of the above buffer is in use. - int pullSize; - -protected: - // Pullover buffer - char* pullOver; - - // Size of one frame, in bytes. This is also the size of the - // pullOver buffer. - int frameSize; - - // The parameter gives the size of one sample/frame, in bytes. - void setup(int); - - // Read the given number of samples, in multiples of frameSize. Does - // not have to set or respect isEof. - virtual size_t readSamples(void *data, size_t num) = 0; - - public: - SampleReader() : pullSize(0), pullOver(NULL) {} - ~SampleReader(); - size_t read(void *data, size_t length); -}; -}} // Namespace -#endif diff --git a/libs/mangle/sound/sources/stream_source.hpp b/libs/mangle/sound/sources/stream_source.hpp deleted file mode 100644 index 43c605a004..0000000000 --- a/libs/mangle/sound/sources/stream_source.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef MANGLE_SOUND_STREAMSOURCE_H -#define MANGLE_SOUND_STREAMSOURCE_H - -#include "../source.hpp" - -namespace Mangle { -namespace Sound { - -/// A class for reading raw samples directly from a stream. -class Stream2Samples : public SampleSource -{ - Mangle::Stream::StreamPtr inp; - int32_t rate, channels, bits; - - public: - Stream2Samples(Mangle::Stream::StreamPtr _inp, int32_t _rate, int32_t _channels, int32_t _bits) - : inp(_inp), rate(_rate), channels(_channels), bits(_bits) - { - isSeekable = inp->isSeekable; - hasPosition = inp->hasPosition; - hasSize = inp->hasSize; - hasPtr = inp->hasPtr; - } - - /// Get the sample rate, number of channels, and bits per - /// sample. NULL parameters are ignored. - void getInfo(int32_t *_rate, int32_t *_channels, int32_t *_bits) - { - if(_rate) *_rate = rate; - if(_channels) *_channels = channels; - if(_bits) *_bits = bits; - } - - size_t read(void *out, size_t count) - { return inp->read(out, count); } - - void seek(size_t pos) { inp->seek(pos); } - size_t tell() const { return inp->tell(); } - size_t size() const { return inp->size(); } - bool eof() const { return inp->eof(); } - const void *getPtr() { return inp->getPtr(); } - const void *getPtr(size_t size) { return inp->getPtr(size); } - const void *getPtr(size_t pos, size_t size) { return inp->getPtr(pos, size); } -}; - -}} // namespaces -#endif diff --git a/libs/mangle/sound/sources/wav_source.cpp b/libs/mangle/sound/sources/wav_source.cpp deleted file mode 100644 index a46b3d27ec..0000000000 --- a/libs/mangle/sound/sources/wav_source.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "wav_source.hpp" - -#include "../../stream/servers/file_stream.hpp" - -#include - -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -static void fail(const std::string &msg) -{ throw std::runtime_error("Mangle::Wav exception: " + msg); } - -void WavSource::getInfo(int32_t *pRate, int32_t *pChannels, int32_t *pBits) -{ - // Use the values we found in the constructor - *pRate = rate; - *pChannels = channels; - *pBits = bits; -} - -void WavSource::seek(size_t pos) -{ - // Seek the stream and set 'left' - assert(isSeekable); - if(pos > total) pos = total; - input->seek(dataOffset + pos); - left = total-pos; -} - -size_t WavSource::read(void *data, size_t length) -{ - if(length > left) - length = left; - size_t read = input->read(data, length); - if(read < length) - // Something went wrong - fail("WAV read error"); - return length; -} - -void WavSource::open(Mangle::Stream::StreamPtr data) -{ - input = data; - - hasPosition = true; - hasSize = true; - // If we can check position and seek in the input stream, then we - // can seek the wav data too. - isSeekable = input->isSeekable && input->hasPosition; - - // Read header - unsigned int val; - - input->read(&val,4); // header - if(val != 0x46464952) // "RIFF" - fail("Not a WAV file"); - - input->read(&val,4); // size (ignored) - input->read(&val,4); // file format - if(val != 0x45564157) // "WAVE" - fail("Not a valid WAV file"); - - input->read(&val,4); // "fmt " - input->read(&val,4); // chunk size (must be 16) - if(val != 16) - fail("Unsupported WAV format"); - - input->read(&val,2); - if(val != 1) - fail("Non-PCM (compressed) WAV files not supported"); - - // Sound data specification - channels = 0; - input->read(&channels,2); - input->read(&rate, 4); - - // Skip next 6 bytes - input->read(&val, 4); - input->read(&val, 2); - - // Bits per sample - bits = 0; - input->read(&bits,2); - - input->read(&val,4); // Data header - if(val != 0x61746164) // "data" - fail("Expected data block"); - - // Finally, read the data size - input->read(&total,4); - left = total; - - // Store the beginning of the data block for later - if(input->hasPosition) - dataOffset = input->tell(); -} - -WavSource::WavSource(const std::string &file) -{ open(StreamPtr(new FileStream(file))); } diff --git a/libs/mangle/sound/sources/wav_source.hpp b/libs/mangle/sound/sources/wav_source.hpp deleted file mode 100644 index 227f4da733..0000000000 --- a/libs/mangle/sound/sources/wav_source.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef MANGLE_SOUND_WAV_SOURCE_H -#define MANGLE_SOUND_WAV_SOURCE_H - -#include "../source.hpp" -#include - -namespace Mangle { -namespace Sound { - -/// WAV file decoder. Has no external library dependencies. -class WavSource : public SampleSource -{ - // Sound info - uint32_t rate, channels, bits; - - // Total size (of output) and bytes left - uint32_t total, left; - - // Offset in input of the beginning of the data block - size_t dataOffset; - - Mangle::Stream::StreamPtr input; - - void open(Mangle::Stream::StreamPtr); - - public: - /// Decode the given sound file - WavSource(const std::string&); - - /// Decode from stream - WavSource(Mangle::Stream::StreamPtr s) - { open(s); } - - void getInfo(int32_t *rate, int32_t *channels, int32_t *bits); - size_t read(void *data, size_t length); - - void seek(size_t); - size_t tell() const { return total-left; } - size_t size() const { return total; } - bool eof() const { return left > 0; } -}; - -#include "loadertemplate.hpp" - -/// A factory that loads WavSources from file and stream -typedef SSL_Template WavLoader; - -}} // Namespace -#endif diff --git a/libs/mangle/sound/tests/.gitignore b/libs/mangle/sound/tests/.gitignore deleted file mode 100644 index 8144904045..0000000000 --- a/libs/mangle/sound/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*_test diff --git a/libs/mangle/sound/tests/Makefile b/libs/mangle/sound/tests/Makefile deleted file mode 100644 index 6fcac72da7..0000000000 --- a/libs/mangle/sound/tests/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -GCC=g++ -I../ -Wall - -all: audiere_source_test ffmpeg_source_test openal_output_test openal_audiere_test openal_ffmpeg_test openal_mpg123_test openal_sndfile_test wav_source_test openal_various_test - -L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat) -I_FFMPEG=-I/usr/include/libavcodec -I/usr/include/libavformat -L_OPENAL=$(shell pkg-config --libs openal) -L_AUDIERE=-laudiere - -wav_source_test: wav_source_test.cpp ../sources/wav_source.cpp - $(GCC) $^ -o $@ - -openal_various_test: openal_various_test.cpp ../sources/mpg123_source.cpp ../sources/wav_source.cpp ../outputs/openal_out.cpp - $(GCC) $^ -o $@ -lmpg123 ${L_OPENAL} - -openal_audiere_test: openal_audiere_test.cpp ../sources/audiere_source.cpp ../sources/sample_reader.cpp ../outputs/openal_out.cpp ../../stream/clients/audiere_file.cpp - $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) - -openal_ffmpeg_test: openal_ffmpeg_test.cpp ../sources/ffmpeg_source.cpp ../outputs/openal_out.cpp - $(GCC) $^ -o $@ $(L_FFMPEG) $(L_OPENAL) $(I_FFMPEG) - -openal_mpg123_test: openal_mpg123_test.cpp ../sources/mpg123_source.cpp ../outputs/openal_out.cpp - $(GCC) $^ -o $@ -lmpg123 ${L_OPENAL} - -openal_sndfile_test: openal_sndfile_test.cpp ../sources/libsndfile.cpp ../sources/sample_reader.cpp ../outputs/openal_out.cpp - $(GCC) $^ -o $@ -lsndfile ${L_OPENAL} - -openal_output_test: openal_output_test.cpp ../outputs/openal_out.cpp - $(GCC) $^ -o $@ $(L_OPENAL) - -audiere_source_test: audiere_source_test.cpp ../sources/audiere_source.cpp ../../stream/clients/audiere_file.cpp ../sources/sample_reader.cpp - $(GCC) $^ -o $@ $(L_AUDIERE) - -ffmpeg_source_test: ffmpeg_source_test.cpp ../sources/ffmpeg_source.cpp - $(GCC) $^ -o $@ $(L_FFMPEG) $(I_FFMPEG) - -clean: - rm *_test diff --git a/libs/mangle/sound/tests/audiere_source_test.cpp b/libs/mangle/sound/tests/audiere_source_test.cpp deleted file mode 100644 index 637d743b21..0000000000 --- a/libs/mangle/sound/tests/audiere_source_test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../sources/audiere_source.hpp" - -#include -#include - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -// Contents and size of cow.raw -void *orig; -size_t orig_size; - -void run(SampleSourcePtr &src) -{ - size_t ss = src->size(); - assert(ss == orig_size); - - cout << "Source size: " << ss << endl; - int rate, channels, bits; - src->getInfo(&rate, &channels, &bits); - cout << "rate=" << rate << "\nchannels=" << channels - << "\nbits=" << bits << endl; - - cout << "Reading entire buffer into memory\n"; - void *buf = malloc(ss); - src->read(buf, ss); - - cout << "Comparing...\n"; - if(memcmp(buf, orig, ss) != 0) - { - cout << "Oops!\n"; - assert(0); - } - - cout << "Done\n"; -} - -int main() -{ - { - cout << "Reading cow.raw first\n"; - FileStream tmp("cow.raw"); - orig_size = tmp.size(); - cout << "Size: " << orig_size << endl; - orig = malloc(orig_size); - tmp.read(orig, orig_size); - cout << "Done\n"; - } - - { - cout << "\nLoading cow.wav by filename:\n"; - SampleSourcePtr cow_file( new AudiereSource("cow.wav") ); - run(cow_file); - } - - { - cout << "\nLoading cow.wav by stream:\n"; - StreamPtr inp( new FileStream("cow.wav") ); - SampleSourcePtr cow_stream( new AudiereSource(inp) ); - run(cow_stream); - } - - return 0; -} diff --git a/libs/mangle/sound/tests/cow.raw b/libs/mangle/sound/tests/cow.raw deleted file mode 100644 index c4d155bbfb..0000000000 Binary files a/libs/mangle/sound/tests/cow.raw and /dev/null differ diff --git a/libs/mangle/sound/tests/cow.wav b/libs/mangle/sound/tests/cow.wav deleted file mode 100644 index 494e6c4ac1..0000000000 Binary files a/libs/mangle/sound/tests/cow.wav and /dev/null differ diff --git a/libs/mangle/sound/tests/ffmpeg_source_test.cpp b/libs/mangle/sound/tests/ffmpeg_source_test.cpp deleted file mode 100644 index f03b15b996..0000000000 --- a/libs/mangle/sound/tests/ffmpeg_source_test.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../sources/ffmpeg_source.hpp" - -#include -#include - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -// Contents and size of cow.raw -void *orig; -size_t orig_size; - -void run(SampleSourcePtr &src) -{ - int rate, channels, bits; - src->getInfo(&rate, &channels, &bits); - cout << "rate=" << rate << "\nchannels=" << channels - << "\nbits=" << bits << endl; - - cout << "Reading entire buffer into memory\n"; - void *buf = malloc(orig_size); - size_t ss = src->read(buf, orig_size); - cout << "Actually read: " << ss << endl; - assert(ss == orig_size); - - cout << "Comparing...\n"; - if(memcmp(buf, orig, ss) != 0) - { - cout << "Oops!\n"; - assert(0); - } - - cout << "Done\n"; -} - -int main() -{ - { - cout << "Reading cow.raw first\n"; - FileStream tmp("cow.raw"); - orig_size = tmp.size(); - cout << "Size: " << orig_size << endl; - orig = malloc(orig_size); - tmp.read(orig, orig_size); - cout << "Done\n"; - } - - // Initializes the library, not used for anything else. - FFMpegLoader fm; - - { - cout << "\nLoading cow.wav by filename:\n"; - SampleSourcePtr cow_file( new FFMpegSource("cow.wav") ); - run(cow_file); - } - - return 0; -} diff --git a/libs/mangle/sound/tests/openal_audiere_test.cpp b/libs/mangle/sound/tests/openal_audiere_test.cpp deleted file mode 100644 index ced7fe5d23..0000000000 --- a/libs/mangle/sound/tests/openal_audiere_test.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../filters/openal_audiere.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -OpenAL_Audiere_Factory mg; - -void play(const char* name, bool stream=false) -{ - // Only load streams if the backend supports it - if(stream && !mg.canLoadStream) - return; - - cout << "Playing " << name; - if(stream) cout << " (from stream)"; - cout << "\n"; - - SoundPtr snd; - - try - { - if(stream) - snd = mg.load(StreamPtr(new FileStream(name))); - else - snd = mg.load(name); - - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } -} - -int main() -{ - play("cow.wav"); - play("owl.ogg"); - play("cow.wav", true); - return 0; -} diff --git a/libs/mangle/sound/tests/openal_ffmpeg_test.cpp b/libs/mangle/sound/tests/openal_ffmpeg_test.cpp deleted file mode 100644 index d4b8e93003..0000000000 --- a/libs/mangle/sound/tests/openal_ffmpeg_test.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../filters/openal_ffmpeg.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -OpenAL_FFMpeg_Factory mg; - -void play(const char* name, bool stream=false) -{ - // Only load streams if the backend supports it - if(stream && !mg.canLoadStream) - return; - - cout << "Playing " << name; - if(stream) cout << " (from stream)"; - cout << "\n"; - - SoundPtr snd; - - try - { - if(stream) - snd = mg.load(StreamPtr(new FileStream(name))); - else - snd = mg.load(name); - - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } -} - -int main() -{ - play("cow.wav"); - play("owl.ogg"); - play("cow.wav", true); - return 0; -} diff --git a/libs/mangle/sound/tests/openal_mpg123_test.cpp b/libs/mangle/sound/tests/openal_mpg123_test.cpp deleted file mode 100644 index fef1a5605a..0000000000 --- a/libs/mangle/sound/tests/openal_mpg123_test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../filters/openal_mpg123.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -OpenAL_Mpg123_Factory mg; - -void play(const char* name, bool stream=false) -{ - // Only load streams if the backend supports it - if(stream && !mg.canLoadStream) - return; - - cout << "Playing " << name; - if(stream) cout << " (from stream)"; - cout << "\n"; - - SoundPtr snd; - - try - { - if(stream) - snd = mg.load(StreamPtr(new FileStream(name))); - else - snd = mg.load(name); - - snd->setStreaming(true); - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } -} - -int main(int argc, char**argv) -{ - if(argc != 2) - cout << "Please specify an MP3 file\n"; - else - play(argv[1]); - return 0; -} diff --git a/libs/mangle/sound/tests/openal_output_test.cpp b/libs/mangle/sound/tests/openal_output_test.cpp deleted file mode 100644 index a8059ec652..0000000000 --- a/libs/mangle/sound/tests/openal_output_test.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../sources/stream_source.hpp" -#include "../outputs/openal_out.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -int main() -{ - cout << "Loading cow.raw\n"; - - int rate = 11025; - int chan = 1; - int bits = 16; - - cout << " rate=" << rate << "\n channels=" << chan - << "\n bits=" << bits << endl; - - StreamPtr file( new FileStream("cow.raw") ); - SampleSourcePtr source( new Stream2Samples( file, rate, chan, bits)); - - cout << "Playing\n"; - - OpenAL_Factory mg; - - SoundPtr snd = mg.loadRaw(source); - - try - { - // Try setting all kinds of stuff before playing. OpenAL_Sound - // uses delayed buffer loading, but these should still work - // without a buffer. - snd->stop(); - snd->pause(); - snd->setVolume(0.8); - snd->setPitch(0.9); - - // Also test streaming, since all the other examples test - // non-streaming sounds. - snd->setStreaming(true); - - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } - return 0; -} diff --git a/libs/mangle/sound/tests/openal_sndfile_test.cpp b/libs/mangle/sound/tests/openal_sndfile_test.cpp deleted file mode 100644 index bd5f117a59..0000000000 --- a/libs/mangle/sound/tests/openal_sndfile_test.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../filters/openal_sndfile.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -OpenAL_SndFile_Factory mg; - -void play(const char* name, bool stream=false) -{ - // Only load streams if the backend supports it - if(stream && !mg.canLoadStream) - return; - - cout << "Playing " << name; - if(stream) cout << " (from stream)"; - cout << "\n"; - - SoundPtr snd; - - try - { - if(stream) - snd = mg.load(StreamPtr(new FileStream(name))); - else - snd = mg.load(name); - - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } -} - -int main() -{ - play("cow.wav"); - play("owl.ogg"); - play("cow.wav", true); - return 0; -} diff --git a/libs/mangle/sound/tests/openal_various_test.cpp b/libs/mangle/sound/tests/openal_various_test.cpp deleted file mode 100644 index 9426a672ec..0000000000 --- a/libs/mangle/sound/tests/openal_various_test.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include - -#include "../../stream/servers/file_stream.hpp" -#include "../filters/openal_various.hpp" - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; - -OpenAL_Various_Factory mg; - -void play(const char* name, bool stream=false) -{ - // Only load streams if the backend supports it - if(stream && !mg.canLoadStream) - return; - - cout << "Playing " << name; - if(stream) cout << " (from stream)"; - cout << "\n"; - - SoundPtr snd; - - try - { - if(stream) - snd = mg.load(StreamPtr(new FileStream(name))); - else - snd = mg.load(name); - - snd->play(); - - while(snd->isPlaying()) - { - usleep(10000); - if(mg.needsUpdate) mg.update(); - } - } - catch(exception &e) - { - cout << " ERROR: " << e.what() << "\n"; - } -} - -int main() -{ - play("cow.wav"); - play("cow.wav", true); - return 0; -} diff --git a/libs/mangle/sound/tests/output/audiere_source_test.out b/libs/mangle/sound/tests/output/audiere_source_test.out deleted file mode 100644 index 47a5a9e418..0000000000 --- a/libs/mangle/sound/tests/output/audiere_source_test.out +++ /dev/null @@ -1,21 +0,0 @@ -Reading cow.raw first -Size: 37502 -Done - -Loading cow.wav by filename: -Source size: 37502 -rate=11025 -channels=1 -bits=16 -Reading entire buffer into memory -Comparing... -Done - -Loading cow.wav by stream: -Source size: 37502 -rate=11025 -channels=1 -bits=16 -Reading entire buffer into memory -Comparing... -Done diff --git a/libs/mangle/sound/tests/output/ffmpeg_source_test.out b/libs/mangle/sound/tests/output/ffmpeg_source_test.out deleted file mode 100644 index 1c7d491139..0000000000 --- a/libs/mangle/sound/tests/output/ffmpeg_source_test.out +++ /dev/null @@ -1,12 +0,0 @@ -Reading cow.raw first -Size: 37502 -Done - -Loading cow.wav by filename: -rate=11025 -channels=1 -bits=16 -Reading entire buffer into memory -Actually read: 37502 -Comparing... -Done diff --git a/libs/mangle/sound/tests/output/openal_audiere_test.out b/libs/mangle/sound/tests/output/openal_audiere_test.out deleted file mode 100644 index 4fe01eac2b..0000000000 --- a/libs/mangle/sound/tests/output/openal_audiere_test.out +++ /dev/null @@ -1,3 +0,0 @@ -Playing cow.wav -Playing owl.ogg -Playing cow.wav (from stream) diff --git a/libs/mangle/sound/tests/output/openal_ffmpeg_test.out b/libs/mangle/sound/tests/output/openal_ffmpeg_test.out deleted file mode 100644 index 96e1db0f9a..0000000000 --- a/libs/mangle/sound/tests/output/openal_ffmpeg_test.out +++ /dev/null @@ -1,2 +0,0 @@ -Playing cow.wav -Playing owl.ogg diff --git a/libs/mangle/sound/tests/output/openal_mpg123_test.out b/libs/mangle/sound/tests/output/openal_mpg123_test.out deleted file mode 100644 index e55dabbb1d..0000000000 --- a/libs/mangle/sound/tests/output/openal_mpg123_test.out +++ /dev/null @@ -1 +0,0 @@ -Please specify an MP3 file diff --git a/libs/mangle/sound/tests/output/openal_output_test.out b/libs/mangle/sound/tests/output/openal_output_test.out deleted file mode 100644 index 04392a72e8..0000000000 --- a/libs/mangle/sound/tests/output/openal_output_test.out +++ /dev/null @@ -1,5 +0,0 @@ -Loading cow.raw - rate=11025 - channels=1 - bits=16 -Playing diff --git a/libs/mangle/sound/tests/output/openal_sndfile_test.out b/libs/mangle/sound/tests/output/openal_sndfile_test.out deleted file mode 100644 index 96e1db0f9a..0000000000 --- a/libs/mangle/sound/tests/output/openal_sndfile_test.out +++ /dev/null @@ -1,2 +0,0 @@ -Playing cow.wav -Playing owl.ogg diff --git a/libs/mangle/sound/tests/output/openal_various_test.out b/libs/mangle/sound/tests/output/openal_various_test.out deleted file mode 100644 index f25a555138..0000000000 --- a/libs/mangle/sound/tests/output/openal_various_test.out +++ /dev/null @@ -1 +0,0 @@ -Playing cow.wav diff --git a/libs/mangle/sound/tests/output/wav_source_test.out b/libs/mangle/sound/tests/output/wav_source_test.out deleted file mode 100644 index b6fc8e6fc8..0000000000 --- a/libs/mangle/sound/tests/output/wav_source_test.out +++ /dev/null @@ -1,12 +0,0 @@ -Source size: 37502 -rate=11025 -channels=1 -bits=16 -Reading entire buffer into memory - -Reading cow.raw -Size: 37502 - -Comparing... - -Done diff --git a/libs/mangle/sound/tests/owl.ogg b/libs/mangle/sound/tests/owl.ogg deleted file mode 100644 index e992f24d48..0000000000 Binary files a/libs/mangle/sound/tests/owl.ogg and /dev/null differ diff --git a/libs/mangle/sound/tests/test.sh b/libs/mangle/sound/tests/test.sh deleted file mode 100755 index 2d07708adc..0000000000 --- a/libs/mangle/sound/tests/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -make || exit - -mkdir -p output - -PROGS=*_test - -for a in $PROGS; do - if [ -f "output/$a.out" ]; then - echo "Running $a:" - ./$a | diff output/$a.out - - else - echo "Creating $a.out" - ./$a > "output/$a.out" - git add "output/$a.out" - fi -done diff --git a/libs/mangle/sound/tests/wav_source_test.cpp b/libs/mangle/sound/tests/wav_source_test.cpp deleted file mode 100644 index 749af18496..0000000000 --- a/libs/mangle/sound/tests/wav_source_test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include - -#include "../sources/wav_source.hpp" -#include "../../stream/servers/file_stream.hpp" - -#include -#include - -using namespace std; -using namespace Mangle::Sound; -using namespace Mangle::Stream; - -int main() -{ - WavSource wav("cow.wav"); - - cout << "Source size: " << wav.size() << endl; - int rate, channels, bits; - wav.getInfo(&rate, &channels, &bits); - cout << "rate=" << rate << "\nchannels=" << channels - << "\nbits=" << bits << endl; - - cout << "Reading entire buffer into memory\n"; - void *buf = malloc(wav.size()); - wav.read(buf, wav.size()); - - cout << "\nReading cow.raw\n"; - FileStream tmp("cow.raw"); - cout << "Size: " << tmp.size() << endl; - void *buf2 = malloc(tmp.size()); - tmp.read(buf2, tmp.size()); - - cout << "\nComparing...\n"; - if(tmp.size() != wav.size()) - { - cout << "SIZE MISMATCH!\n"; - assert(0); - } - - if(memcmp(buf, buf2, wav.size()) != 0) - { - cout << "CONTENT MISMATCH!\n"; - assert(0); - } - - cout << "\nDone\n"; - return 0; -} diff --git a/libs/openengine/sound/sndmanager.cpp b/libs/openengine/sound/sndmanager.cpp deleted file mode 100644 index 02c6ba1e77..0000000000 --- a/libs/openengine/sound/sndmanager.cpp +++ /dev/null @@ -1,219 +0,0 @@ -#include "sndmanager.hpp" - -#include "../misc/list.hpp" -#include - -using namespace OEngine::Sound; -using namespace Mangle::Sound; - -/** This is our own internal implementation of the - Mangle::Sound::Sound interface. This class links a SoundPtr to - itself and prevents itself from being deleted as long as the sound - is playing. - */ -struct OEngine::Sound::ManagedSound : SoundFilter -{ -private: - /** Who's your daddy? This is set if and only if we are listed - internally in the given SoundManager. - - It may be NULL if the manager has been deleted but the user - keeps their own SoundPtrs to the object. - */ - SoundManager *mgr; - - /** Keep a weak pointer to ourselves, which we convert into a - 'strong' pointer when we are playing. When 'self' is pointing to - ourselves, the object will never be deleted. - - This is used to make sure the sound is not deleted while - playing, unless it is explicitly ordered to do so by the - manager. - - TODO: This kind of construct is useful. If we need it elsewhere - later, template it. It would be generally useful in any system - where we poll to check if a resource is still needed, but where - manual references are allowed. - */ - WSoundPtr weak; - SoundPtr self; - - // Keep this object from being deleted - void lock() - { - self = SoundPtr(weak); - } - - // Release the lock. This may or may not delete the object. Never do - // anything after calling unlock()! - void unlock() - { - self.reset(); - } - -public: - // Used for putting ourselves in linked lists - ManagedSound *next, *prev; - - /** Detach this sound from its manager. This means that the manager - will no longer know we exist. Typically only called when either - the sound or the manager is about to get deleted. - - Since this means update() will no longer be called, we also have - to unlock the sound manually since it will no longer be able to - do that itself. This means that the sound may be deleted, even - if it is still playing, when the manager is deleted. - - However, you are still allowed to keep and manage your own - SoundPtr references, but the lock/unlock system is disabled - after the manager is gone. - */ - void detach() - { - if(mgr) - { - mgr->detach(this); - mgr = NULL; - } - - // Unlock must be last command. Object may get deleted at this - // point. - unlock(); - } - - ManagedSound(SoundPtr snd, SoundManager *mg) - : SoundFilter(snd), mgr(mg) - {} - ~ManagedSound() { detach(); } - - // Needed to set up the weak pointer - void setup(SoundPtr self) - { - weak = WSoundPtr(self); - } - - // Override play() to mark the object as locked - void play() - { - SoundFilter::play(); - - // Lock the object so that it is not deleted while playing. Only - // do this if we have a manager, otherwise the object will never - // get unlocked. - if(mgr) lock(); - } - - // Called regularly by the manager - void update() - { - // If we're no longer playing, don't force object retention. - if(!isPlaying()) - unlock(); - - // unlock() may delete the object, so don't do anything below this - // point. - } - - SoundPtr clone() - { - // Cloning only works when we have a manager. - assert(mgr); - return mgr->wrap(client->clone()); - } -}; - -struct SoundManager::SoundManagerList -{ -private: - // A linked list of ManagedSound objects. - typedef Misc::List SoundList; - SoundList list; - -public: - // Add a new sound to the list - void addNew(ManagedSound* snd) - { - list.insert(snd); - } - - // Remove a sound from the list - void remove(ManagedSound *snd) - { - list.remove(snd); - } - - // Number of sounds in the list - int numSounds() { return list.getNum(); } - - // Update all sounds - void updateAll() - { - ManagedSound *s = list.getHead(); - while(s) - { - ManagedSound *cur = s; - // Propagate first, since update() may delete object - s = s->next; - cur->update(); - } - } - - // Detach and unlock all sounds - void detachAll() - { - ManagedSound *s = list.getHead(); - while(s) - { - ManagedSound *cur = s; - s = s->next; - cur->detach(); - } - } -}; - -SoundManager::SoundManager(SoundFactoryPtr fact) - : FactoryFilter(fact) -{ - needsUpdate = true; - list = new SoundManagerList; -} - -SoundManager::~SoundManager() -{ - // Detach all sounds - list->detachAll(); -} - -SoundPtr SoundManager::wrap(SoundPtr client) -{ - // Create and set up the sound wrapper - ManagedSound *snd = new ManagedSound(client,this); - SoundPtr ptr(snd); - snd->setup(ptr); - - // Add ourselves to the list of all sounds - list->addNew(snd); - - return ptr; -} - -// Remove the sound from this manager. -void SoundManager::detach(ManagedSound *sound) -{ - list->remove(sound); -} - -int SoundManager::numSounds() -{ - return list->numSounds(); -} - -void SoundManager::update() -{ - // Update all the sounds we own - list->updateAll(); - - // Update the source if it needs it - if(client->needsUpdate) - client->update(); -} diff --git a/libs/openengine/sound/sndmanager.hpp b/libs/openengine/sound/sndmanager.hpp deleted file mode 100644 index 5ea0c4fc37..0000000000 --- a/libs/openengine/sound/sndmanager.hpp +++ /dev/null @@ -1,93 +0,0 @@ -#ifndef OENGINE_SOUND_MANAGER_H -#define OENGINE_SOUND_MANAGER_H - -#include - -namespace OEngine -{ - namespace Sound - { - using namespace Mangle::Sound; - - class ManagedSound; - - /** A manager of Mangle::Sounds. - - The sound manager is a wrapper around the more low-level - SoundFactory - although it is also itself an implementation of - SoundFactory. It will: - - keep a list of all created sounds - - let you iterate the list - - keep references to playing sounds so you don't have to - - auto-release references to sounds that are finished playing - (ie. deleting them if you're not referencing them) - */ - class SoundManager : public FactoryFilter - { - // Shove the implementation details into the cpp file. - struct SoundManagerList; - SoundManagerList *list; - - // Create a new sound wrapper based on the given source sound. - SoundPtr wrap(SoundPtr snd); - - /** Internal function. Will completely disconnect the given - sound from this manager. Called from ManagedSound. - */ - friend class ManagedSound; - void detach(ManagedSound *sound); - public: - SoundManager(SoundFactoryPtr fact); - ~SoundManager(); - void update(); - - /// Get number of sounds currently managed by this manager. - int numSounds(); - - SoundPtr loadRaw(SampleSourcePtr input) - { return wrap(client->loadRaw(input)); } - - SoundPtr load(Mangle::Stream::StreamPtr input) - { return wrap(client->load(input)); } - - SoundPtr load(const std::string &file) - { return wrap(client->load(file)); } - - // Play a sound immediately, and release when done unless you - // keep the returned SoundPtr. - SoundPtr play(Mangle::Stream::StreamPtr sound) - { - SoundPtr snd = load(sound); - snd->play(); - return snd; - } - - SoundPtr play(const std::string &sound) - { - SoundPtr snd = load(sound); - snd->play(); - return snd; - } - - // Ditto for 3D sounds - SoundPtr play3D(Mangle::Stream::StreamPtr sound, float x, float y, float z) - { - SoundPtr snd = load(sound); - snd->setPos(x,y,z); - snd->play(); - return snd; - } - - SoundPtr play3D(const std::string &sound, float x, float y, float z) - { - SoundPtr snd = load(sound); - snd->setPos(x,y,z); - snd->play(); - return snd; - } - }; - - typedef boost::shared_ptr SoundManagerPtr; - } -} -#endif diff --git a/libs/openengine/sound/tests/Makefile b/libs/openengine/sound/tests/Makefile deleted file mode 100644 index 04952167f7..0000000000 --- a/libs/openengine/sound/tests/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -GCC=g++ -I../ - -all: sound_manager_test sound_3d_test - -L_FFMPEG=$(shell pkg-config --libs libavcodec libavformat) -L_OPENAL=$(shell pkg-config --libs openal) -L_AUDIERE=-laudiere - -sound_manager_test: sound_manager_test.cpp ../../mangle/sound/sources/audiere_source.cpp ../../mangle/sound/outputs/openal_out.cpp ../../mangle/stream/clients/audiere_file.cpp ../sndmanager.cpp - $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) -I../.. - -sound_3d_test: sound_3d_test.cpp ../../mangle/sound/sources/audiere_source.cpp ../../mangle/sound/outputs/openal_out.cpp ../../mangle/stream/clients/audiere_file.cpp ../sndmanager.cpp - $(GCC) $^ -o $@ $(L_AUDIERE) $(L_OPENAL) -I../.. - -clean: - rm *_test diff --git a/libs/openengine/sound/tests/output/sound_3d_test.out b/libs/openengine/sound/tests/output/sound_3d_test.out deleted file mode 100644 index a443c84f02..0000000000 --- a/libs/openengine/sound/tests/output/sound_3d_test.out +++ /dev/null @@ -1,3 +0,0 @@ -Playing at 0,0,0 -Playing at 1,1,0 -Playing at -1,0,0 diff --git a/libs/openengine/sound/tests/output/sound_manager_test.out b/libs/openengine/sound/tests/output/sound_manager_test.out deleted file mode 100644 index 2b458493d2..0000000000 --- a/libs/openengine/sound/tests/output/sound_manager_test.out +++ /dev/null @@ -1,5 +0,0 @@ -Playing ../../mangle/sound/tests/cow.wav -Replaying -pause -restart -Done playing. diff --git a/libs/openengine/sound/tests/sound_3d_test.cpp b/libs/openengine/sound/tests/sound_3d_test.cpp deleted file mode 100644 index f5b197fd0b..0000000000 --- a/libs/openengine/sound/tests/sound_3d_test.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include -#include - -#include -#include - -#include - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; -using namespace OEngine::Sound; - -const std::string sound = "../../mangle/sound/tests/cow.wav"; - -SoundManagerPtr m; - -// Play and wait for finish -void play(float x, float y, float z) -{ - cout << "Playing at " << x << "," << y << "," << z << endl; - - SoundPtr snd = m->play3D(sound,x,y,z); - - while(snd->isPlaying()) - { - usleep(10000); - m->update(); - } -} - -int main() -{ - SoundFactoryPtr oaf(new OpenAL_Audiere_Factory); - SoundManagerPtr mg(new SoundManager(oaf)); - m = mg; - - mg->setListenerPos(0,0,0,0,1,0,0,0,1); - - play(0,0,0); - play(1,1,0); - play(-1,0,0); - - return 0; -} diff --git a/libs/openengine/sound/tests/sound_manager_test.cpp b/libs/openengine/sound/tests/sound_manager_test.cpp deleted file mode 100644 index 3794c4a3cf..0000000000 --- a/libs/openengine/sound/tests/sound_manager_test.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include -#include -#include - -#include -#include - -#include - -using namespace std; -using namespace Mangle::Stream; -using namespace Mangle::Sound; -using namespace OEngine::Sound; - -const std::string sound = "../../mangle/sound/tests/cow.wav"; - -int main() -{ - SoundFactoryPtr oaf(new OpenAL_Audiere_Factory); - SoundManagerPtr mg(new SoundManager(oaf)); - - cout << "Playing " << sound << "\n"; - - assert(mg->numSounds() == 0); - - /** Start the sound playing, and then let the pointer go out of - scope. Lower-level players (like 'oaf' above) will immediately - delete the sound. SoundManager OTOH will keep it until it's - finished. - */ - mg->play(sound); - - assert(mg->numSounds() == 1); - - // Loop while there are still sounds to manage - while(mg->numSounds() != 0) - { - assert(mg->numSounds() == 1); - usleep(10000); - if(mg->needsUpdate) - mg->update(); - } - - SoundPtr snd = mg->play(sound); - cout << "Replaying\n"; - int i = 0; - while(mg->numSounds() != 0) - { - assert(mg->numSounds() == 1); - usleep(10000); - if(mg->needsUpdate) - mg->update(); - - if(i++ == 70) - { - cout << "pause\n"; - snd->pause(); - } - if(i == 130) - { - cout << "restart\n"; - snd->play(); - // Let the sound go out of scope - snd.reset(); - } - } - - cout << "Done playing.\n"; - - assert(mg->numSounds() == 0); - - return 0; -} diff --git a/libs/openengine/sound/tests/test.sh b/libs/openengine/sound/tests/test.sh deleted file mode 100755 index 2d07708adc..0000000000 --- a/libs/openengine/sound/tests/test.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -make || exit - -mkdir -p output - -PROGS=*_test - -for a in $PROGS; do - if [ -f "output/$a.out" ]; then - echo "Running $a:" - ./$a | diff output/$a.out - - else - echo "Creating $a.out" - ./$a > "output/$a.out" - git add "output/$a.out" - fi -done