Przeglądaj źródła

new audiotraits for new system

Dave Schuyler 24 lat temu
rodzic
commit
f9b240fb27

+ 32 - 0
panda/src/audiotraits/Sources.pp

@@ -0,0 +1,32 @@
+#define OTHER_LIBS dtoolconfig dtool
+#define DIRECTORY_IF_AUDIO yes
+
+#begin lib_target
+  #define USE_RAD_MSS yes
+  #define TARGET miles_audio
+  #define BUILDING_DLL BUILDING_MILES_AUDIO
+  #define LOCAL_LIBS audio
+
+  #define SOURCES \
+      config_milesAudio.cxx config_milesAudio.h \
+      milesAudioManager.cxx milesAudioManager.h \
+      milesAudioSound.I milesAudioSound.cxx milesAudioSound.h
+
+#end lib_target
+
+//#begin lib_target
+//  #define TARGET audio_linux
+//  #define BUILDING_DLL BUILDING_MISC
+//  //#define LOCAL_LIBS \
+//  //  audio
+//
+//  #define SOURCES \
+//    $[if $[HAVE_SYS_SOUNDCARD_H], \
+//      linuxAudioManager.cxx linuxAudioManager.h \
+//      linuxAudioSound.cxx linuxAudioSound.h \
+//    , \
+//      nullAudioManager.cxx nullAudioManager.h \
+//      nullAudioSound.cxx nullAudioSound.h \
+//    ]
+//
+//#end lib_target

+ 60 - 0
panda/src/audiotraits/config_milesAudio.cxx

@@ -0,0 +1,60 @@
+// Filename: config_milesAudio.cxx
+// Created by:  skyler
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "config_milesAudio.h"
+#include "milesAudioManager.h"
+#include "milesAudioSound.h"
+#include "dconfig.h"
+
+ConfigureDef(config_milesAudio);
+NotifyCategoryDef(milesAudio, "");
+
+ConfigureFn(config_milesAudio) {
+  init_libMilesAudio();
+}
+/*
+const float LinearIntegrator::_max_linear_dt =
+  config_milesAudio.GetFloat("default_max_linear_dt", 1.0f / 30.0f);
+
+const float AngularIntegrator::_max_angular_dt =
+  config_milesAudio.GetFloat("default_max_angular_dt", 1.0f / 30.0f);
+
+int LinearNoiseForce::_random_seed =
+  config_milesAudio.GetInt("default_noise_force_seed", 665);
+
+const float milesAudioObject::_default_terminal_velocity =
+  config_milesAudio.GetFloat("default_terminal_velocity", 400.0f);*/
+
+////////////////////////////////////////////////////////////////////
+//     Function: init_libMilesAudio
+//  Description: Initializes the library.  This must be called at
+//               least once before any of the functions or classes in
+//               this library can be used.  Normally it will be
+//               called by the static initializers and need not be
+//               called explicitly, but special cases exist.
+////////////////////////////////////////////////////////////////////
+void
+init_libMilesAudio() {
+  static bool initialized = false;
+  if (initialized) {
+    return;
+  }
+  initialized = true;
+  
+  AudioManager::register_AudioManager_creator(Create_AudioManager);
+}

+ 31 - 0
panda/src/audiotraits/config_milesAudio.h

@@ -0,0 +1,31 @@
+// Filename: config_milesAudio.h
+// Created by:  skyler
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CONFIG_MILESAUDIO_H
+#define CONFIG_MILESAUDIO_H
+
+#include "pandabase.h"
+#include "notifyCategoryProxy.h"
+#include "dconfig.h"
+
+ConfigureDecl(config_milesAudio, EXPCL_MILES_AUDIO, EXPTP_MILES_AUDIO);
+NotifyCategoryDecl(milesAudio, EXPCL_MILES_AUDIO, EXPTP_MILES_AUDIO);
+
+extern EXPCL_MILES_AUDIO void init_libMilesAudio();
+
+#endif // CONFIG_MILESAUDIO_H

+ 282 - 0
panda/src/audiotraits/milesAudioManager.cxx

