From 40879d8defbfd44fd4dd711a59cdfaadf7e20991 Mon Sep 17 00:00:00 2001 From: Josh Yelon Date: Wed, 22 Aug 2007 17:28:34 +0000 Subject: [PATCH] More work on OpenAL --- panda/src/audiotraits/config_fmodAudio.cxx | 2 - panda/src/audiotraits/fmodAudioDSP.I | 25 -- panda/src/audiotraits/fmodAudioDSP.cxx | 448 ------------------ panda/src/audiotraits/fmodAudioDSP.h | 164 ------- panda/src/audiotraits/openalAudioManager.cxx | 449 +++++++++---------- panda/src/audiotraits/openalAudioManager.h | 71 +-- panda/src/audiotraits/openalAudioSound.cxx | 305 +++++-------- panda/src/audiotraits/openalAudioSound.h | 25 +- 8 files changed, 395 insertions(+), 1094 deletions(-) delete mode 100644 panda/src/audiotraits/fmodAudioDSP.I delete mode 100644 panda/src/audiotraits/fmodAudioDSP.cxx delete mode 100644 panda/src/audiotraits/fmodAudioDSP.h diff --git a/panda/src/audiotraits/config_fmodAudio.cxx b/panda/src/audiotraits/config_fmodAudio.cxx index 797fd638d1..35550d7646 100644 --- a/panda/src/audiotraits/config_fmodAudio.cxx +++ b/panda/src/audiotraits/config_fmodAudio.cxx @@ -23,7 +23,6 @@ #include "config_fmodAudio.h" #include "fmodAudioManager.h" #include "fmodAudioSound.h" -#include "fmodAudioDSP.h" #include "pandaSystem.h" #include "dconfig.h" @@ -55,7 +54,6 @@ init_libFmodAudio() { FmodAudioManager::init_type(); FmodAudioSound::init_type(); - FmodAudioDSP::init_type(); PandaSystem *ps = PandaSystem::get_global_ptr(); ps->add_system("FMOD"); diff --git a/panda/src/audiotraits/fmodAudioDSP.I b/panda/src/audiotraits/fmodAudioDSP.I deleted file mode 100644 index 30a5196d7a..0000000000 --- a/panda/src/audiotraits/fmodAudioDSP.I +++ /dev/null @@ -1,25 +0,0 @@ -// Filename: fmodAudioDSP.I -// Created by: Stan Rosenbaum "Staque" - Spring 2006 -// -// -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - - - - - - diff --git a/panda/src/audiotraits/fmodAudioDSP.cxx b/panda/src/audiotraits/fmodAudioDSP.cxx deleted file mode 100644 index 0424b174b5..0000000000 --- a/panda/src/audiotraits/fmodAudioDSP.cxx +++ /dev/null @@ -1,448 +0,0 @@ -// Filename: fmodAudioDSP.cxx -// Created by: Stan Rosenbaum "Staque" - Spring 2006 -// -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "pandabase.h" -#include "dcast.h" - -#ifdef HAVE_FMODEX //[ - -//Panda Headers -#include "config_audio.h" -#include "fmodAudioDSP.h" - - -TypeHandle FmodAudioDSP::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::FmodAudioDSP -// Access: Protected -// Description: Constructor -// This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -FmodAudioDSP:: -FmodAudioDSP(AudioManager *manager, AudioManager::DSP_category cat) { - // Intentionally blank. - - audio_debug("FmodAudioDSP::FmodAudioDSP() Creating new DSP " ); - - //Local Variables that are needed. - FMOD_RESULT result; - - //Assign the values we need - DCAST_INTO_V(_manager, manager); - - FMOD_DSP_TYPE dsptype = (FMOD_DSP_TYPE)cat; - - result = _manager->_system->createDSPByType( dsptype, &_dsp); - fmod_audio_errcheck("_system->createDSPByType()", result); - - set_in_chain(false); - - audio_debug("DSP Loaded"); -} - - - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::Destructor -// Access: Published, Virtual -// Description: DESTRUCTOR!!! -//////////////////////////////////////////////////////////////////// -FmodAudioDSP:: -~FmodAudioDSP() { - audio_debug("FmodAudioSound::FmodAudioDSP() Destruction!!! " ); - - //Local Variables that are needed. - FMOD_RESULT result; - - result = _dsp->remove(); - fmod_audio_errcheck("_dsp->remove()", result); - - result = _dsp->release(); - fmod_audio_errcheck("_dsp->release()", result); - - audio_debug("DSP GONE"); -} - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::reset -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -// [This resets an FMOD DSP to its default values] -//////////////////////////////////////////////////////////////////// -void FmodAudioDSP:: -reset() { - audio_debug("FmodAudioSound::reset() Reset DSP to default settings." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - result = _dsp->reset(); - fmod_audio_errcheck("_dsp->reset()", result); - - audio_debug("DSP Reset."); -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::remove -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -// [This removes the DSP from an Effects Chain] -//////////////////////////////////////////////////////////////////// -void FmodAudioDSP:: -remove() { - audio_debug("FmodAudioSound::remove() Removes a DSP from and effect chain." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - result = _dsp->remove(); - fmod_audio_errcheck("_dsp->remove()", result); - - audio_debug("DSP Removed from relative effects chain."); -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::set_bypass -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -// [This turns the Bypass for an Effect on and off]/ -//////////////////////////////////////////////////////////////////// -void FmodAudioDSP:: -set_bypass(bool bypass) { - audio_debug("FmodAudioSound::set_bypass() ." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - result = _dsp->setBypass(bypass); - fmod_audio_errcheck("_dsp->setBypass()", result); - - audio_debug("DSP Bypass set to:" << bypass ); -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_bypass -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -bool FmodAudioDSP:: -get_bypass() { - audio_debug("FmodAudioSound::get_bypass() ." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - bool bypass; - - result = _dsp->getBypass(&bypass); - fmod_audio_errcheck("_dsp->getBypass()", result); - - return bypass; -} - - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::set_parameter -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -void FmodAudioDSP:: -set_parameter(const string &name, float value) { - int parameterIndex = find_parameter(name); - if (parameterIndex < 0) { - return; - } - - //Local Variables that are needed. - FMOD_RESULT result; - - result = _dsp->setParameter(parameterIndex, value); - fmod_audio_errcheck("_dsp->setParameter()", result); -} - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_num_parameters -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -int FmodAudioDSP:: -get_num_parameters() { - audio_debug("FmodAudioSound::get_num_parameters() ." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - int numOfParameters; - - result = _dsp->getNumParameters(&numOfParameters); - fmod_audio_errcheck("_dsp->getNumParameters()", result); - - return numOfParameters; -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_parameter_name -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -string FmodAudioDSP:: -get_parameter_name(int parameterIndex) { - - audio_debug("FmodAudioSound::get_parameter_name()" ); - - //Local Variables that are needed. - FMOD_RESULT result; - - //int parameterIndex; - char parameterName[32]; - char parameterLabel[32]; - char parameterDescription[32]; - int parameterDescriptionLength = 0; - float parameterMin; - float parameterMax; - - result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax); - fmod_audio_errcheck("_dsp->getParameterInfo()", result); - - string returnInfo = (parameterName); - - return returnInfo; - - //return ""; -} - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_parameter_description -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -// This Method actually returns FMOD's Parameter Label -// Information, and not Description. -// The reason is, that most of the FMOD's Description -// Properties seem to be empty. -// Also the Label sort of serves as as a description by -// return the type of unit the cooresponding parameter -// modifies for a DSP. -// IE. For the Echo. The first parameter is 'Delay' -// and the units for measuring the Delay is in Milliseconds. -// The Label returns Milliseconds letting you know that. -//////////////////////////////////////////////////////////////////// -string FmodAudioDSP:: -get_parameter_description(int parameterIndex) { - // intentionally blank - - audio_debug("FmodAudioSound::get_parameter_description()." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - //int parameterIndex; - char parameterName[32]; - char parameterLabel[32]; - char parameterDescription[32]; - int parameterDescriptionLength = 0; - float parameterMin; - float parameterMax; - - result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax); - fmod_audio_errcheck("_dsp->getParameterInfo()", result); - - return parameterLabel; - -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_parameter_min -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -float FmodAudioDSP:: -get_parameter_min(int parameterIndex) { - - audio_debug("FmodAudioSound::get_parameter_min()." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - //int parameterIndex; - char parameterName[32]; - char parameterLabel[32]; - char parameterDescription[32]; - int parameterDescriptionLength = 0; - float parameterMin; - float parameterMax; - - result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax); - fmod_audio_errcheck("_dsp->getParameterInfo()", result); - - return parameterMin; -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_parameter_max -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -float FmodAudioDSP:: -get_parameter_max(int parameterIndex) { - - audio_debug("FmodAudioSound::get_parameter_min()." ); - - //Local Variables that are needed. - FMOD_RESULT result; - - //int parameterIndex; - char parameterName[32]; - char parameterLabel[32]; - char parameterDescription[32]; - int parameterDescriptionLength = 0; - float parameterMin; - float parameterMax; - - result = _dsp->getParameterInfo(parameterIndex, parameterName, parameterLabel, parameterDescription, parameterDescriptionLength, ¶meterMin, ¶meterMax); - fmod_audio_errcheck("_dsp->getParameterInfo()", result); - - return parameterMax; -} - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_parameter_value -// Access: Published, Virtual -// Description: This is a thin wrapper around FMOD-EX. -// See the FMOD-EX documentation. -//////////////////////////////////////////////////////////////////// -float FmodAudioDSP:: -get_parameter_value(const string &name) { - - int parameterIndex = find_parameter(name); - if (parameterIndex < 0) { - return 0.0; - } - - //Local Variables that are needed. - FMOD_RESULT result; - - float parameterValue; - char valuestr[32]; - int valuestrlen = 32; - - - result = _dsp->getParameter(parameterIndex, ¶meterValue, valuestr, valuestrlen); - fmod_audio_errcheck("_dsp->getParameter()", result); - - return parameterValue; -} - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::find_parameter -// Access: Private -// Description: Convert a parameter name to an fmod parameter index. -//////////////////////////////////////////////////////////////////// -int FmodAudioDSP:: -find_parameter(const string &name) { - int np = get_num_parameters(); - for (int i=0; igetInfo(name, &version, &channels, &configwidth, &configheight); - fmod_audio_errcheck("_dsp->getInfo()", result); - - string returnInfo = (name); - //returnInfo.append(" Version: "); - //returnInfo.append(version); - //returnInfo.append("\n"); - - return returnInfo; -} - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::get_in_chain() -// Access: Published, Virtual -// Description: This is a functiont to query if a DSP have been assigned -// to the GLOBAL or a SOUND's effect chain. -// This is to make sure you 'remove' an effect from a chain -// before you move it somewhere else or destroy it. -//////////////////////////////////////////////////////////////////// -bool FmodAudioDSP:: -get_in_chain() { - audio_debug("FmodAudioSound::get_in_chain()." ); - - return _in_chain; -} - - -//////////////////////////////////////////////////////////////////// -// Function: FmodAudioDSP::set_in_chain() -// Access: Published, Virtual -// Description: This is a functiont to set if a DSP have been assigned -// to the GLOBAL or a SOUND's effect chain. -//////////////////////////////////////////////////////////////////// -void FmodAudioDSP:: -set_in_chain(bool chain_state) { - audio_debug("FmodAudioSound::set_in_chain()." ); - - _in_chain = chain_state; -} - - -#endif //] diff --git a/panda/src/audiotraits/fmodAudioDSP.h b/panda/src/audiotraits/fmodAudioDSP.h deleted file mode 100644 index d9418d218e..0000000000 --- a/panda/src/audiotraits/fmodAudioDSP.h +++ /dev/null @@ -1,164 +0,0 @@ -// Filename: fmodAudioDSP.h -// Created by: Stan Rosenbaum "Staque" - Spring 2006 -// -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// -//[FIRST READ FmodAudioManager and then maybe FmodAudioSound for an Introduction -//if you haven't already]. -// -//Hello, all future Panda audio code people! This is my errata documentation to -//Help any future programmer maintain FMOD and PANDA. -// -//Finally let’s talk about the DSP, or Digital Signal Processing. To the layman, -//these are filters and shaders for sound. -// -//Currently FmodAudioDSP give you access to all of FMOD’s built in DSP functions. -// -//The enumerated list for the types are found in the 'AudioManager.h’, but I will -//repeat it here for good fortune. -// -// enum DSP_category { -// // These enumerants line up one-to-one -// // with the FMOD DSP enumerants. -// DSP_unknown, -// DSP_mixer, -// DSP_oscillator, -// DSP_lowpass, -// DSP_itlowpass, -// DSP_highpass, -// DSP_echo, -// DSP_flange, -// DSP_distortion, -// DSP_normalize, -// DSP_parameq, -// DSP_pitchshift, -// DSP_chorus, -// DSP_reverb, -// DSP_vstplugin, -// DSP_winampplugin, -// DSP_itecho, -// DSP_COUNT -// }; -// -//Now, I want to point a couple things out. First, we have to place the above list -//in AudioManager.h because that was the only way to them to be 'PUBLISHED’ in -//Panda’s Python bindings when you build Panda. -// -//Second, you only need to use the 'it####’ named DSP effects if you are using -//mod/tracker files. [If you don’t know what a mod/tracker file is you probably -//aren’t using them so don’t worry about it.] -// -//I think that is everything, the DSP info was pretty short. -//////////////////////////////////////////////////////////////////// -// - - - -#ifndef __FMOD_AUDIO_DSP_H__ -#define __FMOD_AUDIO_DSP_H__ - -#include - -#ifdef HAVE_FMODEX //[ - -#include "audioManager.h" -#include "audioDSP.h" - -#include -#include - -class EXPCL_FMOD_AUDIO FmodAudioDSP : public AudioDSP { - - public: - - FmodAudioDSP(AudioManager *mgr, AudioManager::DSP_category); - - virtual void reset(); - virtual void remove(); - virtual void set_bypass(bool bypass); - virtual void set_parameter(const string &name, float value); - virtual float get_parameter_value(const string &name); - - virtual bool get_bypass(); - - virtual int get_num_parameters(); - virtual string get_parameter_name(int index); - virtual string get_parameter_description(int index); - virtual float get_parameter_min(int index); - virtual float get_parameter_max(int index); - - bool get_in_chain(); - void set_in_chain(bool chain_state); - - virtual ~FmodAudioDSP(); - - protected: - virtual string get_dsp_name(); - - - private: - int find_parameter(const string &pn); - - bool _in_chain; - FmodAudioManager *_manager; - FMOD::DSP *_dsp; - - friend class FmodAudioManager; - friend class FmodAudioSound; - - - //////////////////////////////////////////////////////////// - //These are needed for Panda's Pointer System. DO NOT ERASE! - //////////////////////////////////////////////////////////// - - public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - AudioDSP::init_type(); - register_type(_type_handle, "FmodAudioDSP", AudioDSP::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() { - init_type(); - return get_class_type(); - } - - private: - static TypeHandle _type_handle; - - //////////////////////////////////////////////////////////// - //DONE - //////////////////////////////////////////////////////////// - -}; - -#include "fmodAudioDSP.I" - -#endif //] - -#endif /* __FMOD_AUDIO_DSP_H__ */ - - - - - - - - diff --git a/panda/src/audiotraits/openalAudioManager.cxx b/panda/src/audiotraits/openalAudioManager.cxx index 57e4f7fe96..7b309d9aaf 100644 --- a/panda/src/audiotraits/openalAudioManager.cxx +++ b/panda/src/audiotraits/openalAudioManager.cxx @@ -80,9 +80,9 @@ PT(AudioManager) Create_AudioManager() { //////////////////////////////////////////////////////////////////// -// Function: OpenALAudioManager::OpenALAudioManager() +// Function: OpenALAudioManager::Constructor // Access: Public -// Description: Constructor +// Description: //////////////////////////////////////////////////////////////////// OpenALAudioManager:: OpenALAudioManager() { @@ -164,9 +164,9 @@ OpenALAudioManager() { } //////////////////////////////////////////////////////////////////// -// Function: OpenALAudioManager::~OpenALAudioManager +// Function: OpenALAudioManager::Destructor // Access: Public -// Description: DESTRCUTOR !!! +// Description: //////////////////////////////////////////////////////////////////// OpenALAudioManager:: ~OpenALAudioManager() { @@ -214,22 +214,7 @@ shutdown() { //////////////////////////////////////////////////////////////////// bool OpenALAudioManager:: is_valid() { - bool check=true; - if (_sounds.size() != _lru.size()) { - audio_debug("-- Error _sounds.size() != _lru.size() --"); - check=false; - } else { - LRU::const_iterator i=_lru.begin(); - for (; i != _lru.end(); ++i) { - SoundMap::const_iterator smi=_sounds.find(**i); - if (smi == _sounds.end()) { - audio_debug("-- "<<**i<<" in _lru and not in _sounds --"); - check=false; - break; - } - } - } - return _is_valid && check; + return _is_valid; } //////////////////////////////////////////////////////////////////// @@ -245,40 +230,66 @@ make_current() const { alc_audio_errcheck("alcMakeContextCurrent(_context)",_device); } - //////////////////////////////////////////////////////////////////// -// Function: OpenALAudioManager::load +// Function: OpenALAudioManager::can_use_audio // Access: Private -// Description: Reads a sound file and allocates a SoundData pointer -// for it. Returns NULL if the sound file cannot be -// loaded. +// Description: Returns true if the specified MovieAudioCursor +// can be used by this AudioManager. Mostly, this +// involves checking whether or not the format is +// implemented/supported. //////////////////////////////////////////////////////////////////// -PT(OpenALAudioManager::SoundData) OpenALAudioManager:: -load(Filename file_name) { - string raw_data; - PT(SoundData) sd = new SoundData(this); - - sd->_basename = file_name.get_basename(); - - make_current(); - - PT(MovieAudioCursor) source = MovieAudio::get(file_name)->open(); - if (source == 0) { - audio_error("Could not load audio file "<audio_channels(); if ((channels != 1)&&(channels != 2)) { audio_error("Currently, only mono and stereo are supported."); - return NULL; - } - int samples = (int)(source->length() * source->audio_rate()); - if (samples > 10000000) { - audio_error("Sound is too long for loading into RAM."); - return NULL; + return false; } + return true; +} +//////////////////////////////////////////////////////////////////// +// Function: OpenALAudioManager::can_load_audio +// Access: Private +// Description: Returns true if the specified MovieAudio can be +// cached into RAM. To be cached, the data must have +// a filename (otherwise, we have no cache key), and it +// must not take too many bytes. +//////////////////////////////////////////////////////////////////// +bool OpenALAudioManager:: +can_load_audio(MovieAudioCursor *source) { + if (source->get_source()->get_filename().empty()) { + return false; + } + if (source->length() > 60.0) { + return false; + } + int channels = source->audio_channels(); + int samples = (int)(source->length() * source->audio_rate()); + int bytes = samples * channels * 2; + if (bytes > 200000000) { + return false; + } + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenALAudioManager::load_sound_data +// Access: Private +// Description: Reads a sound file and creates a SoundData. +// When you are done with the SoundData, you need +// to decrement the client count. +//////////////////////////////////////////////////////////////////// +OpenALAudioManager::SoundData *OpenALAudioManager:: +load_sound_data(MovieAudioCursor *source) { + + nassertr(can_use_audio(source), NULL); + nassertr(can_load_audio(source), NULL); + + make_current(); + Filename path = source->get_source()->get_filename(); + SoundData *sd = new SoundData(this, path); + alGetError(); // clear errors sd->_buffer = 0; alGenBuffers(1, &sd->_buffer); @@ -287,6 +298,9 @@ load(Filename file_name) { audio_error("Could not create an OpenAL buffer object"); return NULL; } + + int channels = source->audio_channels(); + int samples = (int)(source->length() * source->audio_rate()); PN_int16 *data = new PN_int16[samples * channels]; source->read_samples(samples, data); @@ -299,11 +313,33 @@ load(Filename file_name) { alDeleteBuffers(1, &sd->_buffer); return NULL; } - audio_debug("Loaded "<length()); - double len = sd->get_length(); + sd->_rate = source->audio_rate(); + sd->_channels = source->audio_channels(); + sd->_length = source->length(); + _all_sound_data.insert(SoundDataSet::value_type(path, sd)); return sd; } +//////////////////////////////////////////////////////////////////// +// Function: OpenALAudioManager::cached_sound_data +// Access: Private +// Description: Looks in the cache for the specified sound data, +// and returns it if present. +// +// When you are done with the SoundData, you need +// to decrement the client count. +//////////////////////////////////////////////////////////////////// +OpenALAudioManager::SoundData *OpenALAudioManager:: +cached_sound_data(const Filename &path) { + SoundDataSet::const_iterator si=_all_sound_data.find(path); + if (si != _all_sound_data.end()) { + SoundData *sd = (*si).second; + increment_client_count(sd); + return sd; + } + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: OpenALAudioManager::get_sound() // Access: Public @@ -311,137 +347,76 @@ load(Filename file_name) { //////////////////////////////////////////////////////////////////// PT(AudioSound) OpenALAudioManager:: get_sound(const string &file_name, bool positional) { - audio_debug("OpenALAudioManager::get_sound(file_name=\""<resolve_filename(path, get_sound_path()) || vfs->resolve_filename(path, get_model_path()); - audio_debug(" resolved file_name is '"<= (unsigned int)_cache_limit) { - uncache_a_sound(); - } - // Put it in the pool: - // The following is roughly like: _sounds[path] = sd; - // But, it gives us an iterator into the map. - pair ib - =_sounds.insert(SoundMap::value_type(path, sd)); - if (!ib.second) { - // The insert failed. - audio_debug(" failed map insert of "<open(); + if (cursor == 0) { + audio_error("Cannot open file: "<set_active(_active); - bool inserted = _sounds_on_loan.insert(openalAudioSound).second; - nassertr(inserted, openalAudioSound.p()); - audioSound=openalAudioSound; + + PT(OpenALAudioSound) oas = + new OpenALAudioSound(this, path, cursor, sd, positional); + + if (oas->get_active()) { + _all_audio_sounds.insert(oas); + PT(AudioSound) res = (AudioSound*)(OpenALAudioSound*)oas; + return res; } - - audio_debug(" returning 0x" << (void*)audioSound); - assert(is_valid()); - return audioSound; + return NULL; } //////////////////////////////////////////////////////////////////// // Function: OpenALAudioManager::uncache_sound // Access: Public -// Description: +// Description: Deletes a sound from the expiration queue. +// If the sound is actively in use, then the sound +// cannot be deleted, and this function has no effect. //////////////////////////////////////////////////////////////////// void OpenALAudioManager:: uncache_sound(const string& file_name) { - audio_debug("OpenALAudioManager::uncache_sound(file_name=\"" - <resolve_filename(path, get_sound_path()) || vfs->resolve_filename(path, get_model_path()); - - audio_debug(" path=\""<0); - LRU::iterator lru_i=find(_lru.begin(), _lru.end(), &(i->first)); - assert(lru_i != _lru.end()); - _lru.erase(lru_i); - _sounds.erase(i); + + SoundDataSet::iterator sdi=_all_sound_data.find(path); + if (sdi != _all_sound_data.end()) { + SoundData *sd = (*sdi).second; + ExpirationQueue::iterator exi = + find(_expiration_queue.begin(), _expiration_queue.end(), sd); + if (exi != _expiration_queue.end()) { + _expiration_queue.erase(exi); + _all_sound_data.erase(sdi); + delete sd; + } } - assert(is_valid()); -} - -//////////////////////////////////////////////////////////////////// -// Function: OpenALAudioManager::uncache_a_sound -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void OpenALAudioManager:: -uncache_a_sound() { - audio_debug("OpenALAudioManager::uncache_a_sound()"); - assert(is_valid()); - // uncache least recently used: - assert(_lru.size()>0); - LRU::reference path=_lru.front(); - SoundMap::iterator i = _sounds.find(*path); - assert(i != _sounds.end()); - _lru.pop_front(); - - if (i != _sounds.end()) { - audio_debug(" uncaching \""<first<<"\""); - _sounds.erase(i); - } - assert(is_valid()); -} - -//////////////////////////////////////////////////////////////////// -// Function: OpenALAudioManager::most_recently_used -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void OpenALAudioManager:: -most_recently_used(const string& path) { - audio_debug("OpenALAudioManager::most_recently_used(path=\"" - < count) { - uncache_a_sound(); - } _cache_limit=count; - assert(is_valid()); + discard_excess_cache(count); } //////////////////////////////////////////////////////////////////// @@ -481,8 +447,6 @@ set_cache_limit(unsigned int count) { //////////////////////////////////////////////////////////////////// unsigned int OpenALAudioManager:: get_cache_limit() const { - audio_debug("OpenALAudioManager::get_cache_limit() returning " - <<_cache_limit); return _cache_limit; } @@ -493,13 +457,10 @@ get_cache_limit() const { //////////////////////////////////////////////////////////////////// void OpenALAudioManager:: release_sound(OpenALAudioSound* audioSound) { - audio_debug("OpenALAudioManager::release_sound(audioSound=\"" - <get_name()<<"\"), this = " << (void *)this); - AudioSet::iterator ai = _sounds_on_loan.find(audioSound); - nassertv(ai != _sounds_on_loan.end()); - _sounds_on_loan.erase(ai); - - audio_debug("OpenALAudioManager::release_sound() finished"); + AudioSoundSet::iterator ai = _all_audio_sounds.find(audioSound); + if (ai != _all_audio_sounds.end()) { + _all_audio_sounds.erase(ai); + } } //////////////////////////////////////////////////////////////////// @@ -514,8 +475,8 @@ void OpenALAudioManager::set_volume(float volume) { _volume = volume; // Tell our AudioSounds to adjust: - AudioSet::iterator i=_sounds_on_loan.begin(); - for (; i!=_sounds_on_loan.end(); ++i) { + AudioSoundSet::iterator i=_all_audio_sounds.begin(); + for (; i!=_all_audio_sounds.end(); ++i) { (**i).set_volume((**i).get_volume()); } @@ -553,8 +514,8 @@ set_play_rate(float play_rate) { if (_play_rate!=play_rate) { _play_rate = play_rate; // Tell our AudioSounds to adjust: - AudioSet::iterator i=_sounds_on_loan.begin(); - for (; i!=_sounds_on_loan.end(); ++i) { + AudioSoundSet::iterator i=_all_audio_sounds.begin(); + for (; i!=_all_audio_sounds.end(); ++i) { (**i).set_play_rate((**i).get_play_rate()); } } @@ -583,8 +544,8 @@ set_active(bool active) { if (_active!=active) { _active=active; // Tell our AudioSounds to adjust: - AudioSet::iterator i=_sounds_on_loan.begin(); - for (; i!=_sounds_on_loan.end(); ++i) { + AudioSoundSet::iterator i=_all_audio_sounds.begin(); + for (; i!=_all_audio_sounds.end(); ++i) { (**i).set_active(_active); } } @@ -700,8 +661,8 @@ audio_3d_set_distance_factor(float factor) { al_audio_errcheck("alDopplerFactor()"); } - AudioSet::iterator i=_sounds_on_loan.begin(); - for (; i!=_sounds_on_loan.end(); ++i) { + AudioSoundSet::iterator i=_all_audio_sounds.begin(); + for (; i!=_all_audio_sounds.end(); ++i) { (**i).set_3d_min_distance((**i).get_3d_min_distance()); (**i).set_3d_max_distance((**i).get_3d_max_distance()); } @@ -754,8 +715,8 @@ void OpenALAudioManager:: audio_3d_set_drop_off_factor(float factor) { _drop_off_factor = factor; - AudioSet::iterator i=_sounds_on_loan.begin(); - for (; i!=_sounds_on_loan.end(); ++i) { + AudioSoundSet::iterator i=_all_audio_sounds.begin(); + for (; i!=_all_audio_sounds.end(); ++i) { (**i).set_3d_drop_off_factor((**i).get_3d_drop_off_factor()); } } @@ -774,10 +735,18 @@ audio_3d_get_drop_off_factor() const { // Function: OpenALAudioManager::starting_sound // Access: // Description: Inform the manager that a sound is about to play. +// The manager will add this sound to the table of +// sounds that are playing, and will allocate a source +// to this sound. //////////////////////////////////////////////////////////////////// void OpenALAudioManager:: starting_sound(OpenALAudioSound* audio) { ALuint source=0; + + // If the sound already has a source, we don't need to do anything. + if (audio->_source) { + return; + } // first give all sounds that have finished a chance to stop, so that these get stopped first update(); @@ -805,9 +774,8 @@ starting_sound(OpenALAudioSound* audio) { _al_sources->erase(source); } - assert(!audio->_source); audio->_source = source; - + if (source) _sounds_playing.insert(audio); } @@ -923,17 +891,17 @@ cleanup() { return; } - // Be sure to cleanup associated sounds before cleaning up the manager: - AudioSet::iterator ai; - for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) { + AudioSoundSet sounds(_all_audio_sounds); + AudioSoundSet::iterator ai; + for (ai = sounds.begin(); ai != sounds.end(); ++ai) { (*ai)->cleanup(); } - + + assert(_all_sound_data.size() == _expiration_queue.size()); clear_cache(); - + nassertv(_active_managers > 0); --_active_managers; - audio_debug(" _active_managers="<<_active_managers); if (_active_managers == 0) { if (_openal_active) { @@ -968,12 +936,6 @@ cleanup() { _openal_active = false; } - /*if (_managers) { - delete _managers; - _managers = NULL; - delete _al_sources; - _al_sources = NULL; - }*/ } _cleanup_required = false; audio_debug("OpenALAudioManager::cleanup() finished"); @@ -985,10 +947,12 @@ cleanup() { // Description: //////////////////////////////////////////////////////////////////// OpenALAudioManager::SoundData:: -SoundData(OpenALAudioManager* manager) : +SoundData(OpenALAudioManager* manager, const Filename &path) : _manager(manager), + _path(path), _buffer(0), - _has_length(false) + _client_count(1), + _length(0.0) { } @@ -1009,41 +973,60 @@ OpenALAudioManager::SoundData:: } //////////////////////////////////////////////////////////////////// -// Function: OpenALAudioManager::SoundData::get_length +// Function: OpenALAudioManager::increment_client_count // Access: Public -// Description: +// Description: Increments the SoundData's client count. Any +// SoundData that is actively in use (ie, has a client) +// is removed entirely from the expiration queue. //////////////////////////////////////////////////////////////////// -float OpenALAudioManager::SoundData:: -get_length() { - int freq,bits,channels,size; - - if (!_has_length) { - // Time to determine the length of the file. - - audio_debug("Computing length of " << _basename); - - _manager->make_current(); - - alGetError(); // clear errors - alGetBufferi(_buffer,AL_FREQUENCY,&freq); - audio_debug("Frequency = "<_path); + sd->_client_count += 1; + if (sd->_client_count == 1) { + audio_debug("Removing from expiration queue: " << sd->_path); + ExpirationQueue::iterator p=find(_expiration_queue.begin(), _expiration_queue.end(), sd); + assert(p != _expiration_queue.end()); + _expiration_queue.erase(p); } +} - return _length; +//////////////////////////////////////////////////////////////////// +// Function: OpenALAudioManager::decrement_client_count +// Access: Public +// Description: Decrements the SoundData's client count. Sounds +// that are no longer in use (ie, have no clients) +// go into the expiration queue. When the expiration +// queue reaches the cache limit, the first item on +// the queue is freed. +//////////////////////////////////////////////////////////////////// +void OpenALAudioManager:: +decrement_client_count(SoundData *sd) { + audio_debug("Decrementing client count: " << sd->_path); + sd->_client_count -= 1; + if (sd->_client_count == 0) { + audio_debug("Adding to expiration queue: " << sd->_path); + _expiration_queue.push_back(sd); + discard_excess_cache(_cache_limit); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: OpenALAudioManager::discard_excess_cache +// Access: Public +// Description: Discards sounds from the sound cache until the +// number of sounds remaining is under the limit. +//////////////////////////////////////////////////////////////////// +void OpenALAudioManager:: +discard_excess_cache(int limit) { + while (((int)_expiration_queue.size()) > limit) { + SoundData *sd = _expiration_queue.front(); + audio_debug("Deleting head of sound cache: " << sd->_path); + assert(sd->_client_count == 0); + _expiration_queue.pop_front(); + _all_sound_data.erase(sd->_path); + delete sd; + } } #endif //] diff --git a/panda/src/audiotraits/openalAudioManager.h b/panda/src/audiotraits/openalAudioManager.h index 349b0ee53a..01ff13e6d2 100644 --- a/panda/src/audiotraits/openalAudioManager.h +++ b/panda/src/audiotraits/openalAudioManager.h @@ -28,17 +28,16 @@ #include "pset.h" #include "pmap.h" #include "pdeque.h" +#include "movieAudioCursor.h" //The Includes needed for OpenAL #include #include -#include class OpenALAudioSound; extern void al_audio_errcheck(const char *context); extern void alc_audio_errcheck(const char *context,ALCdevice* device); -extern void alut_audio_errcheck(const char *context); class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager { class SoundData; @@ -116,51 +115,63 @@ class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager { private: void make_current() const; - - PT(SoundData) load(Filename file_name); + + bool can_use_audio(MovieAudioCursor *source); + bool can_load_audio(MovieAudioCursor *source); + + SoundData *cached_sound_data(const Filename &file_name); + SoundData *load_sound_data(MovieAudioCursor *source); // Tell the manager that the sound dtor was called. void release_sound(OpenALAudioSound* audioSound); + void increment_client_count(SoundData *sd); + void decrement_client_count(SoundData *sd); + void discard_excess_cache(int limit); - void most_recently_used(const string& path); - void uncache_a_sound(); - void starting_sound(OpenALAudioSound* audio); void stopping_sound(OpenALAudioSound* audio); void cleanup(); + private: - // The sound cache: - class SoundData : public ReferenceCount { + // An AudioSound that uses a SoundData is called a "client" + // of the SoundData. The SoundData keeps track of how + // many clients are using it. When the number of clients + // drops to zero, the SoundData is no longer in use. The + // expiration queue is a list of all SoundData that aren't + // in use, in least-recently-used order. If a SoundData + // in the expiration queue gains a new client, it is removed + // from the expiration queue. When the number of sounds + // in the expiration queue exceeds the cache limit, the + // first sound in the expiration queue is purged. + + class SoundData { public: - SoundData(OpenALAudioManager* manager); + SoundData(OpenALAudioManager* manager, const Filename &path); ~SoundData(); - float get_length(); - OpenALAudioManager* _manager; - string _basename; + Filename _path; ALuint _buffer; - bool _has_length; - float _length; // in seconds. + double _length; + int _rate; + int _channels; + int _client_count; }; - typedef pmap SoundMap; - SoundMap _sounds; - int _cache_limit; - - typedef pset AudioSet; - // The offspring of this manager: - AudioSet _sounds_on_loan; - - typedef pset SoundsPlaying; - // The sounds from this manager that are currently playing + typedef pmap SoundDataSet; + SoundDataSet _all_sound_data; + + typedef pset AudioSoundSet; + AudioSoundSet _all_audio_sounds; + + typedef pdeque ExpirationQueue; + ExpirationQueue _expiration_queue; + + typedef pset SoundsPlaying; SoundsPlaying _sounds_playing; - - // The Least Recently Used mechanism: - typedef pdeque LRU; - LRU _lru; - + // State: + int _cache_limit; float _volume; float _play_rate; bool _active; diff --git a/panda/src/audiotraits/openalAudioSound.cxx b/panda/src/audiotraits/openalAudioSound.cxx index ed459f25c6..54ba5a9c95 100644 --- a/panda/src/audiotraits/openalAudioSound.cxx +++ b/panda/src/audiotraits/openalAudioSound.cxx @@ -38,26 +38,31 @@ TypeHandle OpenALAudioSound::_type_handle; #endif //] //////////////////////////////////////////////////////////////////// -// Function: OpenALAudioSound::OpenALAudioSound -// Access: public -// Description: Constructor -// All sound will DEFAULT load as a 2D sound unless -// otherwise specified. +// Function: OpenALAudioSound::Constructor +// Access: Private +// Description: //////////////////////////////////////////////////////////////////// OpenALAudioSound:: OpenALAudioSound(OpenALAudioManager* manager, - OpenALAudioManager::SoundData *sd, string file_name, bool positional) - : _sd(sd), _source(0), _manager(manager), _file_name(file_name), - _volume(1.0f), _balance(0), _play_rate(1.0), - _loop_count(1), _pause_time(0.0), - _active(true), _paused(false) { - nassertv(sd != NULL); - nassertv(!file_name.empty()); - audio_debug("OpenALAudioSound(manager=0x"<<(void*)&manager - <<", sd=0x"<<(void*)sd<<", file_name="<_buffer; - // don't assign source until we play since sources are limited - /* - // Create a source to play the buffer - alGetError(); // clear errors - alGenSources(1,&_source); - al_audio_errcheck("alGenSources()"); - - // Assign the buffer to the source - alSourcei(_source,AL_BUFFER,_buffer); - al_audio_errcheck("alSourcei(_source,AL_BUFFER,_buffer)"); - */ - - // nonpositional sources are made relative to the listener so they don't move _positional = positional; if (_positional) { - int nChannels=1; - alGetBufferi(_buffer,AL_CHANNELS,&nChannels); - al_audio_errcheck("alGetBufferi(_buffer,AL_CHANNELS)"); - if (nChannels>1) - audio_warning("OpenALAudioSound: Stereo sounds won't be spacialized: "<_channels != 1)) || + (_stream && (_stream->audio_channels() != 1))) { + audio_warning("Stereo sounds won't be spacialized: "<release_sound(this); - openal_audio_debug("~OpenALAudioSound() done"); } +//////////////////////////////////////////////////////////////////// +// Function: OpenALAudioSound::cleanup +// Access: Private +// Description: Disables the sound forever. Releases resources and +// detaches the sound from its audio manager. +//////////////////////////////////////////////////////////////////// +void OpenALAudioSound:: +cleanup() { + if (_manager == 0) { + return; + } + if (_source) { + stop(); + } + if (_sample) { + _manager->decrement_client_count(_sample); + _sample = 0; + } + _manager->release_sound(this); + _manager = 0; + _active = false; +} //////////////////////////////////////////////////////////////////// -// Function: OpenALAudioSound:: play +// Function: OpenALAudioSound::play // Access: public // Description: Plays a sound. //////////////////////////////////////////////////////////////////// void OpenALAudioSound:: play() { - float px,py,pz,vx,vy,vz; - - openal_audio_debug("play()"); - if (_active) { - if (status() == AudioSound::PLAYING) { - stop(); - } - //nassertv(_source); - _manager->starting_sound(this); - - if (_source) { - // Setup source - _manager->make_current(); - - alGetError(); // clear errors - - // Assign the buffer to the source - alSourcei(_source,AL_BUFFER,_buffer); - ALenum result = alGetError(); - if (result!=AL_NO_ERROR) { - audio_error("alSourcei(_source,AL_BUFFER,_buffer): " << alGetString(result) ); - stop(); - return; - } - - // nonpositional sources are made relative to the listener so they don't move - alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE); - al_audio_errcheck("alSourcei(_source,AL_SOURCE_RELATIVE)"); - - // set source properties that we have stored - set_volume(_volume); - //set_balance(_balance); - set_play_rate(_play_rate); - set_3d_min_distance(_min_dist); - set_3d_max_distance(_max_dist); - set_3d_drop_off_factor(_drop_off_factor); - - get_3d_attributes(&px,&py,&pz,&vx,&vy,&vz); - set_3d_attributes(px, py, pz, vx, vy, vz); - - set_loop_count(_loop_count); - - if (_pause_time) { - set_time(_pause_time); - _pause_time = 0.0; - } - - // Start playing: - alSourcePlay(_source); - al_audio_errcheck("alSourcePlay(_source)"); - - audio_debug(" started sound " << _file_name ); - } - } else { - // In case _loop_count gets set to forever (zero): - audio_debug(" paused "<<_file_name ); - _paused=true; - } + set_time(0.0); } + //////////////////////////////////////////////////////////////////// // Function: OpenALAudioSound::stop // Access: public @@ -207,8 +146,6 @@ stop() { al_audio_errcheck("alSourceStop(_source)"); } - _pause_time = 0.0; - _manager->stopping_sound(this); // The _paused flag should not be cleared here. _paused is not like // the Pause button on a cd/dvd player. It is used as a flag to say @@ -239,8 +176,6 @@ finished() { //////////////////////////////////////////////////////////////////// void OpenALAudioSound:: set_loop(bool loop) { - openal_audio_debug("set_loop(loop="<make_current(); - + alGetError(); // clear errors alSourcei(_source,AL_LOOPING,_loop_count==0?AL_TRUE:AL_FALSE); al_audio_errcheck("alSourcei(_source,AL_LOOPING)"); @@ -289,7 +226,6 @@ set_loop_count(unsigned long loop_count) { //////////////////////////////////////////////////////////////////// unsigned long OpenALAudioSound:: get_loop_count() const { - openal_audio_debug("get_loop_count() returning "<<_loop_count); return _loop_count; } @@ -300,32 +236,63 @@ get_loop_count() const { //////////////////////////////////////////////////////////////////// void OpenALAudioSound:: set_time(float time) { + float px,py,pz,vx,vy,vz; + + openal_audio_debug("play()"); + if (!_active) { + _paused=true; + return; + } + + if (status() == AudioSound::PLAYING) { + stop(); + } + + _manager->starting_sound(this); + + if (!_source) { + return; + } + + // Setup source + _manager->make_current(); + + alGetError(); // clear errors + + // Assign the buffer to the source + alSourcei(_source,AL_BUFFER,_sample->_buffer); + ALenum result = alGetError(); + if (result!=AL_NO_ERROR) { + audio_error("alSourcei(_source,AL_BUFFER,_sample->_buffer): " << alGetString(result) ); + stop(); + return; + } + + // nonpositional sources are made relative to the listener so they don't move + alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE); + al_audio_errcheck("alSourcei(_source,AL_SOURCE_RELATIVE)"); + + // set source properties that we have stored + set_volume(_volume); + //set_balance(_balance); + set_play_rate(_play_rate); + set_3d_min_distance(_min_dist); + set_3d_max_distance(_max_dist); + set_3d_drop_off_factor(_drop_off_factor); + get_3d_attributes(&px,&py,&pz,&vx,&vy,&vz); + set_3d_attributes(px, py, pz, vx, vy, vz); + + set_loop_count(_loop_count); + openal_audio_debug("set_time(time="< max_time) { - openalAudio_cat.warning() - << "set_time(" << time << ") requested for sound of length " - << max_time << "\n"; - time = max_time; - } - - if (_source) { - _manager->make_current(); - - alGetError(); // clear errors - alSourcef(_source,AL_SEC_OFFSET,time); - al_audio_errcheck("alSourcef(_source,AL_SEC_OFFSET)"); - } - - if (status()==PLAYING) { - _pause_time = 0.0; - } else { - _pause_time = time; - } + audio_debug(" started sound " << _path ); } //////////////////////////////////////////////////////////////////// @@ -336,19 +303,16 @@ set_time(float time) { float OpenALAudioSound:: get_time() const { float time; - - //nassertv(_source); - + if (_source) { _manager->make_current(); - alGetError(); // clear errors alGetSourcef(_source,AL_SEC_OFFSET,&time); al_audio_errcheck("alGetSourcef(_source,AL_SEC_OFFSET)"); } else { - time = _pause_time; + return 0.0; } - openal_audio_debug("get_time() returning "<get_length(); + return _sample->_length; } //////////////////////////////////////////////////////////////////// @@ -674,7 +638,7 @@ get_finished_event() const { //////////////////////////////////////////////////////////////////// const string& OpenALAudioSound:: get_name() const { - return _file_name; + return _path; } //////////////////////////////////////////////////////////////////// @@ -685,18 +649,18 @@ get_name() const { AudioSound::SoundStatus OpenALAudioSound:: status() const { ALenum status; - + if (_source==0) { //return AudioSound::BAD; return AudioSound::READY; } - + _manager->make_current(); - + alGetError(); // clear errors alGetSourcei(_source,AL_SOURCE_STATE,&status); al_audio_errcheck("alGetSourcei(_source,AL_SOURCE_STATE)"); - + if (status == AL_PLAYING/* || status == AL_PAUSED*/) { return AudioSound::PLAYING; } else { @@ -704,27 +668,4 @@ status() const { } } -//////////////////////////////////////////////////////////////////// -// Function: OpenALAudioSound::cleanup -// Access: Private -// Description: Called to release any resources associated with the -// sound. -//////////////////////////////////////////////////////////////////// -void OpenALAudioSound:: -cleanup() { - if (_source) { - stop(); - /* - if (OpenALAudioManager::_openal_active) { - // delete the source - _manager->make_current(); - alGetError(); // clear errors - alDeleteSources(1,&_source); - al_audio_errcheck("alDeleteSources()"); - } - _source = 0; - */ - } -} - #endif //] diff --git a/panda/src/audiotraits/openalAudioSound.h b/panda/src/audiotraits/openalAudioSound.h index 664c900965..2aa42d1256 100644 --- a/panda/src/audiotraits/openalAudioSound.h +++ b/panda/src/audiotraits/openalAudioSound.h @@ -27,10 +27,10 @@ #ifdef HAVE_OPENAL //[ #include "audioSound.h" +#include "movieAudioCursor.h" #include #include -#include class EXPCL_OPENAL_AUDIO OpenALAudioSound : public AudioSound { friend class OpenALAudioManager; @@ -113,22 +113,27 @@ public: void finished(); private: - OpenALAudioSound(OpenALAudioManager* manager, OpenALAudioManager::SoundData *sd, - string file_name, bool positional); + OpenALAudioSound(OpenALAudioManager* manager, + const Filename &path, + PT(MovieAudioCursor) cursor, + OpenALAudioManager::SoundData *sd, + bool positional); void cleanup(); private: - PT(OpenALAudioManager::SoundData) _sd; - ALuint _buffer; + + // A Sound can have a sample or a stream, but not both. + OpenALAudioManager::SoundData *_sample; + PT(MovieAudioCursor) _stream; + ALuint _stream_buffers[3]; + ALuint _source; PT(OpenALAudioManager) _manager; - + float _volume; // 0..1.0 float _balance; // -1..1 float _play_rate; // 0..1.0 - float _pause_time; - bool _positional; ALfloat _location[3]; ALfloat _velocity[3]; @@ -144,8 +149,8 @@ private: // when the sound finishes playing. It is not triggered // when the sound is stopped with stop(). string _finished_event; - - string _file_name; + + Filename _path; // _active is for things like a 'turn off sound effects' in // a preferences pannel.