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