Browse Source

More work on OpenAL

Josh Yelon 18 years ago
parent
commit
40879d8def

+ 0 - 2
panda/src/audiotraits/config_fmodAudio.cxx

@@ -23,7 +23,6 @@
 #include "config_fmodAudio.h"
 #include "config_fmodAudio.h"
 #include "fmodAudioManager.h"
 #include "fmodAudioManager.h"
 #include "fmodAudioSound.h"
 #include "fmodAudioSound.h"
-#include "fmodAudioDSP.h"
 #include "pandaSystem.h"
 #include "pandaSystem.h"
 #include "dconfig.h"
 #include "dconfig.h"
 
 
@@ -55,7 +54,6 @@ init_libFmodAudio() {
 
 
   FmodAudioManager::init_type();
   FmodAudioManager::init_type();
   FmodAudioSound::init_type();
   FmodAudioSound::init_type();
-  FmodAudioDSP::init_type();
 
 
   PandaSystem *ps = PandaSystem::get_global_ptr();
   PandaSystem *ps = PandaSystem::get_global_ptr();
   ps->add_system("FMOD");
   ps->add_system("FMOD");

+ 0 - 25
panda/src/audiotraits/fmodAudioDSP.I

@@ -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
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-
-
-
-
-

+ 0 - 448
panda/src/audiotraits/fmodAudioDSP.cxx

@@ -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
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-
-#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, &parameterMin, &parameterMax);
-  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, &parameterMin, &parameterMax);
-  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, &parameterMin, &parameterMax);
-  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, &parameterMin, &parameterMax);
-  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, &parameterValue, 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; i<np; i++) {
-    if ( name == get_parameter_name(i) ) {
-
-      audio_debug("FmodAudioSound::find_parameter() returning: " << get_parameter_name(i) << " " << i );
-
-      return i;
-    }
-  }
-  return -1;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: FmodAudioDSP::get_dsp_name()
-//       Access: Protected
-//  Description: This is a thin wrapper around FMOD-EX.
-//               See the FMOD-EX documentation.
-////////////////////////////////////////////////////////////////////
-string FmodAudioDSP::
-get_dsp_name() {
-  audio_debug("FmodAudioSound::get_dsp_name()." );
-
-  //Local Variables that are needed.
-  FMOD_RESULT result;
-  char  name[32];
-  unsigned int  version;
-  int   channels;
-  int   configwidth;
-  int   configheight;
-
-  result = _dsp->getInfo(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 //]

+ 0 - 164
panda/src/audiotraits/fmodAudioDSP.h

@@ -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
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
-//[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 <pandabase.h>
-
-#ifdef HAVE_FMODEX //[
-
-#include "audioManager.h"
-#include "audioDSP.h"
-
-#include <fmod.hpp>
-#include <fmod_errors.h>
-
-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__ */
-
-
-
-
-
-
-
-

+ 214 - 231
panda/src/audiotraits/openalAudioManager.cxx

@@ -80,9 +80,9 @@ PT(AudioManager) Create_AudioManager() {
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: OpenALAudioManager::OpenALAudioManager()
+//     Function: OpenALAudioManager::Constructor
 //       Access: Public
 //       Access: Public
-//  Description: Constructor
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 OpenALAudioManager::
 OpenALAudioManager::
 OpenALAudioManager() {
 OpenALAudioManager() {
@@ -164,9 +164,9 @@ OpenALAudioManager() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: OpenALAudioManager::~OpenALAudioManager
+//     Function: OpenALAudioManager::Destructor
 //       Access: Public
 //       Access: Public
-//  Description: DESTRCUTOR !!!
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 OpenALAudioManager::
 OpenALAudioManager::
 ~OpenALAudioManager() {
 ~OpenALAudioManager() {
@@ -214,22 +214,7 @@ shutdown() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool OpenALAudioManager::
 bool OpenALAudioManager::
 is_valid() {
 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);
   alc_audio_errcheck("alcMakeContextCurrent(_context)",_device);
 }
 }
 
 
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: OpenALAudioManager::load
+//     Function: OpenALAudioManager::can_use_audio
 //       Access: Private
 //       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 "<<file_name);
-    return NULL;
-  }
-
+bool OpenALAudioManager::
+can_use_audio(MovieAudioCursor *source) {
   int channels = source->audio_channels();
   int channels = source->audio_channels();
   if ((channels != 1)&&(channels != 2)) {
   if ((channels != 1)&&(channels != 2)) {
     audio_error("Currently, only mono and stereo are supported.");
     audio_error("Currently, only mono and stereo are supported.");
-    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 samples = (int)(source->length() * source->audio_rate());
-  if (samples > 10000000) {
-    audio_error("Sound is too long for loading into RAM.");
-    return NULL;
+  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
   alGetError(); // clear errors
   sd->_buffer = 0;
   sd->_buffer = 0;
   alGenBuffers(1, &sd->_buffer);
   alGenBuffers(1, &sd->_buffer);
@@ -287,6 +298,9 @@ load(Filename file_name) {
     audio_error("Could not create an OpenAL buffer object");
     audio_error("Could not create an OpenAL buffer object");
     return NULL;
     return NULL;
   }
   }
+
+  int channels = source->audio_channels();
+  int samples = (int)(source->length() * source->audio_rate());
   
   
   PN_int16 *data = new PN_int16[samples * channels];
   PN_int16 *data = new PN_int16[samples * channels];
   source->read_samples(samples, data);
   source->read_samples(samples, data);
@@ -299,11 +313,33 @@ load(Filename file_name) {
     alDeleteBuffers(1, &sd->_buffer);
     alDeleteBuffers(1, &sd->_buffer);
     return NULL;
     return NULL;
   }
   }
-  audio_debug("Loaded "<<file_name<<" Src Len "<<source->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;
   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()
 //     Function: OpenALAudioManager::get_sound()
 //       Access: Public
 //       Access: Public
@@ -311,137 +347,76 @@ load(Filename file_name) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PT(AudioSound) OpenALAudioManager::
 PT(AudioSound) OpenALAudioManager::
 get_sound(const string &file_name, bool positional) {
 get_sound(const string &file_name, bool positional) {
-  audio_debug("OpenALAudioManager::get_sound(file_name=\""<<file_name<<"\")");
-
   if(!is_valid()) {
   if(!is_valid()) {
-     audio_debug("invalid OpenALAudioManager returning NullSound");
-     return get_null_sound();
+    return get_null_sound();
   }
   }
-
-  assert(is_valid());
+  
   Filename path = file_name;
   Filename path = file_name;
-
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   vfs->resolve_filename(path, get_sound_path()) ||
   vfs->resolve_filename(path, get_sound_path()) ||
     vfs->resolve_filename(path, get_model_path());
     vfs->resolve_filename(path, get_model_path());
-  audio_debug("  resolved file_name is '"<<path<<"'");
-
-  PT(SoundData) sd;
-  // Get the sound, either from the cache or from a loader:
-  SoundMap::const_iterator si=_sounds.find(path);
-  if (si != _sounds.end()) {
-    // ...found the sound in the cache.
-    sd = (*si).second;
-    audio_debug("  sound found in pool 0x" << (void*)sd);
-  } else {
-    // ...the sound was not found in the cache/pool.
-    sd = load(path);
-    if (sd != (SoundData *)NULL) {
-      while (_sounds.size() >= (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<SoundMap::const_iterator, bool> ib
-          =_sounds.insert(SoundMap::value_type(path, sd));
-      if (!ib.second) {
-        // The insert failed.
-        audio_debug("  failed map insert of "<<path);
-        assert(is_valid());
-        return get_null_sound();
-      }
-      // Set si, so that we can get a reference to the path
-      // for the OpenALAudioSound.
-      si=ib.first;
+  
+  if (path.empty()) {
+    audio_error("get_sound - invalid filename");
+    return NULL;
+  }
+  
+  PT(MovieAudioCursor) cursor;
+  SoundData *sd = cached_sound_data(path);
+  if (sd == 0) {
+    cursor = MovieAudio::get(path)->open();
+    if (cursor == 0) {
+      audio_error("Cannot open file: "<<path);
+      return NULL;
+    }
+    if (!can_use_audio(cursor)) {
+      audio_error("Audio data not supported format: "<<path);
+      return NULL;
+    }
+    if (can_load_audio(cursor)) {
+      sd = load_sound_data(cursor);
+      cursor = 0;
     }
     }
   }
   }
-  // Create an AudioSound from the sound:
-  PT(AudioSound) audioSound = 0;
-  if (sd != (SoundData *)NULL) {
-    most_recently_used((*si).first);
-    PT(OpenALAudioSound) openalAudioSound
-        =new OpenALAudioSound(this, sd, (*si).first, positional);
-    nassertr(openalAudioSound, 0);
-    openalAudioSound->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
 //     Function: OpenALAudioManager::uncache_sound
 //       Access: Public
 //       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::
 void OpenALAudioManager::
 uncache_sound(const string& file_name) {
 uncache_sound(const string& file_name) {
-  audio_debug("OpenALAudioManager::uncache_sound(file_name=\""
-      <<file_name<<"\")");
   assert(is_valid());
   assert(is_valid());
   Filename path = file_name;
   Filename path = file_name;
-
+  
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   vfs->resolve_filename(path, get_sound_path()) ||
   vfs->resolve_filename(path, get_sound_path()) ||
     vfs->resolve_filename(path, get_model_path());
     vfs->resolve_filename(path, get_model_path());
-
-  audio_debug("  path=\""<<path<<"\"");
-  SoundMap::iterator i=_sounds.find(path);
-  if (i != _sounds.end()) {
-    assert(_lru.size()>0);
-    LRU::iterator lru_i=find(_lru.begin(), _lru.end(), &(i->first));
-    assert(lru_i != _lru.end());
-    _lru.erase(lru_i);
-    _sounds.erase(i);
-  }
-  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 \""<<i->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=\""
-      <<path<<"\")");
-  LRU::iterator i=find(_lru.begin(), _lru.end(), &path);
-  if (i != _lru.end()) {
-    _lru.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;
+    }
   }
   }
-  // At this point, path should not exist in the _lru:
-  assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
-  _lru.push_back(&path);
-  assert(is_valid());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -451,11 +426,7 @@ most_recently_used(const string& path) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void OpenALAudioManager::
 void OpenALAudioManager::
 clear_cache() {
 clear_cache() {
-  audio_debug("OpenALAudioManager::clear_cache()");
-  if (_is_valid) { assert(is_valid()); }
-  _sounds.clear();
-  _lru.clear();
-  if (_is_valid) { assert(is_valid()); }
+  discard_excess_cache(0);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -465,13 +436,8 @@ clear_cache() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void OpenALAudioManager::
 void OpenALAudioManager::
 set_cache_limit(unsigned int count) {
 set_cache_limit(unsigned int count) {
-  audio_debug("OpenALAudioManager::set_cache_limit(count="<<count<<")");
-  assert(is_valid());
-  while (_lru.size() > count) {
-    uncache_a_sound();
-  }
   _cache_limit=count;
   _cache_limit=count;
-  assert(is_valid());
+  discard_excess_cache(count);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -481,8 +447,6 @@ set_cache_limit(unsigned int count) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 unsigned int OpenALAudioManager::
 unsigned int OpenALAudioManager::
 get_cache_limit() const {
 get_cache_limit() const {
-  audio_debug("OpenALAudioManager::get_cache_limit() returning "
-      <<_cache_limit);
   return _cache_limit;
   return _cache_limit;
 }
 }
 
 
@@ -493,13 +457,10 @@ get_cache_limit() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void OpenALAudioManager::
 void OpenALAudioManager::
 release_sound(OpenALAudioSound* audioSound) {
 release_sound(OpenALAudioSound* audioSound) {
-  audio_debug("OpenALAudioManager::release_sound(audioSound=\""
-              <<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;
     _volume = volume;
 
 
     // Tell our AudioSounds to adjust:
     // 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());
       (**i).set_volume((**i).get_volume());
     }
     }
 
 
@@ -553,8 +514,8 @@ set_play_rate(float play_rate) {
   if (_play_rate!=play_rate) {
   if (_play_rate!=play_rate) {
     _play_rate = play_rate;
     _play_rate = play_rate;
     // Tell our AudioSounds to adjust:
     // 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());
       (**i).set_play_rate((**i).get_play_rate());
     }
     }
   }
   }
@@ -583,8 +544,8 @@ set_active(bool active) {
   if (_active!=active) {
   if (_active!=active) {
     _active=active;
     _active=active;
     // Tell our AudioSounds to adjust:
     // 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);
       (**i).set_active(_active);
     }
     }
   }
   }
@@ -700,8 +661,8 @@ audio_3d_set_distance_factor(float factor) {
     al_audio_errcheck("alDopplerFactor()");
     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_min_distance((**i).get_3d_min_distance());
     (**i).set_3d_max_distance((**i).get_3d_max_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) {
 audio_3d_set_drop_off_factor(float factor) {
   _drop_off_factor = 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());
     (**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
 //     Function: OpenALAudioManager::starting_sound
 //       Access: 
 //       Access: 
 //  Description: Inform the manager that a sound is about to play.
 //  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::
 void OpenALAudioManager::
 starting_sound(OpenALAudioSound* audio) {
 starting_sound(OpenALAudioSound* audio) {
   ALuint source=0;
   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
   // first give all sounds that have finished a chance to stop, so that these get stopped first
   update();
   update();
@@ -805,9 +774,8 @@ starting_sound(OpenALAudioSound* audio) {
     _al_sources->erase(source);
     _al_sources->erase(source);
   }
   }
 
 
-  assert(!audio->_source);
   audio->_source = source;
   audio->_source = source;
-
+  
   if (source)
   if (source)
     _sounds_playing.insert(audio);
     _sounds_playing.insert(audio);
 }
 }
@@ -923,17 +891,17 @@ cleanup() {
     return;
     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();
     (*ai)->cleanup();
   }
   }
-
+  
+  assert(_all_sound_data.size() == _expiration_queue.size());
   clear_cache();
   clear_cache();
-
+  
   nassertv(_active_managers > 0);
   nassertv(_active_managers > 0);
   --_active_managers;
   --_active_managers;
-  audio_debug("  _active_managers="<<_active_managers);
 
 
   if (_active_managers == 0) {
   if (_active_managers == 0) {
     if (_openal_active) {
     if (_openal_active) {
@@ -968,12 +936,6 @@ cleanup() {
 
 
       _openal_active = false;
       _openal_active = false;
     }
     }
-    /*if (_managers) {
-      delete _managers;
-      _managers = NULL;
-      delete _al_sources;
-      _al_sources = NULL;
-    }*/
   }
   }
   _cleanup_required = false;
   _cleanup_required = false;
   audio_debug("OpenALAudioManager::cleanup() finished");
   audio_debug("OpenALAudioManager::cleanup() finished");
@@ -985,10 +947,12 @@ cleanup() {
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 OpenALAudioManager::SoundData::
 OpenALAudioManager::SoundData::
-SoundData(OpenALAudioManager* manager) :
+SoundData(OpenALAudioManager* manager, const Filename &path) :
   _manager(manager),
   _manager(manager),
+  _path(path),
   _buffer(0),
   _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
 //       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();
+void OpenALAudioManager::
+increment_client_count(SoundData *sd) {
+  audio_debug("Incrementing client count: " << sd->_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);
+  }
+}
 
 
-    alGetError(); // clear errors
-    alGetBufferi(_buffer,AL_FREQUENCY,&freq);
-    audio_debug("Frequency = "<<freq);
-    al_audio_errcheck("alGetBufferi(_buffer,AL_FREQUENCY)");
-    alGetBufferi(_buffer,AL_BITS,&bits);
-    audio_debug("Bits = "<<bits);
-    al_audio_errcheck("alGetBufferi(_buffer,AL_BITS)");
-    alGetBufferi(_buffer,AL_CHANNELS,&channels);
-    audio_debug("Channels = "<<channels);
-    al_audio_errcheck("alGetBufferi(_buffer,AL_CHANNELS)");
-    alGetBufferi(_buffer,AL_SIZE,&size);
-    audio_debug("Size = "<<size);
-    al_audio_errcheck("alGetBufferi(_buffer,AL_SIZE)");
-  
-    _length = ((float)size)/channels/((float)bits/8)/freq;
-    audio_debug("Length = "<<_length);
-    _has_length = true;
+////////////////////////////////////////////////////////////////////
+//     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);
   }
   }
+}
 
 
-  return _length;
+////////////////////////////////////////////////////////////////////
+//     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 //]
 #endif //]

+ 41 - 30
panda/src/audiotraits/openalAudioManager.h

@@ -28,17 +28,16 @@
 #include "pset.h"
 #include "pset.h"
 #include "pmap.h"
 #include "pmap.h"
 #include "pdeque.h"
 #include "pdeque.h"
+#include "movieAudioCursor.h"
 
 
 //The Includes needed for OpenAL
 //The Includes needed for OpenAL
 #include <al.h>
 #include <al.h>
 #include <alc.h>
 #include <alc.h>
-#include <alut.h>
 
 
 class OpenALAudioSound;
 class OpenALAudioSound;
 
 
 extern void al_audio_errcheck(const char *context);
 extern void al_audio_errcheck(const char *context);
 extern void alc_audio_errcheck(const char *context,ALCdevice* device);
 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 EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager {
   class SoundData;
   class SoundData;
@@ -116,51 +115,63 @@ class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager {
 
 
 private:
 private:
   void make_current() const;
   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.
   // Tell the manager that the sound dtor was called.
   void release_sound(OpenALAudioSound* audioSound);
   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 starting_sound(OpenALAudioSound* audio);
   void stopping_sound(OpenALAudioSound* audio);
   void stopping_sound(OpenALAudioSound* audio);
 
 
   void cleanup();
   void cleanup();
+  
 private:
 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:
   public:
-    SoundData(OpenALAudioManager* manager);
+    SoundData(OpenALAudioManager* manager, const Filename &path);
     ~SoundData();
     ~SoundData();
-    float get_length();
-
     OpenALAudioManager* _manager;
     OpenALAudioManager* _manager;
-    string _basename;
+    Filename _path;
     ALuint _buffer;
     ALuint _buffer;
-    bool _has_length;
-    float _length;  // in seconds.
+    double _length;
+    int _rate;
+    int _channels;
+    int _client_count;
   };
   };
-  typedef pmap<string, PT(SoundData) > SoundMap;
-  SoundMap _sounds;
-  int _cache_limit;
-
-  typedef pset<OpenALAudioSound* > AudioSet;
-  // The offspring of this manager:
-  AudioSet _sounds_on_loan;
-
-  typedef pset<OpenALAudioSound* > SoundsPlaying;
-  // The sounds from this manager that are currently playing
+  typedef pmap<string, SoundData *> SoundDataSet;
+  SoundDataSet _all_sound_data;
+  
+  typedef pset<OpenALAudioSound *> AudioSoundSet;
+  AudioSoundSet _all_audio_sounds;
+  
+  typedef pdeque<SoundData *> ExpirationQueue;
+  ExpirationQueue _expiration_queue;
+  
+  typedef pset<OpenALAudioSound *> SoundsPlaying;
   SoundsPlaying _sounds_playing;
   SoundsPlaying _sounds_playing;
-
-  // The Least Recently Used mechanism:
-  typedef pdeque<const string* > LRU;
-  LRU _lru;
-
+  
   // State:
   // State:
+  int _cache_limit;
   float _volume;
   float _volume;
   float _play_rate;
   float _play_rate;
   bool _active;
   bool _active;

+ 121 - 180
panda/src/audiotraits/openalAudioSound.cxx

@@ -38,26 +38,31 @@ TypeHandle OpenALAudioSound::_type_handle;
 #endif //]
 #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::
 OpenALAudioSound(OpenALAudioManager* manager,
 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="<<file_name<<")");
-
+                 const Filename &path,
+                 PT(MovieAudioCursor) stream,
+                 OpenALAudioManager::SoundData *sample,
+                 bool positional) :
+  _sample(sample),
+  _stream(stream),
+  _source(0),
+  _manager(manager),
+  _path(path),
+  _volume(1.0f),
+  _balance(0),
+  _play_rate(1.0),
+  _loop_count(1),
+  _active(true),
+  _paused(false)
+{
   //Inits 3D Attributes
   //Inits 3D Attributes
+  
   _location[0] = 0;
   _location[0] = 0;
   _location[1] = 0;
   _location[1] = 0;
   _location[2] = 0;
   _location[2] = 0;
@@ -68,127 +73,61 @@ OpenALAudioSound(OpenALAudioManager* manager,
 
 
   _min_dist = 3.28f; _max_dist = 1000000000.0f;
   _min_dist = 3.28f; _max_dist = 1000000000.0f;
   _drop_off_factor = 1.0f;
   _drop_off_factor = 1.0f;
-
-  _buffer = _sd->_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;
   _positional = positional;
   if (_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: "<<file_name);
-  } else {
-    /*alSourcei(_source,AL_SOURCE_RELATIVE,AL_TRUE);
-    al_audio_errcheck("alSourcei(_source,AL_SOURCE_RELATIVE,AL_TRUE)");*/
+    if ((_sample && (_sample->_channels != 1)) ||
+        (_stream && (_stream->audio_channels() != 1))) {
+      audio_warning("Stereo sounds won't be spacialized: "<<path);
+    }
   }
   }
-
-  /*
-  // set initial values since they are manager-relative
-  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);
-  */
 }
 }
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: OpenALAudioSound::~OpenALAudioSound
+//     Function: OpenALAudioSound::Destructor
 //       Access: public
 //       Access: public
-//  Description: DESTRUCTOR!!!
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 OpenALAudioSound::
 OpenALAudioSound::
 ~OpenALAudioSound() {
 ~OpenALAudioSound() {
-  openal_audio_debug("~OpenALAudioSound()");
   cleanup();
   cleanup();
-  _manager->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
 //       Access: public
 //  Description: Plays a sound.
 //  Description: Plays a sound.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void OpenALAudioSound::
 void OpenALAudioSound::
 play() {
 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
 //     Function: OpenALAudioSound::stop
 //       Access: public
 //       Access: public
@@ -207,8 +146,6 @@ stop() {
     al_audio_errcheck("alSourceStop(_source)");
     al_audio_errcheck("alSourceStop(_source)");
   }
   }
 
 
-  _pause_time = 0.0;
-
   _manager->stopping_sound(this);
   _manager->stopping_sound(this);
   // The _paused flag should not be cleared here.  _paused is not like
   // 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
   // the Pause button on a cd/dvd player.  It is used as a flag to say
@@ -239,8 +176,6 @@ finished() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void OpenALAudioSound::
 void OpenALAudioSound::
 set_loop(bool loop) {
 set_loop(bool loop) {
-  openal_audio_debug("set_loop(loop="<<loop<<")");
-  // loop count of 0 means always loop
   set_loop_count((loop)?0:1);
   set_loop_count((loop)?0:1);
 }
 }
 
 
@@ -251,8 +186,7 @@ set_loop(bool loop) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool OpenALAudioSound::
 bool OpenALAudioSound::
 get_loop() const {
 get_loop() const {
-  openal_audio_debug("get_loop() returning "<<(_loop_count==0));
-  return (_loop_count == 0);
+  return (_loop_count != 1);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -268,14 +202,17 @@ set_loop_count(unsigned long loop_count) {
     audio_error("OpenALAudioSound::set_loop_count() doesn't support looping a finite number of times, 0 (infinite) or 1 only");
     audio_error("OpenALAudioSound::set_loop_count() doesn't support looping a finite number of times, 0 (infinite) or 1 only");
     loop_count = 1;
     loop_count = 1;
   }
   }
-
-  if (_loop_count!=loop_count) {
-    _loop_count=loop_count;
+  
+  if (_loop_count==loop_count) {
+    return;
   }
   }
-
+  
+  _loop_count=loop_count;
+  
   if (_source) {
   if (_source) {
+    // I believe there is a race condition here.
     _manager->make_current();
     _manager->make_current();
-
+    
     alGetError(); // clear errors
     alGetError(); // clear errors
     alSourcei(_source,AL_LOOPING,_loop_count==0?AL_TRUE:AL_FALSE);
     alSourcei(_source,AL_LOOPING,_loop_count==0?AL_TRUE:AL_FALSE);
     al_audio_errcheck("alSourcei(_source,AL_LOOPING)");
     al_audio_errcheck("alSourcei(_source,AL_LOOPING)");
@@ -289,7 +226,6 @@ set_loop_count(unsigned long loop_count) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 unsigned long OpenALAudioSound::
 unsigned long OpenALAudioSound::
 get_loop_count() const {
 get_loop_count() const {
-  openal_audio_debug("get_loop_count() returning "<<_loop_count);
   return _loop_count;
   return _loop_count;
 }
 }
 
 
@@ -300,32 +236,63 @@ get_loop_count() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void OpenALAudioSound::
 void OpenALAudioSound::
 set_time(float time) {
 set_time(float time) {
-  openal_audio_debug("set_time(time="<<time<<")");
-
-  //nassertv(_source);
+  float px,py,pz,vx,vy,vz;
   
   
-  // Ensure we don't inadvertently run off the end of the sound.
-  float max_time = length();
-  if (time > max_time) {
-    openalAudio_cat.warning()
-      << "set_time(" << time << ") requested for sound of length " 
-      << max_time << "\n";
-    time = max_time;
+  openal_audio_debug("play()");
+  if (!_active) {
+    _paused=true;
+    return;
   }
   }
-
-  if (_source) {
-    _manager->make_current();
-
-    alGetError(); // clear errors
-    alSourcef(_source,AL_SEC_OFFSET,time);
-    al_audio_errcheck("alSourcef(_source,AL_SEC_OFFSET)");
+  
+  if (status() == AudioSound::PLAYING) {
+    stop();
+  }
+  
+  _manager->starting_sound(this);
+  
+  if (!_source) {
+    return;
   }
   }
 
 
-  if (status()==PLAYING) {
-    _pause_time = 0.0;
-  } else {
-    _pause_time = time;
+  // 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="<<time<<")");
+
+  alSourcef(_source,AL_SEC_OFFSET,time);
+  al_audio_errcheck("alSourcef(_source,AL_SEC_OFFSET)");
+
+  alSourcePlay(_source);
+  al_audio_errcheck("alSourcePlay(_source)");
+  
+  audio_debug("  started sound " << _path );
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -336,19 +303,16 @@ set_time(float time) {
 float OpenALAudioSound::
 float OpenALAudioSound::
 get_time() const {
 get_time() const {
   float time;
   float time;
-
-  //nassertv(_source);
-
+  
   if (_source) {
   if (_source) {
     _manager->make_current();
     _manager->make_current();
-
     alGetError(); // clear errors
     alGetError(); // clear errors
     alGetSourcef(_source,AL_SEC_OFFSET,&time);
     alGetSourcef(_source,AL_SEC_OFFSET,&time);
     al_audio_errcheck("alGetSourcef(_source,AL_SEC_OFFSET)");
     al_audio_errcheck("alGetSourcef(_source,AL_SEC_OFFSET)");
   } else {
   } else {
-    time = _pause_time;
+    return 0.0;
   }
   }
-  openal_audio_debug("get_time() returning "<<time);
+  
   return time;
   return time;
 }
 }
 
 
@@ -455,7 +419,7 @@ get_play_rate() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 float OpenALAudioSound::
 float OpenALAudioSound::
 length() const {
 length() const {
-  return _sd->get_length();
+  return _sample->_length;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -674,7 +638,7 @@ get_finished_event() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 const string& OpenALAudioSound::
 const string& OpenALAudioSound::
 get_name() const {
 get_name() const {
-  return _file_name;
+  return _path;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -685,18 +649,18 @@ get_name() const {
 AudioSound::SoundStatus OpenALAudioSound::
 AudioSound::SoundStatus OpenALAudioSound::
 status() const {
 status() const {
   ALenum status;
   ALenum status;
-
+  
   if (_source==0) {
   if (_source==0) {
     //return AudioSound::BAD;
     //return AudioSound::BAD;
     return AudioSound::READY;
     return AudioSound::READY;
   }
   }
-
+  
   _manager->make_current();
   _manager->make_current();
-
+  
   alGetError(); // clear errors
   alGetError(); // clear errors
   alGetSourcei(_source,AL_SOURCE_STATE,&status);
   alGetSourcei(_source,AL_SOURCE_STATE,&status);
   al_audio_errcheck("alGetSourcei(_source,AL_SOURCE_STATE)");
   al_audio_errcheck("alGetSourcei(_source,AL_SOURCE_STATE)");
-
+  
   if (status == AL_PLAYING/* || status == AL_PAUSED*/) {
   if (status == AL_PLAYING/* || status == AL_PAUSED*/) {
     return AudioSound::PLAYING;
     return AudioSound::PLAYING;
   } else {
   } 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 //]
 #endif //]

+ 15 - 10
panda/src/audiotraits/openalAudioSound.h

@@ -27,10 +27,10 @@
 #ifdef HAVE_OPENAL //[
 #ifdef HAVE_OPENAL //[
 
 
 #include "audioSound.h"
 #include "audioSound.h"
+#include "movieAudioCursor.h"
 
 
 #include <al.h>
 #include <al.h>
 #include <alc.h>
 #include <alc.h>
-#include <alut.h>
 
 
 class EXPCL_OPENAL_AUDIO OpenALAudioSound : public AudioSound {
 class EXPCL_OPENAL_AUDIO OpenALAudioSound : public AudioSound {
   friend class OpenALAudioManager;
   friend class OpenALAudioManager;
@@ -113,22 +113,27 @@ public:
   void finished();
   void finished();
 
 
 private:
 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();
   void cleanup();
 
 
 private:
 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;
   ALuint _source;
   PT(OpenALAudioManager) _manager;
   PT(OpenALAudioManager) _manager;
-
+  
   float _volume; // 0..1.0
   float _volume; // 0..1.0
   float _balance; // -1..1
   float _balance; // -1..1
   float _play_rate; // 0..1.0
   float _play_rate; // 0..1.0
 
 
-  float _pause_time;
-
   bool _positional;
   bool _positional;
   ALfloat _location[3];
   ALfloat _location[3];
   ALfloat _velocity[3];
   ALfloat _velocity[3];
@@ -144,8 +149,8 @@ private:
   // when the sound finishes playing.  It is not triggered
   // when the sound finishes playing.  It is not triggered
   // when the sound is stopped with stop().
   // when the sound is stopped with stop().
   string _finished_event;
   string _finished_event;
-
-  string _file_name;
+  
+  Filename _path;
 
 
   // _active is for things like a 'turn off sound effects' in
   // _active is for things like a 'turn off sound effects' in
   // a preferences pannel.
   // a preferences pannel.