@@ -0,0 +1,282 @@
+// Filename: milesAudioManager.cxx
+// Created by:  skyler (June 6, 2001)
+// Prior system by: cary
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "pandabase.h"
+#ifdef HAVE_RAD_MSS //[
+
+#include "milesAudioManager.h"
+#include "config_audio.h"
+#include "config_util.h"
+
+int MilesAudioManager::_active_managers;
+HDLSFILEID MilesAudioManager::_dls_field;
+
+AudioManager* Create_AudioManager() {
+  audio_debug("Create_AudioManger()");
+  return new MilesAudioManager();
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::MilesAudioManager
+//       Access: Public
+//  Description: set the overall volume of SFX
+////////////////////////////////////////////////////////////////////
+MilesAudioManager::
+MilesAudioManager() {
+  audio_debug("MilesAudioManager::MilesAudioManager()");
+  audio_debug("  audio_active="<<audio_active);
+  audio_debug("  audio_volume="<<audio_volume);
+  _active = audio_active;
+  _volume = audio_volume;
+  if (!_active_managers) {
+    S32 use_digital=(audio_play_wave || audio_play_mp3)?1:0;
+    S32 use_MIDI=(audio_play_midi)?1:0;
+    if (audio_play_midi && audio_software_midi) {
+      use_MIDI=AIL_QUICK_DLS_ONLY;
+    }
+    audio_debug("  use_digital="<<use_digital);
+    audio_debug("  use_MIDI="<<use_MIDI);
+    audio_debug("  audio_output_rate="<<audio_output_rate);
+    audio_debug("  audio_output_bits="<<audio_output_bits);
+    audio_debug("  audio_output_channels="<<audio_output_channels);
+    audio_debug("  audio_software_midi="<<audio_software_midi);
+    if (AIL_quick_startup(use_digital, 
+        use_MIDI, audio_output_rate, 
+        audio_output_bits, audio_output_channels)) {
+      if (audio_software_midi) {
+        // Load the downloadable sounds file:
+        HDLSDEVICE dls;
+        AIL_quick_handles(0, 0, &dls);
+        nassertv(audio_dls_file);
+        nassertv(!_dls_field);
+        audio_debug("  audio_dls_file=\""<<*audio_dls_file<<"\"");
+        _dls_field=AIL_DLS_load_file(dls, audio_dls_file->c_str(), 0);
+        if (!_dls_field) {
+          audio_error("  AIL_DLS_load_memory() failed, \""<<AIL_last_error()
+              <<"\" Switching to hardware midi");
+          AIL_quick_shutdown();
+          if (!AIL_quick_startup(use_digital, 1, audio_output_rate, 
+              audio_output_bits, audio_output_channels)) {
+            audio_error("  startup failed, "<<AIL_last_error());
+          }
+        } else {
+          audio_debug("  using Miles software midi");
+        }
+      }
+    } else {
+      audio_debug("  AIL_quick_startup failed: "<<AIL_last_error());
+    }
+  }
+  // We increment _active_managers regardless of possible errors above.
+  // The miles shutdown call will do the right thing when it's called,
+  // either way.
+  audio_debug("  _active_managers="<<_active_managers);
+  ++_active_managers;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::MilesAudioManager
+//       Access: Public
+//  Description: set the overall volume of SFX
+////////////////////////////////////////////////////////////////////
+MilesAudioManager::
+~MilesAudioManager() {
+  audio_debug("MilesAudioManager::~MilesAudioManager()");
+  // Be sure to delete associated sounds before deleting the manager:
+  nassertv(_soundsOnLoan.empty());
+  SoundMap::iterator i=_sounds.begin();
+  for (; i!=_sounds.end(); ++i) {
+    AIL_quick_unload(i->second);
+  }
+  _sounds.clear();
+  --_active_managers;
+  if (!_active_managers) {
+    if (audio_software_midi) {
+      HDLSDEVICE dls;
+      AIL_quick_handles(0, 0, &dls);
+      AIL_DLS_unload(dls, _dls_field);
+      #ifndef NDEBUG //[
+        // Clear _dls_field in debug version (for assert in ctor):
+        _dls_field=0;
+      #endif //]
+    }
+    AIL_quick_shutdown();
+    audio_debug("  AIL_quick_shutdown()");
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::load
+//       Access: 
+//  Description: 
+////////////////////////////////////////////////////////////////////
+HAUDIO MilesAudioManager::
+load(Filename file_name) {
+  string stmp = file_name.to_os_specific();
+  audio_debug("  \"" << stmp << "\"");
+  HAUDIO audio = AIL_quick_load(stmp.c_str());
+  if (!audio) {
+    audio_debug("  MilesAudioManager::load failed "<<AIL_last_error());
+  }
+  return audio;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::get_sound
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+AudioSound* MilesAudioManager::
+get_sound(const string& file_name) {
+  audio_debug("MilesAudioManager::get_sound(file_name=\""<<file_name<<"\"");
+  Filename path = file_name;
+  path.resolve_filename(get_sound_path());
+  audio_debug("  resolved file_name is '"<<path<<"'");
+
+  HAUDIO audio=0;
+  // 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.
+    audio = (*si).second;
+    audio_debug("  sound found in pool 0x" << (void*)audio);
+  } else {
+    // ...the sound was not found in the cache/pool.
+    audio=load(path);
+    if (audio) {
+      // Put it in the pool:
+      // The following is roughly like: _sounds[path] = audio;
+      // But, it gives us an iterator into the map.
+      pair<SoundMap::const_iterator, bool> ib 
+          =_sounds.insert(pair<string, HAUDIO>(path, audio));
+      if (!ib.second) {
+        // The insert failed.
+        audio_debug("  failed map insert of "<<path);
+        return 0;
+      }
+      // Set si, so that we can get a reference to the path 
+      // for the MilesAudioSound.
+      si=ib.first;
+    }
+  }
+  // Create an AudioSound from the sound:
+  AudioSound* audioSound = 0;
+  if (audio) {
+    MilesAudioSound* milesAudioSound
+        =new MilesAudioSound(*this, audio, (*si).first);
+    nassertr(milesAudioSound, 0);
+    milesAudioSound->set_active(_active);
+    _soundsOnLoan.insert(milesAudioSound);
+    audioSound=milesAudioSound;
+  }
+  audio_debug("  returning 0x" << (void*)audioSound);
+  return audioSound;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::drop_sound
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void MilesAudioManager::
+drop_sound(const string& file_name) {
+  audio_debug("MilesAudioManager::drop_sound(file_name=\""
+      <<file_name<<"\"");
+  Filename path = file_name;
+  path.resolve_filename(get_sound_path());
+  audio_debug("  path=\""<<path<<"\"");
+  SoundMap::iterator i=_sounds.find(path);
+  if (i != _sounds.end()) {
+    AIL_quick_unload(i->second);
+    _sounds.erase(i);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::release_sound
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void MilesAudioManager::
+release_sound(MilesAudioSound* audioSound) {
+  audio_debug("MilesAudioManager::release_sound(audioSound=\""
+      <<audioSound->get_name()<<"\"");
+  _soundsOnLoan.erase(audioSound);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::set_volume
+//       Access: Public
+//  Description: set the overall volume
+////////////////////////////////////////////////////////////////////
+void MilesAudioManager::
+set_volume(float volume) {
+  audio_debug("MilesAudioManager::set_volume(volume="<<volume<<")");
+  if (_volume!=volume) {
+    _volume = volume;
+    // Tell our AudioSounds to adjust:
+    AudioSet::iterator i=_soundsOnLoan.begin();
+    for (; i!=_soundsOnLoan.end(); ++i) {
+      (**i).set_volume((**i).get_volume());
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::get_volume
+//       Access: Public
+//  Description: get the overall volume
+////////////////////////////////////////////////////////////////////
+float MilesAudioManager::
+get_volume() {
+  audio_debug("MilesAudioManager::get_volume() returning "<<_volume);
+  return _volume;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::set_active
+//       Access: Public
+//  Description: turn on/off
+////////////////////////////////////////////////////////////////////
+void MilesAudioManager::
+set_active(bool active) {
+  audio_debug("MilesAudioManager::set_active(flag="<<active<<")");
+  if (_active!=active) {
+    _active=active;
+    // Tell our AudioSounds to adjust:
+    AudioSet::iterator i=_soundsOnLoan.begin();
+    for (; i!=_soundsOnLoan.end(); ++i) {
+      (**i).set_active(_active);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MilesAudioManager::get_active
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+bool MilesAudioManager::
+get_active() {
+  audio_debug("MilesAudioManager::get_active() returning "<<_active);
+  return _active;
+}
+
+#endif //]

+ 68 - 0
panda/src/audiotraits/milesAudioManager.h

@@ -0,0 +1,68 @@
+// Filename: milesAudioManager.h
+// Created by:  skyler (June 6, 2001)
+// Prior system by: cary
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef __MILES_AUDIO_MANAGER_H__ //[
+#define __MILES_AUDIO_MANAGER_H__
+
+#include <pandabase.h>
+#ifdef HAVE_RAD_MSS //[
+
+#include "audioManager.h"
+#include "milesAudioSound.h"
+
+class EXPCL_MILES_AUDIO MilesAudioManager: public AudioManager {
+public:
+  MilesAudioManager();
+  ~MilesAudioManager();
+
+  AudioSound* get_sound(const string& file_name);
+  void drop_sound(const string& file_name);
+
+  void set_volume(float volume);
+  float get_volume();
+  
+  void set_active(bool active);
+  bool get_active();
+
+private:
+  typedef pmap<string, HAUDIO > SoundMap;
+  SoundMap _sounds;
+  typedef pset<MilesAudioSound* > AudioSet;
+  AudioSet _soundsOnLoan;
+  float _volume;
+  bool _active;
+  // keep a count for startup and shutdown:
+  static int _active_managers;
+  static HDLSFILEID _dls_field;
+  
+  HAUDIO load(Filename file_name);
+  // Tell the manager that the sound dtor was called.
+  void release_sound(MilesAudioSound* audioSound);
+  
+  friend MilesAudioSound;
+};
+
+EXPCL_MILES_AUDIO AudioManager* Create_AudioManager();
+
+
+#endif //]
+
+#endif //]
+
+

+ 24 - 0
panda/src/audiotraits/milesAudioSound.I

@@ -0,0 +1,24 @@
+// Filename: milesAudioSound.I
+// Created by:  skyler (June 6, 2001)
+// Prior system by: cary
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+
+
+
+

+ 224 - 0
panda/src/audiotraits/milesAudioSound.cxx

@@ -0,0 +1,224 @@
+// Filename: milesAudioSound.cxx
+// Created by:  skyler (June 6, 2001)
+// Prior system by: cary
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include <pandabase.h>
+#ifdef HAVE_RAD_MSS //[
+
+#include "milesAudioSound.h"
+#include "milesAudioManager.h"
+
+
+MilesAudioSound::
+MilesAudioSound(MilesAudioManager& manager,
+    HAUDIO audio, string file_name)
+    : _manager(manager), _file_name(file_name),
+    _start_time(0), _volume(1.0), _balance(0),
+    _loop_count(1),
+    _active(true), _paused(false) {
+  nassertv(audio);
+  nassertv(!file_name.empty());
+  audio_debug("MilesAudioSound::MilesAudioSound(manager=0x"<<(void*)&manager
+      <<", audio=0x"<<(void*)audio<<", file_name="<<file_name<<")");
+  // Make our own copy of the sound header data:
+  _audio=AIL_quick_copy(audio);
+}
+
+MilesAudioSound::
+~MilesAudioSound() {
+  audio_debug("MilesAudioSound::~MilesAudioSound() "<<get_name());
+  _manager.release_sound(this);
+  AIL_quick_unload(_audio);
+}
+
+void MilesAudioSound::
+play() {
+  audio_debug("MilesAudioSound::play() "<<get_name());
+  if (_active) {
+    // Start playing:
+    if (AIL_quick_play(_audio, _loop_count)) {
+      audio_debug("  started sound");
+    } else {
+      audio_debug("  failed to play sound "<<AIL_last_error());
+    }
+  } else {
+    // In case _loop_count gets set to forever (zero):
+    audio_debug("  paused");
+    _paused=true;
+  }
+}
+
+void MilesAudioSound::
+stop() {
+  audio_debug("MilesAudioSound::stop() "<<get_name());
+  AIL_quick_halt(_audio);
+}
+
+void MilesAudioSound::
+set_loop(bool loop) {
+  audio_debug("MilesAudioSound::set_loop(loop="<<loop<<") "<<get_name());
+  set_loop_count((loop)?0:1);
+}
+
+bool MilesAudioSound::
+get_loop() const {
+  audio_debug("MilesAudioSound::get_loop() returning "<<(_loop_count==0));
+  return _loop_count == 0;
+}
+
+void MilesAudioSound::
+set_loop_count(unsigned long loop_count) {
+  audio_debug("MilesAudioSound::set_loop_count(loop_count="<<loop_count<<") "<<get_name());
+  if (_loop_count!=loop_count) {
+    _loop_count=loop_count;
+    if (status()==PLAYING) {
+      stop();
+      play();
+    }
+  }
+}
+
+unsigned long MilesAudioSound::
+get_loop_count() const {
+  audio_debug("MilesAudioSound::get_loop_count() returning "<<_loop_count);
+  return _loop_count;
+}
+
+void MilesAudioSound::set_time(float start_time) {
+  audio_debug("MilesAudioSound::set_time(start_time="<<start_time<<") "<<get_name());
+  _start_time=start_time;
+  S32 milisecond_start_time=S32(1000*_start_time);
+  AIL_quick_set_ms_position(_audio, milisecond_start_time);
+}
+
+float MilesAudioSound::get_time() const {
+  audio_debug("MilesAudioSound::get_time() returning "<<_start_time);
+  return _start_time;
+}
+
+void MilesAudioSound::set_volume(float volume) {
+  audio_debug("MilesAudioSound::set_volume(volume="<<volume<<") "<<get_name());
+  // *Set the volume even if our volume is not changing, because the
+  // *MilesAudioManager will call set_volume when *its* volume changes.
+  // Set the volume:
+  _volume=volume;
+  // Account for the category of sound:
+  volume*=_manager.get_volume();
+  // Change to Miles volume, range 0 to 127:
+  S32 milesVolume=(S32(127*volume))%128;
+  // Account for type:
+  S32 audioType=AIL_quick_type(_audio);
+  if (audioType==AIL_QUICK_XMIDI_TYPE
+      ||
+      audioType==AIL_QUICK_DLS_XMIDI_TYPE) {
+    // ...it's a midi file.
+    AIL_quick_set_volume(_audio, milesVolume, 0); // 0 delay.
+    audio_debug("  volume for this midi is now "<<milesVolume);
+  } else {
+    // ...it's a wav or mp3.
+    // Convert balance of -1.0..1.0 to 0..127:
+    S32 milesBalance=(S32(63.5*(_balance+1.0)))%128;
+    AIL_quick_set_volume(_audio, milesVolume, milesBalance);
+    audio_debug("  volume for this wav or mp3 is now "<<milesVolume
+        <<", balance="<<milesBalance);
+  }
+}
+
+float MilesAudioSound::get_volume() const {
+  audio_debug("MilesAudioSound::get_volume() returning "<<_volume);
+  return _volume;
+}
+
+void MilesAudioSound::set_active(bool active) {
+  audio_debug("MilesAudioSound::set_active(active="<<active<<") "<<get_name());
+  if (_active!=active) {
+    _active=active;
+    if (_active) {
+      // ...activate the sound.
+      if (_paused
+          &&
+          _loop_count==0) {
+        // ...this sound was looping when it was paused.
+        _paused=false;
+        play();
+      }
+    } else {
+      // ...deactivate the sound.
+      if (status()==PLAYING) {
+        if (_loop_count==0) {
+          // ...we're pausing a looping sound.
+          _paused=true;
+        }
+        stop();
+      }
+    }
+  }
+}
+
+bool MilesAudioSound::get_active() const {
+  audio_debug("MilesAudioSound::get_active() returning "<<_active);
+  return _active;
+}
+
+void MilesAudioSound::set_balance(float balance_right) {
+  audio_debug("MilesAudioSound::set_balance(balance_right="<<balance_right<<") "<<get_name());
+  _balance=balance_right;
+  // Call set_volume to effect the change:
+  set_volume(_volume);
+}
+
+float MilesAudioSound::get_balance() const {
+  audio_debug("MilesAudioSound::get_balance() returning "<<_balance);
+  return _balance;
+}
+
+float MilesAudioSound::length() const {
+  float length;
+  if (AIL_quick_status(_audio)==QSTAT_PLAYING) {
+    length=((float)AIL_quick_ms_length(_audio))*0.001;
+  } else {
+    AIL_quick_play(_audio, 1);
+    length=((float)AIL_quick_ms_length(_audio))*0.001;
+    AIL_quick_halt(_audio);
+  }
+  audio_debug("MilesAudioSound::length() returning "<<length);
+  return length;
+}
+
+const string& MilesAudioSound::get_name() const {
+  //audio_debug("MilesAudioSound::get_name() returning "<<_file_name);
+  return _file_name;
+}
+
+AudioSound::SoundStatus MilesAudioSound::status() const {
+  if (!_audio) {
+    return AudioSound::BAD;
+  }
+  switch (AIL_quick_status(_audio)) {
+    case QSTAT_LOADED:
+    case QSTAT_DONE:
+      return AudioSound::READY;
+    case QSTAT_PLAYING:
+      return AudioSound::PLAYING;
+    default:
+      return AudioSound::BAD;
+  }
+}
+
+
+#endif //]

+ 102 - 0
panda/src/audiotraits/milesAudioSound.h

@@ -0,0 +1,102 @@
+// Filename: milesAudioSound.h
+// Created by:  skyler (June 6, 2001)
+// Prior system by: cary
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef __MILES_AUDIO_SOUND_H__
+#define __MILES_AUDIO_SOUND_H__
+
+#include <pandabase.h>
+#ifdef HAVE_RAD_MSS //[
+
+#include "audioSound.h"
+#include "mss.h"
+
+
+class MilesAudioManager;
+
+class EXPCL_MILES_AUDIO MilesAudioSound : public AudioSound {
+public:
+  ~MilesAudioSound();
+  
+  // For best compatability, set the loop_count, start_time,
+  // volume, and balance, prior to calling play().  You may
+  // set them while they're playing, but it's implementation
+  // specific whether you get the results.
+  void play();
+  void stop();
+  
+  // loop: 0 = play once; 1 = play forever.
+  // inits to false.
+  void set_loop(bool loop=false);
+  bool get_loop() const;
+  
+  // loop_count: 0 = forever; 1 = play once; n = play n times.
+  // inits to 1.
+  void set_loop_count(unsigned long loop_count=1);
+  unsigned long get_loop_count() const;
+  
+  // 0 = begining; length() = end.
+  // inits to 0.0.
+  void set_time(float start_time=0.0);
+  float get_time() const;
+  
+  // 0 = minimum; 1.0 = maximum.
+  // inits to 1.0.
+  void set_volume(float volume=1.0);
+  float get_volume() const;
+  
+  // -1.0 is hard left
+  // 0.0 is centered
+  // 1.0 is hard right
+  // inits to 0.0.
+  void set_balance(float balance_right=0.0);
+  float get_balance() const;
+
+  // inits to manager's state.
+  void set_active(bool active=true);
+  bool get_active() const;
+  
+  const string& get_name() const;
+  
+  // return: playing time in seconds.
+  float length() const;
+
+  AudioSound::SoundStatus status() const;
+
+private:
+  HAUDIO _audio;
+  MilesAudioManager& _manager;
+  float _start_time; // 0..length()
+  float _volume; // 0..1.0
+  float _balance; // -1..1
+  unsigned long _loop_count;
+  string _file_name;
+  bool _active;
+  bool _paused;
+
+  MilesAudioSound(MilesAudioManager& manager, 
+      HAUDIO audio, string file_name);
+
+  friend class MilesAudioManager;
+};
+
+#include "milesAudioSound.I"
+
+#endif //]
+
+#endif /* __MILES_AUDIO_SOUND_H__ */