mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
miles streaming
This commit is contained in:
parent
e51f0b2baf
commit
15f2e539d6
@ -209,7 +209,7 @@ setSpeakerSetup(SpeakerModeCategory cat) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::update()
|
||||
// Access: Published
|
||||
// Access: Published, Virtual
|
||||
// Description: Must be called every frame. Failure to call this
|
||||
// every frame could cause problems for some audio
|
||||
// managers.
|
||||
@ -296,7 +296,7 @@ float AudioManager::audio_3d_get_drop_off_factor() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::get_dls_pathname
|
||||
// Access: Public
|
||||
// Access: Published, Static
|
||||
// Description: Returns the full pathname to the DLS file, as
|
||||
// specified by the Config.prc file, or the default for
|
||||
// the current OS if appropriate. Returns empty string
|
||||
@ -337,3 +337,23 @@ get_dls_pathname() {
|
||||
return Filename();
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::output
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::
|
||||
output(ostream &out) const {
|
||||
out << get_type();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::write
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioManager::
|
||||
write(ostream &out) const {
|
||||
out << (*this) << "\n";
|
||||
}
|
||||
|
@ -216,7 +216,10 @@ PUBLISHED:
|
||||
virtual void audio_3d_set_drop_off_factor(float factor);
|
||||
virtual float audio_3d_get_drop_off_factor() const;
|
||||
|
||||
Filename get_dls_pathname();
|
||||
static Filename get_dls_pathname();
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out) const;
|
||||
|
||||
public:
|
||||
static void register_AudioManager_creator(Create_AudioManager_proc* proc);
|
||||
@ -251,4 +254,10 @@ private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
inline ostream &
|
||||
operator << (ostream &out, const AudioManager &mgr) {
|
||||
mgr.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
#endif /* __AUDIO_MANAGER_H__ */
|
||||
|
@ -74,7 +74,7 @@ get_3d_max_distance() const {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::add_dsp
|
||||
// Function: AudioSound::add_dsp
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -85,7 +85,7 @@ add_dsp(PT(AudioDSP) x) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::remove_dsp
|
||||
// Function: AudioSound::remove_dsp
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -97,7 +97,7 @@ remove_dsp(PT(AudioDSP) x) {
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::getSpeakerMix
|
||||
// Function: AudioSound::getSpeakerMix
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -108,7 +108,7 @@ get_speaker_mix(int speaker) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::setSpeakerMix
|
||||
// Function: AudioSound::setSpeakerMix
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -119,7 +119,7 @@ set_speaker_mix(float frontleft, float frontright, float center, float sub, floa
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::get_priority
|
||||
// Function: AudioSound::get_priority
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -130,7 +130,7 @@ get_priority() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioManager::set_priority
|
||||
// Function: AudioSound::set_priority
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -140,3 +140,42 @@ set_priority(int priority) {
|
||||
;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSound::output
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioSound::
|
||||
output(ostream &out) const {
|
||||
out << get_type() << " " << get_name() << " " << status();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSound::write
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AudioSound::
|
||||
write(ostream &out) const {
|
||||
out << (*this) << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: AudioSound::SoundStatus::output operator
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ostream &
|
||||
operator << (ostream &out, AudioSound::SoundStatus status) {
|
||||
switch (status) {
|
||||
case AudioSound::BAD:
|
||||
return out << "BAD";
|
||||
|
||||
case AudioSound::READY:
|
||||
return out << "READY";
|
||||
|
||||
case AudioSound::PLAYING:
|
||||
return out << "PLAYING";
|
||||
}
|
||||
|
||||
return out << "**invalid AudioSound::SoundStatus(" << (int)status << ")**";
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
class AudioManager;
|
||||
|
||||
|
||||
class EXPCL_PANDA_AUDIO AudioSound : public TypedReferenceCount {
|
||||
PUBLISHED:
|
||||
virtual ~AudioSound();
|
||||
@ -138,6 +137,9 @@ class EXPCL_PANDA_AUDIO AudioSound : public TypedReferenceCount {
|
||||
enum SoundStatus { BAD, READY, PLAYING };
|
||||
virtual SoundStatus status() const = 0;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out) const;
|
||||
|
||||
protected:
|
||||
AudioSound();
|
||||
|
||||
@ -161,4 +163,13 @@ class EXPCL_PANDA_AUDIO AudioSound : public TypedReferenceCount {
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
inline ostream &
|
||||
operator << (ostream &out, const AudioSound &sound) {
|
||||
sound.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
EXPCL_PANDA_AUDIO ostream &
|
||||
operator << (ostream &out, AudioSound::SoundStatus status);
|
||||
|
||||
#endif /* __AUDIOSOUND_H__ */
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define BUILD_TARGET $[HAVE_RAD_MSS]
|
||||
#define USE_PACKAGES rad_mss
|
||||
#define BUILDING_DLL BUILDING_MILES_AUDIO
|
||||
#define LOCAL_LIBS audio event
|
||||
#define LOCAL_LIBS audio event pipeline
|
||||
#define WIN_SYS_LIBS $[WIN_SYS_LIBS] user32.lib advapi32.lib winmm.lib
|
||||
|
||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
|
||||
@ -16,10 +16,16 @@
|
||||
#define SOURCES \
|
||||
config_milesAudio.h \
|
||||
milesAudioManager.h \
|
||||
milesAudioSound.I milesAudioSound.h
|
||||
milesAudioSound.I milesAudioSound.h \
|
||||
milesAudioSample.I milesAudioSample.h \
|
||||
milesAudioSequence.I milesAudioSequence.h \
|
||||
milesAudioStream.I milesAudioStream.h \
|
||||
globalMilesManager.I globalMilesManager.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_milesAudio.cxx milesAudioManager.cxx milesAudioSound.cxx
|
||||
config_milesAudio.cxx milesAudioManager.cxx milesAudioSound.cxx \
|
||||
milesAudioStream.cxx globalMilesManager.cxx milesAudioSample.cxx \
|
||||
milesAudioSequence.cxx
|
||||
|
||||
#end lib_target
|
||||
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include "config_milesAudio.h"
|
||||
#include "milesAudioManager.h"
|
||||
#include "milesAudioSound.h"
|
||||
#include "milesAudioSample.h"
|
||||
#include "milesAudioSequence.h"
|
||||
#include "milesAudioStream.h"
|
||||
#include "pandaSystem.h"
|
||||
#include "dconfig.h"
|
||||
|
||||
@ -42,16 +45,26 @@ ConfigVariableInt miles_audio_expand_mp3_threshold
|
||||
"work around problems with Miles being unable to correctly "
|
||||
"report the length of, or seek within, a variable bit-rate encoded "
|
||||
"MP3 file. Any MP3 file whose length in bytes is less than "
|
||||
"this value will be expanded."));
|
||||
"this value will be expanded. This only applies to files "
|
||||
"within the miles-audio-preload-threshold."));
|
||||
|
||||
ConfigVariableInt miles_audio_calc_mp3_threshold
|
||||
("miles-audio-calc-mp3-threshold", 1048576,
|
||||
PRC_DESC("This is a second fallback for miles-audio-expand-mp3-threshold. "
|
||||
"Any MP3 file whose length in bytes is less than this value "
|
||||
"will have its length calculated on demand, by running through "
|
||||
"the entire file first. This works around a Miles bug in "
|
||||
"which variable bit-rate encoded MP3 files do not report an "
|
||||
"accurate length."));
|
||||
ConfigVariableInt miles_audio_preload_threshold
|
||||
("miles-audio-preload-threshold", -1,
|
||||
PRC_DESC("This is the last Miles fallback size, and should be no smaller "
|
||||
"than both miles-audio-expand-mp3-threshold and "
|
||||
"miles-audio-calc-mp3-threshold. Files that are smaller "
|
||||
"than this number of bytes will be preloaded and kept "
|
||||
"resident in memory, while files that are this size or larger "
|
||||
"will be streamed from disk. Set this to -1 to preload "
|
||||
"every file."));
|
||||
|
||||
ConfigVariableBool miles_audio_panda_threads
|
||||
("miles-audio-panda-threads", true,
|
||||
PRC_DESC("Set this true to service Miles background audio via Panda's "
|
||||
"threading interface, instead of Miles' built-in threading "
|
||||
"interface. This gives Panda more control over the threading, "
|
||||
"and ensures better lock protection within Panda. This has "
|
||||
"no meaning unless Panda is compiled with thread support."));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libMilesAudio
|
||||
@ -73,6 +86,9 @@ init_libMilesAudio() {
|
||||
|
||||
MilesAudioManager::init_type();
|
||||
MilesAudioSound::init_type();
|
||||
MilesAudioSample::init_type();
|
||||
MilesAudioSequence::init_type();
|
||||
MilesAudioStream::init_type();
|
||||
|
||||
PandaSystem *ps = PandaSystem::get_global_ptr();
|
||||
ps->add_system("Miles");
|
||||
|
@ -32,7 +32,8 @@ NotifyCategoryDecl(milesAudio, EXPCL_MILES_AUDIO, EXPTP_MILES_AUDIO);
|
||||
|
||||
extern ConfigVariableBool miles_audio_force_midi_reset;
|
||||
extern ConfigVariableInt miles_audio_expand_mp3_threshold;
|
||||
extern ConfigVariableInt miles_audio_calc_mp3_threshold;
|
||||
extern ConfigVariableInt miles_audio_preload_threshold;
|
||||
extern ConfigVariableBool miles_audio_panda_threads;
|
||||
|
||||
extern EXPCL_MILES_AUDIO void init_libMilesAudio();
|
||||
|
||||
|
29
panda/src/audiotraits/globalMilesManager.I
Normal file
29
panda/src/audiotraits/globalMilesManager.I
Normal file
@ -0,0 +1,29 @@
|
||||
// Filename: globalMilesManager.I
|
||||
// Created by: drose (30Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::is_open
|
||||
// Access: Public
|
||||
// Description: Returns true if the Miles Sound System is open (and
|
||||
// active), false if it is not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool GlobalMilesManager::
|
||||
is_open() const {
|
||||
return _is_open;
|
||||
}
|
489
panda/src/audiotraits/globalMilesManager.cxx
Normal file
489
panda/src/audiotraits/globalMilesManager.cxx
Normal file
@ -0,0 +1,489 @@
|
||||
// Filename: globalMilesManager.cxx
|
||||
// Created by: drose (26Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "globalMilesManager.h"
|
||||
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "mutexHolder.h"
|
||||
#include "milesAudioManager.h"
|
||||
#include "milesAudioSample.h"
|
||||
#include "milesAudioSequence.h"
|
||||
|
||||
GlobalMilesManager *GlobalMilesManager::_global_ptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GlobalMilesManager::
|
||||
GlobalMilesManager() :
|
||||
_managers_lock("GlobalMilesManager::_managers_lock"),
|
||||
_samples_lock("GlobalMilesManager::_samples_lock"),
|
||||
_sequences_lock("GlobalMilesManager::_sequences_lock")
|
||||
{
|
||||
_digital_driver = 0;
|
||||
_midi_driver = 0;
|
||||
_dls_device = 0;
|
||||
_dls_file = 0;
|
||||
_is_open = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::add_manager
|
||||
// Access: Public
|
||||
// Description: Records a new MilesAudioManager in the world. This
|
||||
// will open the Miles API when the first audio manager
|
||||
// is added.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
add_manager(MilesAudioManager *manager) {
|
||||
MutexHolder holder(_managers_lock);
|
||||
_managers.insert(manager);
|
||||
if (!_is_open) {
|
||||
open_api();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::remove_manager
|
||||
// Access: Public
|
||||
// Description: Records that a MilesAudioManager is destructing.
|
||||
// This will clsoe the Miles API when the last audio
|
||||
// manager is removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
remove_manager(MilesAudioManager *manager) {
|
||||
MutexHolder holder(_managers_lock);
|
||||
_managers.erase(manager);
|
||||
if (_managers.empty() && _is_open) {
|
||||
close_api();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::cleanup
|
||||
// Access: Public
|
||||
// Description: Calls cleanup() on all MilesAudioManagers, to cause a
|
||||
// clean shutdown.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
cleanup() {
|
||||
MutexHolder holder(_managers_lock);
|
||||
Managers::iterator mi;
|
||||
for (mi = _managers.begin(); mi != _managers.end(); ++mi) {
|
||||
(*mi)->cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::get_sample
|
||||
// Access: Public
|
||||
// Description: Gets a sample handle from the global pool for the
|
||||
// digital output device, to be used with the indicated
|
||||
// AudioSound.
|
||||
//
|
||||
// If successful, sets the sample handle and the index
|
||||
// (which should later be used to release the sample)
|
||||
// and returns true. If unsuccessful (because there are
|
||||
// no more available handles), returns false.
|
||||
//
|
||||
// This is a very limited resource; you should only get
|
||||
// a sample just before playing a sound.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GlobalMilesManager::
|
||||
get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound) {
|
||||
MutexHolder holder(_samples_lock);
|
||||
|
||||
for (size_t i = 0; i < _samples.size(); ++i) {
|
||||
SampleData &smp = _samples[i];
|
||||
if (AIL_sample_status(smp._sample) == SMP_DONE) {
|
||||
if (smp._sound != NULL) {
|
||||
// Tell the last sound that was using this sample that it's
|
||||
// done now.
|
||||
smp._sound->internal_stop();
|
||||
}
|
||||
smp._sound = sound;
|
||||
sample = smp._sample;
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No more already-allocated samples; get a new one from the system.
|
||||
sample = AIL_allocate_sample_handle(_digital_driver);
|
||||
if (sample == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AIL_init_sample(sample, DIG_F_STEREO_16, 0);
|
||||
index = _samples.size();
|
||||
|
||||
SampleData smp;
|
||||
smp._sound = sound;
|
||||
smp._sample = sample;
|
||||
_samples.push_back(smp);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::release_sample
|
||||
// Access: Public
|
||||
// Description: Indicates that the indicated AudioSound no longer
|
||||
// needs this sample.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
release_sample(size_t index, MilesAudioSample *sound) {
|
||||
MutexHolder holder(_samples_lock);
|
||||
nassertv(index < _samples.size());
|
||||
|
||||
SampleData &smp = _samples[index];
|
||||
if (smp._sound == sound) {
|
||||
smp._sound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::get_sequence
|
||||
// Access: Public
|
||||
// Description: Gets a sequence handle from the global pool for the
|
||||
// digital output device, to be used with the indicated
|
||||
// AudioSound.
|
||||
//
|
||||
// If successful, sets the sequence handle and the index
|
||||
// (which should later be used to release the sequence)
|
||||
// and returns true. If unsuccessful (because there are
|
||||
// no more available handles), returns false.
|
||||
//
|
||||
// This is a very limited resource; you should only get
|
||||
// a sequence just before playing a sound.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GlobalMilesManager::
|
||||
get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound) {
|
||||
MutexHolder holder(_sequences_lock);
|
||||
|
||||
for (size_t i = 0; i < _sequences.size(); ++i) {
|
||||
SequenceData &seq = _sequences[i];
|
||||
if (AIL_sequence_status(seq._sequence) == SEQ_DONE) {
|
||||
if (seq._sound != NULL) {
|
||||
// Tell the last sound that was using this sequence that it's
|
||||
// done now.
|
||||
seq._sound->internal_stop();
|
||||
}
|
||||
seq._sound = sound;
|
||||
sequence = seq._sequence;
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// No more already-allocated sequences; get a new one from the system.
|
||||
sequence = AIL_allocate_sequence_handle(_midi_driver);
|
||||
if (sequence == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
index = _sequences.size();
|
||||
|
||||
SequenceData seq;
|
||||
seq._sound = sound;
|
||||
seq._sequence = sequence;
|
||||
_sequences.push_back(seq);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::release_sequence
|
||||
// Access: Public
|
||||
// Description: Indicates that the indicated AudioSound no longer
|
||||
// needs this sequence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
release_sequence(size_t index, MilesAudioSequence *sound) {
|
||||
MutexHolder holder(_sequences_lock);
|
||||
nassertv(index < _sequences.size());
|
||||
|
||||
SequenceData &seq = _sequences[index];
|
||||
if (seq._sound == sound) {
|
||||
seq._sound = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::force_midi_reset
|
||||
// Access: Public
|
||||
// Description: Sometimes Miles seems to leave midi notes hanging,
|
||||
// even after stop is called, so call this method to
|
||||
// perform an explicit reset using winMM.dll calls, just
|
||||
// to ensure silence.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
force_midi_reset() {
|
||||
if (!miles_audio_force_midi_reset) {
|
||||
audio_debug("MilesAudioManager::skipping force_midi_reset");
|
||||
return;
|
||||
}
|
||||
audio_debug("MilesAudioManager::force_midi_reset");
|
||||
|
||||
#ifdef WIN32
|
||||
if ((_midi_driver!=NULL) && (_midi_driver->deviceid != MIDI_NULL_DRIVER) && (_midi_driver->hMidiOut != NULL)) {
|
||||
audio_debug("MilesAudioManager::calling midiOutReset");
|
||||
midiOutReset(_midi_driver->hMidiOut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::get_global_ptr
|
||||
// Access: Public, Static
|
||||
// Description: Returns the pointer to the one GlobalMilesManager
|
||||
// object.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
GlobalMilesManager *GlobalMilesManager::
|
||||
get_global_ptr() {
|
||||
if (_global_ptr == NULL) {
|
||||
_global_ptr = new GlobalMilesManager;
|
||||
}
|
||||
return _global_ptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::open_api
|
||||
// Access: Private
|
||||
// Description: Called internally to initialize the Miles API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
open_api() {
|
||||
audio_debug("GlobalMilesManager::open_api()")
|
||||
nassertv(!_is_open);
|
||||
|
||||
bool use_digital = (audio_play_wave || audio_play_mp3);
|
||||
if (audio_play_midi && audio_software_midi) {
|
||||
use_digital = true;
|
||||
}
|
||||
|
||||
#ifdef IS_OSX
|
||||
audio_software_midi = true;
|
||||
#endif
|
||||
|
||||
audio_debug(" use_digital="<<use_digital);
|
||||
audio_debug(" audio_play_midi="<<audio_play_midi);
|
||||
audio_debug(" audio_software_midi="<<audio_software_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 !defined(NDEBUG) && defined(AIL_MSS_version) //[
|
||||
char version[8];
|
||||
AIL_MSS_version(version, 8);
|
||||
audio_debug(" Mss32.dll Version: "<<version);
|
||||
#endif //]
|
||||
|
||||
if (!AIL_startup()) {
|
||||
milesAudio_cat.warning()
|
||||
<< "Miles Sound System already initialized!\n";
|
||||
}
|
||||
|
||||
AIL_set_file_callbacks(open_callback, close_callback,
|
||||
seek_callback, read_callback);
|
||||
|
||||
if (use_digital) {
|
||||
_digital_driver =
|
||||
AIL_open_digital_driver(audio_output_rate, audio_output_bits,
|
||||
audio_output_channels, 0);
|
||||
}
|
||||
|
||||
if (audio_play_midi) {
|
||||
if (audio_software_midi) {
|
||||
_midi_driver = AIL_open_XMIDI_driver(AIL_OPEN_XMIDI_NULL_DRIVER);
|
||||
|
||||
// Load the downloadable sounds file:
|
||||
_dls_device = AIL_DLS_open(_midi_driver, _digital_driver, NULL, 0,
|
||||
audio_output_rate, audio_output_bits,
|
||||
audio_output_channels);
|
||||
|
||||
Filename dls_pathname = AudioManager::get_dls_pathname();
|
||||
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->resolve_filename(dls_pathname, get_sound_path()) ||
|
||||
vfs->resolve_filename(dls_pathname, get_model_path());
|
||||
|
||||
_dls_data.clear();
|
||||
PT(VirtualFile) file = vfs->get_file(dls_pathname);
|
||||
if (file == (VirtualFile *)NULL) {
|
||||
milesAudio_cat.warning()
|
||||
<< "DLS file does not exist: " << dls_pathname << "\n";
|
||||
|
||||
} else if (!file->read_file(_dls_data, true)) {
|
||||
milesAudio_cat.warning()
|
||||
<< "Could not read DLS file: " << dls_pathname << "\n";
|
||||
|
||||
} else if (_dls_data.empty()) {
|
||||
milesAudio_cat.warning()
|
||||
<< "DLS file is empty: " << dls_pathname << "\n";
|
||||
|
||||
} else {
|
||||
_dls_file = AIL_DLS_load_memory(_dls_device, &_dls_data[0], 0);
|
||||
}
|
||||
|
||||
if (_dls_file == 0) {
|
||||
audio_error(" Could not get DLS file, switching to hardware MIDI.");
|
||||
AIL_DLS_close(_dls_device, 0);
|
||||
_dls_device = 0;
|
||||
AIL_close_XMIDI_driver(_midi_driver);
|
||||
_midi_driver = AIL_open_XMIDI_driver(0);
|
||||
|
||||
} else {
|
||||
audio_info(" using Miles software midi");
|
||||
}
|
||||
} else {
|
||||
_midi_driver = AIL_open_XMIDI_driver(0);
|
||||
audio_info(" using Miles hardware midi");
|
||||
}
|
||||
}
|
||||
|
||||
_is_open = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::close_api
|
||||
// Access: Private
|
||||
// Description: Called internally to shut down the Miles API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GlobalMilesManager::
|
||||
close_api() {
|
||||
audio_debug("GlobalMilesManager::close_api()")
|
||||
nassertv(_is_open);
|
||||
|
||||
Samples::iterator si;
|
||||
for (si = _samples.begin(); si != _samples.end(); ++si) {
|
||||
SampleData &smp = (*si);
|
||||
AIL_release_sample_handle(smp._sample);
|
||||
}
|
||||
_samples.clear();
|
||||
|
||||
Sequences::iterator qi;
|
||||
for (qi = _sequences.begin(); qi != _sequences.end(); ++qi) {
|
||||
SequenceData &smp = (*qi);
|
||||
AIL_release_sequence_handle(smp._sequence);
|
||||
}
|
||||
_sequences.clear();
|
||||
|
||||
if (_dls_file != 0) {
|
||||
AIL_DLS_unload(_dls_device, _dls_file);
|
||||
_dls_file = 0;
|
||||
}
|
||||
|
||||
if (_dls_device != 0) {
|
||||
AIL_DLS_close(_dls_device, 0);
|
||||
_dls_device = 0;
|
||||
}
|
||||
|
||||
if (_midi_driver != 0) {
|
||||
AIL_close_XMIDI_driver(_midi_driver);
|
||||
_midi_driver = 0;
|
||||
}
|
||||
|
||||
if (_digital_driver != 0) {
|
||||
AIL_close_digital_driver(_digital_driver);
|
||||
_digital_driver = 0;
|
||||
}
|
||||
|
||||
AIL_shutdown();
|
||||
|
||||
_is_open = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::open_callback
|
||||
// Access: Private, Static
|
||||
// Description: This callback function is given to Miles to handle
|
||||
// file I/O via the Panda VFS. It's only used to
|
||||
// implemented streaming audio files, since in all other
|
||||
// cases we open files directly.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
U32 AILCALLBACK GlobalMilesManager::
|
||||
open_callback(char const *filename, UINTa *file_handle) {
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
istream *strm = vfs->open_read_file(Filename::binary_filename(filename), true);
|
||||
if (strm == NULL) {
|
||||
// Failure.
|
||||
return 0;
|
||||
}
|
||||
// Success.
|
||||
(*file_handle) = (UINTa)strm;
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::close_callback
|
||||
// Access: Private, Static
|
||||
// Description: This callback function is given to Miles to handle
|
||||
// file I/O via the Panda VFS.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AILCALLBACK GlobalMilesManager::
|
||||
close_callback(UINTa file_handle) {
|
||||
istream *strm = (istream *)file_handle;
|
||||
VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
|
||||
vfs->close_read_file(strm);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::seek_callback
|
||||
// Access: Private, Static
|
||||
// Description: This callback function is given to Miles to handle
|
||||
// file I/O via the Panda VFS.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
S32 AILCALLBACK GlobalMilesManager::
|
||||
seek_callback(UINTa file_handle, S32 offset, U32 type) {
|
||||
istream *strm = (istream *)file_handle;
|
||||
strm->clear();
|
||||
switch (type) {
|
||||
case AIL_FILE_SEEK_BEGIN:
|
||||
strm->seekg(offset, ios::beg);
|
||||
break;
|
||||
|
||||
case AIL_FILE_SEEK_CURRENT:
|
||||
strm->seekg(offset, ios::cur);
|
||||
break;
|
||||
|
||||
case AIL_FILE_SEEK_END:
|
||||
strm->seekg(offset, ios::end);
|
||||
break;
|
||||
}
|
||||
|
||||
return strm->tellg();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobalMilesManager::read_callback
|
||||
// Access: Private, Static
|
||||
// Description: This callback function is given to Miles to handle
|
||||
// file I/O via the Panda VFS.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
U32 AILCALLBACK GlobalMilesManager::
|
||||
read_callback(UINTa file_handle, void *buffer, U32 bytes) {
|
||||
istream *strm = (istream *)file_handle;
|
||||
strm->read((char *)buffer, bytes);
|
||||
return strm->gcount();
|
||||
}
|
||||
|
||||
#endif //]
|
||||
|
114
panda/src/audiotraits/globalMilesManager.h
Normal file
114
panda/src/audiotraits/globalMilesManager.h
Normal file
@ -0,0 +1,114 @@
|
||||
// Filename: globalMilesManager.h
|
||||
// Created by: drose (26Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GLOBALMILESMANAGER_H
|
||||
#define GLOBALMILESMANAGER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "mss.h"
|
||||
#include "pset.h"
|
||||
#include "pmutex.h"
|
||||
|
||||
class MilesAudioSample;
|
||||
class MilesAudioSequence;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GlobalMilesManager
|
||||
// Description : This is a wrapper around the parts of the Miles API
|
||||
// that should only be created once. This represents
|
||||
// the global data common to all MilesAudioManagers.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_MILES_AUDIO GlobalMilesManager {
|
||||
private:
|
||||
GlobalMilesManager();
|
||||
|
||||
public:
|
||||
void add_manager(MilesAudioManager *manager);
|
||||
void remove_manager(MilesAudioManager *manager);
|
||||
void cleanup();
|
||||
INLINE bool is_open() const;
|
||||
|
||||
bool get_sample(HSAMPLE &sample, size_t &index, MilesAudioSample *sound);
|
||||
void release_sample(size_t index, MilesAudioSample *sound);
|
||||
|
||||
bool get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound);
|
||||
void release_sequence(size_t index, MilesAudioSequence *sound);
|
||||
|
||||
void force_midi_reset();
|
||||
|
||||
static GlobalMilesManager *get_global_ptr();
|
||||
|
||||
public:
|
||||
HDIGDRIVER _digital_driver;
|
||||
HMDIDRIVER _midi_driver;
|
||||
|
||||
// For software MIDI:
|
||||
HDLSDEVICE _dls_device;
|
||||
HDLSFILEID _dls_file;
|
||||
pvector<unsigned char> _dls_data;
|
||||
|
||||
private:
|
||||
void open_api();
|
||||
void close_api();
|
||||
|
||||
static U32 AILCALLBACK open_callback(char const *filename, UINTa *file_handle);
|
||||
static void AILCALLBACK close_callback(UINTa file_handle);
|
||||
static S32 AILCALLBACK seek_callback(UINTa file_handle, S32 offset, U32 type);
|
||||
static U32 AILCALLBACK read_callback(UINTa file_handle, void *buffer, U32 bytes);
|
||||
|
||||
|
||||
private:
|
||||
bool _is_open;
|
||||
|
||||
typedef pset<MilesAudioManager *> Managers;
|
||||
Managers _managers;
|
||||
Mutex _managers_lock;
|
||||
|
||||
class SampleData {
|
||||
public:
|
||||
HSAMPLE _sample;
|
||||
MilesAudioSample *_sound;
|
||||
};
|
||||
|
||||
typedef pvector<SampleData> Samples;
|
||||
Samples _samples;
|
||||
Mutex _samples_lock;
|
||||
|
||||
class SequenceData {
|
||||
public:
|
||||
HSEQUENCE _sequence;
|
||||
MilesAudioSequence *_sound;
|
||||
};
|
||||
|
||||
typedef pvector<SequenceData> Sequences;
|
||||
Sequences _sequences;
|
||||
Mutex _sequences_lock;
|
||||
|
||||
static GlobalMilesManager *_global_ptr;
|
||||
};
|
||||
|
||||
#include "globalMilesManager.I"
|
||||
|
||||
#endif //]
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,9 @@
|
||||
#include "pmap.h"
|
||||
#include "pdeque.h"
|
||||
#include "pvector.h"
|
||||
#include "thread.h"
|
||||
#include "pmutex.h"
|
||||
#include "conditionVar.h"
|
||||
|
||||
class MilesAudioSound;
|
||||
|
||||
@ -37,35 +40,69 @@ public:
|
||||
// See AudioManager.h for documentation.
|
||||
|
||||
MilesAudioManager();
|
||||
~MilesAudioManager();
|
||||
virtual ~MilesAudioManager();
|
||||
|
||||
virtual void shutdown();
|
||||
|
||||
bool is_valid();
|
||||
virtual bool is_valid();
|
||||
|
||||
virtual PT(AudioSound) get_sound(const string &file_name, bool positional = false);
|
||||
void uncache_sound(const string& file_name);
|
||||
void clear_cache();
|
||||
void set_cache_limit(unsigned int count);
|
||||
unsigned int get_cache_limit() const;
|
||||
virtual void uncache_sound(const string &file_name);
|
||||
virtual void clear_cache();
|
||||
virtual void set_cache_limit(unsigned int count);
|
||||
virtual unsigned int get_cache_limit() const;
|
||||
|
||||
void set_volume(float volume);
|
||||
float get_volume() const;
|
||||
virtual void set_volume(float volume);
|
||||
virtual float get_volume() const;
|
||||
|
||||
void set_play_rate(float play_rate);
|
||||
float get_play_rate() const;
|
||||
|
||||
void set_active(bool active);
|
||||
bool get_active() const;
|
||||
virtual void set_active(bool active);
|
||||
virtual bool get_active() const;
|
||||
|
||||
void set_concurrent_sound_limit(unsigned int limit = 0);
|
||||
unsigned int get_concurrent_sound_limit() const;
|
||||
virtual void set_concurrent_sound_limit(unsigned int limit = 0);
|
||||
virtual unsigned int get_concurrent_sound_limit() const;
|
||||
|
||||
void reduce_sounds_playing_to(unsigned int count);
|
||||
virtual void reduce_sounds_playing_to(unsigned int count);
|
||||
|
||||
void stop_all_sounds();
|
||||
virtual void stop_all_sounds();
|
||||
|
||||
virtual void update();
|
||||
|
||||
// Tell the manager that the sound dtor was called.
|
||||
void release_sound(MilesAudioSound *audioSound);
|
||||
void cleanup();
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out) const;
|
||||
|
||||
private:
|
||||
void start_service_stream(HSTREAM stream);
|
||||
void stop_service_stream(HSTREAM stream);
|
||||
|
||||
void most_recently_used(const string &path);
|
||||
void uncache_a_sound();
|
||||
|
||||
void starting_sound(MilesAudioSound *audio);
|
||||
void stopping_sound(MilesAudioSound *audio);
|
||||
|
||||
class SoundData;
|
||||
PT(SoundData) load(const Filename &file_name);
|
||||
|
||||
void thread_main(volatile bool &keep_running);
|
||||
void do_service_streams();
|
||||
|
||||
private:
|
||||
class StreamThread : public Thread {
|
||||
public:
|
||||
StreamThread(MilesAudioManager *mgr);
|
||||
virtual void thread_main();
|
||||
|
||||
MilesAudioManager *_mgr;
|
||||
volatile bool _keep_running;
|
||||
};
|
||||
|
||||
// The sound cache:
|
||||
class SoundData : public ReferenceCount {
|
||||
public:
|
||||
@ -73,8 +110,7 @@ private:
|
||||
~SoundData();
|
||||
float get_length();
|
||||
|
||||
string _basename;
|
||||
HAUDIO _audio;
|
||||
Filename _basename;
|
||||
S32 _file_type;
|
||||
pvector<unsigned char> _raw_data;
|
||||
bool _has_length;
|
||||
@ -100,38 +136,16 @@ private:
|
||||
bool _active;
|
||||
int _cache_limit;
|
||||
bool _cleanup_required;
|
||||
// keep a count for startup and shutdown:
|
||||
static int _active_managers;
|
||||
static bool _miles_active;
|
||||
unsigned int _concurrent_sound_limit;
|
||||
|
||||
bool _is_valid;
|
||||
bool _hasMidiSounds;
|
||||
|
||||
// Optional Downloadable Sound field for software midi
|
||||
static HDLSFILEID _dls_field;
|
||||
|
||||
typedef pset<MilesAudioManager *> Managers;
|
||||
static Managers *_managers;
|
||||
|
||||
PT(SoundData) load(Filename file_name);
|
||||
// Tell the manager that the sound dtor was called.
|
||||
void release_sound(MilesAudioSound* audioSound);
|
||||
|
||||
void most_recently_used(const string& path);
|
||||
void uncache_a_sound();
|
||||
|
||||
void starting_sound(MilesAudioSound* audio);
|
||||
void stopping_sound(MilesAudioSound* audio);
|
||||
|
||||
// get the default dls file path:
|
||||
void get_gm_file_path(string& result);
|
||||
|
||||
void force_midi_reset();
|
||||
void cleanup();
|
||||
|
||||
friend class MilesAudioSound;
|
||||
|
||||
typedef pvector<HSTREAM> Streams;
|
||||
PT(StreamThread) _stream_thread;
|
||||
Streams _streams;
|
||||
Mutex _streams_lock;
|
||||
ConditionVar _streams_cvar;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
@ -149,6 +163,11 @@ public:
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class MilesAudioSound;
|
||||
friend class MilesAudioSample;
|
||||
friend class MilesAudioSequence;
|
||||
friend class MilesAudioStream;
|
||||
};
|
||||
|
||||
EXPCL_MILES_AUDIO PT(AudioManager) Create_AudioManager();
|
||||
|
24
panda/src/audiotraits/milesAudioSample.I
Normal file
24
panda/src/audiotraits/milesAudioSample.I
Normal file
@ -0,0 +1,24 @@
|
||||
// Filename: milesAudioSample.I
|
||||
// Created by: skyler (June 6, 2001)
|
||||
// Prior system by: cary
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
309
panda/src/audiotraits/milesAudioSample.cxx
Normal file
309
panda/src/audiotraits/milesAudioSample.cxx
Normal file
@ -0,0 +1,309 @@
|
||||
// Filename: milesAudioSample.cxx
|
||||
// Created by: skyler (June 6, 2001)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "milesAudioSample.h"
|
||||
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "milesAudioManager.h"
|
||||
|
||||
|
||||
TypeHandle MilesAudioSample::_type_handle;
|
||||
|
||||
#undef miles_audio_debug
|
||||
|
||||
#ifndef NDEBUG //[
|
||||
#define miles_audio_debug(x) \
|
||||
audio_debug("MilesAudioSample \""<<get_name()<<"\" "<< x )
|
||||
#else //][
|
||||
#define miles_audio_debug(x) ((void)0)
|
||||
#endif //]
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::Constructor
|
||||
// Access: Private
|
||||
// Description: This constructor is called only by the
|
||||
// MilesAudioManager.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioSample::
|
||||
MilesAudioSample(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
|
||||
const string &file_name) :
|
||||
MilesAudioSound(manager, file_name),
|
||||
_sd(sd)
|
||||
{
|
||||
nassertv(sd != NULL);
|
||||
audio_debug("MilesAudioSample(manager=0x"<<(void*)&manager
|
||||
<<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
|
||||
|
||||
_sample = 0;
|
||||
_sample_index = 0;
|
||||
_original_playback_rate = 1.0f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioSample::
|
||||
~MilesAudioSample() {
|
||||
miles_audio_debug("~MilesAudioSample()");
|
||||
cleanup();
|
||||
_manager->release_sound(this);
|
||||
miles_audio_debug("~MilesAudioSample() done");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::play
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
play() {
|
||||
miles_audio_debug("play()");
|
||||
if (_active) {
|
||||
if (_sd->_raw_data.empty()) {
|
||||
milesAudio_cat.warning()
|
||||
<< "Could not play " << _file_name << ": no data\n";
|
||||
} else {
|
||||
stop();
|
||||
_manager->starting_sound(this);
|
||||
|
||||
nassertv(_sample == 0);
|
||||
|
||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||
if (!mgr->get_sample(_sample, _sample_index, this)){
|
||||
milesAudio_cat.warning()
|
||||
<< "Could not play " << _file_name << ": too many open samples\n";
|
||||
_sample = 0;
|
||||
} else {
|
||||
AIL_set_named_sample_file(_sample, _sd->_basename.c_str(),
|
||||
&_sd->_raw_data[0], _sd->_raw_data.size(),
|
||||
0);
|
||||
_original_playback_rate = AIL_sample_playback_rate(_sample);
|
||||
|
||||
set_volume(_volume);
|
||||
set_play_rate(_play_rate);
|
||||
AIL_set_sample_loop_count(_sample, _loop_count);
|
||||
AIL_start_sample(_sample);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In case _loop_count gets set to forever (zero):
|
||||
audio_debug(" paused "<<_file_name );
|
||||
_paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::stop
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
stop() {
|
||||
miles_audio_debug("stop()");
|
||||
_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
|
||||
// that it was looping when it was set inactive. There is no need to
|
||||
// make this symmetrical with play(). set_active() is the 'owner' of
|
||||
// _paused. play() accesses _paused to help in the situation where
|
||||
// someone calls play on an inactive sound().
|
||||
|
||||
if (_sample != 0) {
|
||||
AIL_end_sample(_sample);
|
||||
|
||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||
mgr->release_sample(_sample_index, this);
|
||||
|
||||
_sample = 0;
|
||||
_sample_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::set_time
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
set_time(float time) {
|
||||
miles_audio_debug("set_time(time="<<time<<")");
|
||||
|
||||
if (_sample != 0) {
|
||||
// Ensure we don't inadvertently run off the end of the sound.
|
||||
float max_time = length();
|
||||
if (time > max_time) {
|
||||
milesAudio_cat.warning()
|
||||
<< "set_time(" << time << ") requested for sound of length "
|
||||
<< max_time << "\n";
|
||||
time = max_time;
|
||||
}
|
||||
|
||||
S32 time_ms = (S32)(1000.0f * time);
|
||||
AIL_set_sample_ms_position(_sample, time_ms);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::get_time
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSample::
|
||||
get_time() const {
|
||||
if (_sample == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
S32 current_ms;
|
||||
AIL_sample_ms_position(_sample, NULL, ¤t_ms);
|
||||
float time = float(current_ms * 0.001f);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::set_volume
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
set_volume(float volume) {
|
||||
miles_audio_debug("set_volume(volume="<<volume<<")");
|
||||
|
||||
// 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;
|
||||
|
||||
if (_sample != 0) {
|
||||
volume *= _manager->get_volume();
|
||||
|
||||
// Change to Miles volume, range 0 to 1.0:
|
||||
F32 milesVolume = volume;
|
||||
milesVolume = min(milesVolume, 1.0f);
|
||||
milesVolume = max(milesVolume, 0.0f);
|
||||
|
||||
// Convert balance of -1.0..1.0 to 0-1.0:
|
||||
F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f);
|
||||
|
||||
AIL_set_sample_volume_pan(_sample, milesVolume, milesBalance);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::set_balance
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
set_balance(float balance_right) {
|
||||
miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
|
||||
_balance = balance_right;
|
||||
|
||||
// Call set_volume to effect the change:
|
||||
set_volume(_volume);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::set_play_rate
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
set_play_rate(float play_rate) {
|
||||
miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")");
|
||||
|
||||
// Set the play_rate:
|
||||
_play_rate = play_rate;
|
||||
|
||||
if (_sample != 0) {
|
||||
play_rate *= _manager->get_play_rate();
|
||||
|
||||
// wave and mp3 use sample rate (e.g. 44100)
|
||||
S32 speed = (S32)(play_rate * (float)_original_playback_rate);
|
||||
AIL_set_sample_playback_rate(_sample, speed);
|
||||
audio_debug(" play_rate for this wav or mp3 is now " << speed);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::length
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSample::
|
||||
length() const {
|
||||
return _sd->get_length();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::status
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioSound::SoundStatus MilesAudioSample::
|
||||
status() const {
|
||||
if (_sample == 0) {
|
||||
return AudioSound::READY;
|
||||
}
|
||||
switch (AIL_sample_status(_sample)) {
|
||||
case SMP_DONE:
|
||||
case SMP_STOPPED:
|
||||
case SMP_FREE:
|
||||
return AudioSound::READY;
|
||||
|
||||
case SMP_PLAYING:
|
||||
case SMP_PLAYINGBUTRELEASED:
|
||||
return AudioSound::PLAYING;
|
||||
|
||||
default:
|
||||
return AudioSound::BAD;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::cleanup
|
||||
// Access: Public, Virtual
|
||||
// Description: Stops the sound from playing and releases any
|
||||
// associated resources, in preparation for releasing
|
||||
// the sound or shutting down the sound system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
cleanup() {
|
||||
stop();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSample::internal_stop
|
||||
// Access: Private
|
||||
// Description: Called by the GlobalMilesManager when it is detected
|
||||
// that this particular sound has already stopped, and
|
||||
// its sample handle will be recycled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSample::
|
||||
internal_stop() {
|
||||
_sample = 0;
|
||||
_sample_index = 0;
|
||||
}
|
||||
|
||||
#endif //]
|
93
panda/src/audiotraits/milesAudioSample.h
Normal file
93
panda/src/audiotraits/milesAudioSample.h
Normal file
@ -0,0 +1,93 @@
|
||||
// Filename: milesAudioSample.h
|
||||
// Created by: skyler (June 6, 2001)
|
||||
// Prior system by: cary
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MILESAUDIOSAMPLE_H
|
||||
#define MILESAUDIOSAMPLE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "milesAudioSound.h"
|
||||
#include "milesAudioManager.h"
|
||||
#include "mss.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MilesAudioSample
|
||||
// Description : A sound file, such as a WAV or MP3 file, that is
|
||||
// preloaded into memory and played from memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_MILES_AUDIO MilesAudioSample : public MilesAudioSound {
|
||||
private:
|
||||
MilesAudioSample(MilesAudioManager *manager,
|
||||
MilesAudioManager::SoundData *sd,
|
||||
const string &file_name);
|
||||
|
||||
public:
|
||||
virtual ~MilesAudioSample();
|
||||
|
||||
virtual void play();
|
||||
virtual void stop();
|
||||
|
||||
virtual void set_time(float time=0.0f);
|
||||
virtual float get_time() const;
|
||||
|
||||
virtual void set_volume(float volume=1.0f);
|
||||
virtual void set_balance(float balance_right=0.0f);
|
||||
virtual void set_play_rate(float play_rate=1.0f);
|
||||
|
||||
virtual float length() const;
|
||||
|
||||
virtual AudioSound::SoundStatus status() const;
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
private:
|
||||
void internal_stop();
|
||||
|
||||
PT(MilesAudioManager::SoundData) _sd;
|
||||
HSAMPLE _sample;
|
||||
size_t _sample_index;
|
||||
S32 _original_playback_rate;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
MilesAudioSound::init_type();
|
||||
register_type(_type_handle, "MilesAudioSample",
|
||||
MilesAudioSound::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;
|
||||
|
||||
friend class GlobalMilesManager;
|
||||
friend class MilesAudioManager;
|
||||
};
|
||||
|
||||
#include "milesAudioSample.I"
|
||||
|
||||
#endif //]
|
||||
|
||||
#endif /* MILESAUDIOSAMPLE_H */
|
18
panda/src/audiotraits/milesAudioSequence.I
Normal file
18
panda/src/audiotraits/milesAudioSequence.I
Normal file
@ -0,0 +1,18 @@
|
||||
// Filename: milesAudioSequence.I
|
||||
// Created by: drose (31Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
299
panda/src/audiotraits/milesAudioSequence.cxx
Normal file
299
panda/src/audiotraits/milesAudioSequence.cxx
Normal file
@ -0,0 +1,299 @@
|
||||
// Filename: milesAudioSequence.cxx
|
||||
// Created by: drose (31Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "milesAudioSequence.h"
|
||||
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "milesAudioManager.h"
|
||||
|
||||
|
||||
TypeHandle MilesAudioSequence::_type_handle;
|
||||
|
||||
#undef miles_audio_debug
|
||||
|
||||
#ifndef NDEBUG //[
|
||||
#define miles_audio_debug(x) \
|
||||
audio_debug("MilesAudioSequence \""<<get_name()<<"\" "<< x )
|
||||
#else //][
|
||||
#define miles_audio_debug(x) ((void)0)
|
||||
#endif //]
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::Constructor
|
||||
// Access: Private
|
||||
// Description: This constructor is called only by the
|
||||
// MilesAudioManager.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioSequence::
|
||||
MilesAudioSequence(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
|
||||
const string &file_name) :
|
||||
MilesAudioSound(manager, file_name),
|
||||
_sd(sd)
|
||||
{
|
||||
nassertv(sd != NULL);
|
||||
audio_debug("MilesAudioSequence(manager=0x"<<(void*)&manager
|
||||
<<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
|
||||
|
||||
_sequence = 0;
|
||||
_sequence_index = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioSequence::
|
||||
~MilesAudioSequence() {
|
||||
miles_audio_debug("~MilesAudioSequence()");
|
||||
cleanup();
|
||||
_manager->release_sound(this);
|
||||
miles_audio_debug("~MilesAudioSequence() done");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::play
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
play() {
|
||||
miles_audio_debug("play()");
|
||||
if (_active) {
|
||||
stop();
|
||||
|
||||
if (_sd->_raw_data.empty()) {
|
||||
milesAudio_cat.warning()
|
||||
<< "Could not play " << _file_name << ": no data\n";
|
||||
} else {
|
||||
_manager->starting_sound(this);
|
||||
nassertv(_sequence == 0);
|
||||
|
||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||
if (!mgr->get_sequence(_sequence, _sequence_index, this)){
|
||||
milesAudio_cat.warning()
|
||||
<< "Could not play " << _file_name << ": too many open sequences\n";
|
||||
_sequence = 0;
|
||||
} else {
|
||||
AIL_init_sequence(_sequence, &_sd->_raw_data[0], 0);
|
||||
|
||||
set_volume(_volume);
|
||||
set_play_rate(_play_rate);
|
||||
AIL_set_sequence_loop_count(_sequence, _loop_count);
|
||||
AIL_start_sequence(_sequence);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// In case _loop_count gets set to forever (zero):
|
||||
audio_debug(" paused "<<_file_name );
|
||||
_paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::stop
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
stop() {
|
||||
miles_audio_debug("stop()");
|
||||
_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
|
||||
// that it was looping when it was set inactive. There is no need to
|
||||
// make this symmetrical with play(). set_active() is the 'owner' of
|
||||
// _paused. play() accesses _paused to help in the situation where
|
||||
// someone calls play on an inactive sound().
|
||||
|
||||
if (_sequence != 0) {
|
||||
AIL_end_sequence(_sequence);
|
||||
|
||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||
mgr->release_sequence(_sequence_index, this);
|
||||
|
||||
_sequence = 0;
|
||||
_sequence_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::set_time
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
set_time(float time) {
|
||||
miles_audio_debug("set_time(time="<<time<<")");
|
||||
|
||||
if (_sequence != 0) {
|
||||
S32 time_ms = (S32)(1000.0f * time);
|
||||
|
||||
// Ensure we don't inadvertently run off the end of the sound.
|
||||
S32 length_ms;
|
||||
AIL_sequence_ms_position(_sequence, &length_ms, NULL);
|
||||
time_ms = min(time_ms, length_ms);
|
||||
|
||||
AIL_set_sequence_ms_position(_sequence, time_ms);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::get_time
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSequence::
|
||||
get_time() const {
|
||||
if (_sequence == 0) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
S32 current_ms;
|
||||
AIL_sequence_ms_position(_sequence, NULL, ¤t_ms);
|
||||
float time = float(current_ms * 0.001f);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::set_volume
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
set_volume(float volume) {
|
||||
miles_audio_debug("set_volume(volume="<<volume<<")");
|
||||
|
||||
// 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;
|
||||
|
||||
if (_sequence != 0) {
|
||||
volume *= _manager->get_volume();
|
||||
|
||||
// Change to Miles volume, range 0 to 127:
|
||||
S32 milesVolume = (S32)(volume * 127.0f);
|
||||
milesVolume = min(milesVolume, 127);
|
||||
milesVolume = max(milesVolume, 0);
|
||||
|
||||
AIL_set_sequence_volume(_sequence, milesVolume, 0);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::set_balance
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
set_balance(float balance_right) {
|
||||
miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
|
||||
_balance = balance_right;
|
||||
|
||||
// Balance has no effect on a MIDI file.
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::set_play_rate
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
set_play_rate(float play_rate) {
|
||||
miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")");
|
||||
|
||||
// Set the play_rate:
|
||||
_play_rate = play_rate;
|
||||
|
||||
if (_sequence != 0) {
|
||||
play_rate *= _manager->get_play_rate();
|
||||
|
||||
S32 percent = (S32)(play_rate * 100.0f);
|
||||
AIL_set_sequence_tempo(_sequence, percent, 0);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::length
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSequence::
|
||||
length() const {
|
||||
S32 length_ms;
|
||||
AIL_sequence_ms_position(_sequence, &length_ms, NULL);
|
||||
float time = (float)length_ms * 0.001f;
|
||||
return time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::status
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioSound::SoundStatus MilesAudioSequence::
|
||||
status() const {
|
||||
if (_sequence == 0) {
|
||||
return AudioSound::READY;
|
||||
}
|
||||
switch (AIL_sequence_status(_sequence)) {
|
||||
case SEQ_DONE:
|
||||
case SEQ_STOPPED:
|
||||
case SEQ_FREE:
|
||||
return AudioSound::READY;
|
||||
|
||||
case SEQ_PLAYING:
|
||||
case SEQ_PLAYINGBUTRELEASED:
|
||||
return AudioSound::PLAYING;
|
||||
|
||||
default:
|
||||
return AudioSound::BAD;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::cleanup
|
||||
// Access: Public, Virtual
|
||||
// Description: Stops the sound from playing and releases any
|
||||
// associated resources, in preparation for releasing
|
||||
// the sound or shutting down the sound system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
cleanup() {
|
||||
stop();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSequence::internal_stop
|
||||
// Access: Private
|
||||
// Description: Called by the GlobalMilesManager when it is detected
|
||||
// that this particular sound has already stopped, and
|
||||
// its sequence handle will be recycled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSequence::
|
||||
internal_stop() {
|
||||
_sequence = 0;
|
||||
_sequence_index = 0;
|
||||
}
|
||||
|
||||
#endif //]
|
91
panda/src/audiotraits/milesAudioSequence.h
Normal file
91
panda/src/audiotraits/milesAudioSequence.h
Normal file
@ -0,0 +1,91 @@
|
||||
// Filename: milesAudioSequence.h
|
||||
// Created by: drose (31Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MILESAUDIOSEQUENCE_H
|
||||
#define MILESAUDIOSEQUENCE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "milesAudioSound.h"
|
||||
#include "milesAudioManager.h"
|
||||
#include "mss.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MilesAudioSequence
|
||||
// Description : A MIDI file, preloaded and played from a memory
|
||||
// buffer. MIDI files cannot be streamed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_MILES_AUDIO MilesAudioSequence : public MilesAudioSound {
|
||||
private:
|
||||
MilesAudioSequence(MilesAudioManager *manager,
|
||||
MilesAudioManager::SoundData *sd,
|
||||
const string &file_name);
|
||||
|
||||
public:
|
||||
virtual ~MilesAudioSequence();
|
||||
|
||||
virtual void play();
|
||||
virtual void stop();
|
||||
|
||||
virtual void set_time(float time=0.0f);
|
||||
virtual float get_time() const;
|
||||
|
||||
virtual void set_volume(float volume=1.0f);
|
||||
virtual void set_balance(float balance_right=0.0f);
|
||||
virtual void set_play_rate(float play_rate=1.0f);
|
||||
|
||||
virtual float length() const;
|
||||
|
||||
virtual AudioSound::SoundStatus status() const;
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
private:
|
||||
void internal_stop();
|
||||
|
||||
PT(MilesAudioManager::SoundData) _sd;
|
||||
HSEQUENCE _sequence;
|
||||
size_t _sequence_index;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
MilesAudioSound::init_type();
|
||||
register_type(_type_handle, "MilesAudioSequence",
|
||||
MilesAudioSound::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;
|
||||
|
||||
friend class GlobalMilesManager;
|
||||
friend class MilesAudioManager;
|
||||
};
|
||||
|
||||
#include "milesAudioSequence.I"
|
||||
|
||||
#endif //]
|
||||
|
||||
#endif /* MILESAUDIOSEQUENCE_H */
|
@ -1,6 +1,5 @@
|
||||
// Filename: milesAudioSound.I
|
||||
// Created by: skyler (June 6, 2001)
|
||||
// Prior system by: cary
|
||||
// Created by: drose (30Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -17,8 +16,3 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Filename: milesAudioSound.cxx
|
||||
// Created by: skyler (June 6, 2001)
|
||||
// Created by: drose (30Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -16,308 +16,67 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "milesAudioSound.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "throw_event.h"
|
||||
#include "milesAudioSound.h"
|
||||
#include "milesAudioManager.h"
|
||||
|
||||
|
||||
TypeHandle MilesAudioSound::_type_handle;
|
||||
|
||||
|
||||
#define NEED_MILES_LENGTH_WORKAROUND
|
||||
|
||||
#if (((MSS_MAJOR_VERSION == 6) && (MSS_MINOR_VERSION >= 5)) || (MSS_MAJOR_VERSION >= 7))
|
||||
#define MILES_6_5_OR_HIGHER
|
||||
#endif
|
||||
#undef miles_audio_debug
|
||||
|
||||
#ifndef NDEBUG //[
|
||||
namespace {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: get_status_char
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
char
|
||||
get_status_char(HAUDIO audio) {
|
||||
if (!audio) {
|
||||
return '0'; // NULL.
|
||||
}
|
||||
switch (AIL_quick_status(audio)) {
|
||||
case QSTAT_LOADED:
|
||||
case QSTAT_DONE:
|
||||
return 'r'; // Ready.
|
||||
case QSTAT_PLAYING:
|
||||
return 'p'; // Playing.
|
||||
default:
|
||||
return 'x'; // bad.
|
||||
}
|
||||
}
|
||||
#define miles_audio_debug(x) \
|
||||
audio_debug("MilesAudioSound "<<get_status_char(_audio)<<" \""<<get_name() \
|
||||
<<"\" "<< x )
|
||||
}
|
||||
audio_debug("MilesAudioSound \""<<get_name()<<"\" "<< x )
|
||||
#else //][
|
||||
#define miles_audio_debug(x) ((void)0)
|
||||
#endif //]
|
||||
|
||||
namespace {
|
||||
AILSEQUENCECB sequence_callback = 0;
|
||||
AILSAMPLECB sample_callback = 0;
|
||||
const int user_data_index = 7;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: pandaAudioAilCallback_Sequence
|
||||
// Access: file scope
|
||||
// Description: This function is part of a hack for finish callbacks
|
||||
// when using the Miles quick API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AILCALLBACK
|
||||
pandaAudioAilCallback_Sequence(HSEQUENCE S) {
|
||||
assert(S);
|
||||
AutoAilLock milesLock;
|
||||
audio_debug("pandaAudioAilCallback_Sequence(HSEQUENCE="<<((void*)S)<<")");
|
||||
MilesAudioSound* sound = (MilesAudioSound*)AIL_sequence_user_data(
|
||||
S, user_data_index);
|
||||
assert(sound);
|
||||
sound->finished();
|
||||
if (sequence_callback) {
|
||||
sequence_callback(S);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: pandaAudioAilCallback_Sample
|
||||
// Access: file scope
|
||||
// Description: This function is part of a hack for finish callbacks
|
||||
// when using the Miles quick API.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void AILCALLBACK
|
||||
pandaAudioAilCallback_Sample(HSAMPLE S) {
|
||||
assert(S);
|
||||
AutoAilLock milesLock;
|
||||
audio_debug("pandaAudioAilCallback_Sample(HSAMPLE="<<((void*)S)<<")");
|
||||
MilesAudioSound* sound = (MilesAudioSound*)AIL_sample_user_data(
|
||||
S, user_data_index);
|
||||
assert(sound);
|
||||
sound->finished();
|
||||
if (sample_callback) {
|
||||
sample_callback(S);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: panda_AIL_quick_set_finished_callback
|
||||
// Access: file scope
|
||||
// Description: This function is part of a hack for finish callbacks
|
||||
// when using the Miles quick API.
|
||||
//
|
||||
// This will determine whether the sound is a MIDI or
|
||||
// a wave sample and setup the correct callback.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
panda_AIL_quick_set_finished_callback(HAUDIO audio, MilesAudioSound* sound) {
|
||||
audio_debug("panda_AIL_quick_set_finished_callback(audio="<<((void*)audio)
|
||||
<<", sound="<<((void*)sound)<<")");
|
||||
if (!audio || !sound) {
|
||||
return;
|
||||
}
|
||||
AutoAilLock milesLock;
|
||||
if (audio->handle != NULL) {
|
||||
switch (audio->type) {
|
||||
case AIL_QUICK_XMIDI_TYPE:
|
||||
audio_debug(" AIL_register_sequence_callback");
|
||||
AIL_set_sequence_user_data(
|
||||
(HSEQUENCE)audio->handle, user_data_index, (long)sound);
|
||||
sequence_callback=AIL_register_sequence_callback(
|
||||
(HSEQUENCE)audio->handle, pandaAudioAilCallback_Sequence);
|
||||
audio_debug( "AILCALLBACK "<<((void*)sequence_callback));
|
||||
break;
|
||||
case AIL_QUICK_DIGITAL_TYPE:
|
||||
case AIL_QUICK_MPEG_DIGITAL_TYPE:
|
||||
audio_debug(" AIL_register_EOS_callback");
|
||||
AIL_set_sample_user_data(
|
||||
(HSAMPLE)audio->handle, user_data_index, (long)sound);
|
||||
sample_callback=AIL_register_EOS_callback(
|
||||
(HSAMPLE)audio->handle, pandaAudioAilCallback_Sample);
|
||||
audio_debug(" AILCALLBACK "<<((void*)sample_callback));
|
||||
break;
|
||||
default:
|
||||
audio_debug(" unknown audio type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
S32
|
||||
Get_playback_rate(HAUDIO audio) {
|
||||
if (audio) {
|
||||
switch (audio->type) {
|
||||
case AIL_QUICK_XMIDI_TYPE:
|
||||
case AIL_QUICK_DLS_XMIDI_TYPE:
|
||||
return AIL_sequence_tempo((HSEQUENCE)audio->handle);
|
||||
break;
|
||||
case AIL_QUICK_DIGITAL_TYPE:
|
||||
case AIL_QUICK_MPEG_DIGITAL_TYPE:
|
||||
if (AIL_quick_status(audio) == QSTAT_PLAYING) {
|
||||
return AIL_sample_playback_rate((HSAMPLE)audio->handle);
|
||||
} else {
|
||||
//HACK: The play rate is returning 0 unless it's playing
|
||||
if (AIL_quick_play(audio, 1)) {
|
||||
S32 rate = AIL_sample_playback_rate((HSAMPLE)audio->handle);
|
||||
AIL_quick_halt(audio);
|
||||
return rate;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
audio_debug("Get_playback_rate unknown audio type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::MilesAudioSound
|
||||
// Access:
|
||||
// Function: MilesAudioSound::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioSound::
|
||||
MilesAudioSound(MilesAudioManager *manager,
|
||||
MilesAudioManager::SoundData *sd, string file_name, float length)
|
||||
: _sd(sd), _manager(manager), _file_name(file_name),
|
||||
_volume(1.0f), _balance(0),
|
||||
_loop_count(1), _length(length),
|
||||
_active(true), _paused(false) {
|
||||
nassertv(sd != NULL);
|
||||
const string &file_name) :
|
||||
_manager(manager),
|
||||
_file_name(file_name),
|
||||
_volume(1.0f), _balance(0), _play_rate(1.0f),
|
||||
_loop_count(1),
|
||||
_active(true), _paused(false)
|
||||
{
|
||||
nassertv(!file_name.empty());
|
||||
audio_debug("MilesAudioSound(manager=0x"<<(void*)&manager
|
||||
<<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
|
||||
// Make our own copy of the sound header data:
|
||||
_audio=AIL_quick_copy(sd->_audio);
|
||||
_play_rate = 1.0f;
|
||||
_original_playback_rate = Get_playback_rate(_audio);
|
||||
audio_debug("MilesAudioSound: original_playback_rate " << _original_playback_rate);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::~MilesAudioSound
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioSound::
|
||||
~MilesAudioSound() {
|
||||
miles_audio_debug("~MilesAudioSound()");
|
||||
cleanup();
|
||||
_manager->release_sound(this);
|
||||
miles_audio_debug("~MilesAudioSound() done");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::play
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
play() {
|
||||
#if 0
|
||||
if(_file_name.find(".mid")!=string::npos) {
|
||||
miles_audio_debug("play() midi");
|
||||
}
|
||||
#endif
|
||||
|
||||
miles_audio_debug("play()");
|
||||
if (_active) {
|
||||
if (status() == AudioSound::PLAYING) {
|
||||
stop();
|
||||
}
|
||||
nassertv(_audio);
|
||||
_manager->starting_sound(this);
|
||||
// Start playing:
|
||||
if (AIL_quick_play(_audio, _loop_count)) {
|
||||
//#*#panda_AIL_quick_set_finished_callback(_audio, this);
|
||||
// assert(status()==PLAYING);
|
||||
audio_debug(" started sound " << _file_name );
|
||||
} else {
|
||||
audio_debug(" sound " << _file_name<<" failed to start, err: " <<AIL_last_error());
|
||||
}
|
||||
} else {
|
||||
// In case _loop_count gets set to forever (zero):
|
||||
audio_debug(" paused "<<_file_name );
|
||||
_paused=true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::stop
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
stop() {
|
||||
miles_audio_debug("stop()");
|
||||
_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
|
||||
// that it was looping when it was set inactive. There is no need to
|
||||
// make this symmetrical with play(). set_active() is the 'owner' of
|
||||
// _paused. play() accesses _paused to help in the situation where
|
||||
// someone calls play on an inactive sound().
|
||||
nassertv(_audio);
|
||||
AIL_quick_halt(_audio);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::finished
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
finished() {
|
||||
miles_audio_debug("finished()");
|
||||
_manager->stopping_sound(this);
|
||||
if (!_finished_event.empty()) {
|
||||
throw_event(_finished_event);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::set_loop
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_loop(bool loop) {
|
||||
miles_audio_debug("set_loop(loop="<<loop<<")");
|
||||
// loop count of 0 means always loop
|
||||
set_loop_count((loop)?0:1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_loop
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MilesAudioSound::
|
||||
get_loop() const {
|
||||
miles_audio_debug("get_loop() returning "<<(_loop_count==0));
|
||||
return (_loop_count == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_loop_count(unsigned long loop_count) {
|
||||
miles_audio_debug("set_loop_count(loop_count="<<loop_count<<")");
|
||||
if (_loop_count != loop_count) {
|
||||
_loop_count = loop_count;
|
||||
if (status() == PLAYING) {
|
||||
@ -328,7 +87,6 @@ set_loop_count(unsigned long loop_count) {
|
||||
// need to stop and start the sound, feel free. Or, maybe I'll spend
|
||||
// time on it in the future. Please set the loop option before starting
|
||||
// the sound.
|
||||
stop();
|
||||
play();
|
||||
}
|
||||
}
|
||||
@ -336,200 +94,47 @@ set_loop_count(unsigned long loop_count) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
unsigned long MilesAudioSound::
|
||||
get_loop_count() const {
|
||||
miles_audio_debug("get_loop_count() returning "<<_loop_count);
|
||||
return _loop_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_time(float time) {
|
||||
miles_audio_debug("set_time(time="<<time<<")");
|
||||
|
||||
nassertv(_audio);
|
||||
// Ensure we don't inadvertently run off the end of the sound.
|
||||
float max_time = length();
|
||||
if (time > max_time) {
|
||||
milesAudio_cat.warning()
|
||||
<< "set_time(" << time << ") requested for sound of length "
|
||||
<< max_time << "\n";
|
||||
time = max_time;
|
||||
}
|
||||
|
||||
S32 millisecond_time=(S32)(1000*time);
|
||||
AIL_quick_set_ms_position(_audio, millisecond_time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSound::
|
||||
get_time() const {
|
||||
nassertr(_audio, 0.0f);
|
||||
S32 millisecond_time=AIL_quick_ms_position(_audio);
|
||||
float time=float(millisecond_time*.001);
|
||||
miles_audio_debug("get_time() returning "<<time);
|
||||
return time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_volume(float volume) {
|
||||
miles_audio_debug("set_volume(volume="<<volume<<")");
|
||||
nassertv(_audio);
|
||||
// *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();
|
||||
#ifdef MILES_6_5_OR_HIGHER
|
||||
// Change to Miles volume, range 0 to 1.0:
|
||||
F32 milesVolume=volume;
|
||||
milesVolume=min(milesVolume,1.0f);
|
||||
milesVolume=max(milesVolume,0.0f);
|
||||
#else
|
||||
// Change to Miles volume, range 0 to 127:
|
||||
S32 milesVolume=((S32)(127*volume))%128;
|
||||
#endif
|
||||
// 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.
|
||||
|
||||
// 0 delay, set to this volume immediately
|
||||
#ifdef MILES_6_5_OR_HIGHER
|
||||
F32 midiVolDelay =0.0f;
|
||||
#else
|
||||
S32 midiVolDelay =0;
|
||||
#endif
|
||||
|
||||
AIL_quick_set_volume(_audio, milesVolume, midiVolDelay);
|
||||
audio_debug(" volume for this midi is now "<<milesVolume);
|
||||
} else {
|
||||
// ...it's a wav or mp3.
|
||||
#ifdef MILES_6_5_OR_HIGHER
|
||||
// Convert balance of -1.0..1.0 to 0-1.0:
|
||||
F32 milesBalance=(F32)((_balance+1.0f)*0.5f);
|
||||
#else
|
||||
// Convert balance of -1.0..1.0 to 0..127:
|
||||
S32 milesBalance=((S32)(63.5f*(_balance+1.0f)))%128;
|
||||
#endif
|
||||
AIL_quick_set_volume(_audio, milesVolume, milesBalance);
|
||||
audio_debug(" volume for this wav or mp3 is now " << milesVolume
|
||||
<<", balance="<<milesBalance);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_volume
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSound::
|
||||
get_volume() const {
|
||||
miles_audio_debug("get_volume() returning "<<_volume);
|
||||
return _volume;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_play_rate(float play_rate) {
|
||||
miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")");
|
||||
// Set the play_rate:
|
||||
_play_rate=play_rate;
|
||||
if (_audio) {
|
||||
// Account for the category of sound:
|
||||
play_rate*=_manager->get_play_rate();
|
||||
switch (_audio->type) {
|
||||
case AIL_QUICK_XMIDI_TYPE:
|
||||
case AIL_QUICK_DLS_XMIDI_TYPE:
|
||||
// midi uses whole percentage values 100 == 100%
|
||||
_audio->speed = (S32)(play_rate*100.0f);
|
||||
if ((_audio->speed != -1) && (AIL_quick_status(_audio) == QSTAT_PLAYING)) {
|
||||
AIL_set_sequence_tempo((HSEQUENCE)_audio->handle, _audio->speed, 0);
|
||||
}
|
||||
audio_debug(" play_rate for this midi is now "<<_audio->speed);
|
||||
break;
|
||||
case AIL_QUICK_DIGITAL_TYPE:
|
||||
case AIL_QUICK_MPEG_DIGITAL_TYPE:
|
||||
// wave and mp3 use sample rate (e.g. 44100)
|
||||
_audio->speed = (S32)(play_rate*float(_original_playback_rate));
|
||||
if ((_audio->speed != -1) && (AIL_quick_status(_audio) == QSTAT_PLAYING)) {
|
||||
AIL_set_sample_playback_rate((HSAMPLE)_audio->handle, _audio->speed);
|
||||
}
|
||||
audio_debug(" play_rate for this wav or mp3 is now "<<_audio->speed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_play_rate
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSound::
|
||||
get_play_rate() const {
|
||||
miles_audio_debug("get_play_rate() returning "<<_play_rate);
|
||||
return _play_rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::set_balance
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_balance(float balance_right) {
|
||||
miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
|
||||
_balance=balance_right;
|
||||
// Call set_volume to effect the change:
|
||||
set_volume(_volume);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_balance
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSound::
|
||||
get_balance() const {
|
||||
audio_debug("MilesAudioSound::get_balance() returning "<<_balance);
|
||||
return _balance;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::length
|
||||
// Access:
|
||||
// Function: MilesAudioSound::get_play_rate
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioSound::
|
||||
length() const {
|
||||
return _sd->get_length();
|
||||
get_play_rate() const {
|
||||
return _play_rate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::set_active
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
@ -539,13 +144,12 @@ set_active(bool active) {
|
||||
_active = active;
|
||||
if (_active) {
|
||||
// ...activate the sound.
|
||||
if (_paused
|
||||
&&
|
||||
_loop_count==0) {
|
||||
if (_paused && _loop_count==0) {
|
||||
// ...this sound was looping when it was paused.
|
||||
_paused = false;
|
||||
play();
|
||||
}
|
||||
|
||||
} else {
|
||||
// ...deactivate the sound.
|
||||
if (status() == PLAYING) {
|
||||
@ -561,85 +165,53 @@ set_active(bool active) {
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_active
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool MilesAudioSound::
|
||||
get_active() const {
|
||||
miles_audio_debug("get_active() returning "<<_active);
|
||||
return _active;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::set_finished_event
|
||||
// Access:
|
||||
// Description:
|
||||
// Access: Public, Virtual
|
||||
// Description: This is no longer implemented.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
set_finished_event(const string &event) {
|
||||
miles_audio_debug("set_finished_event(event="<<event<<")");
|
||||
_finished_event = event;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_finished_event
|
||||
// Access:
|
||||
// Description:
|
||||
// Access: Public, Virtual
|
||||
// Description: This is no longer implemented.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &MilesAudioSound::
|
||||
get_finished_event() const {
|
||||
miles_audio_debug("get_finished_event() returning "<<_finished_event);
|
||||
return _finished_event;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::get_name
|
||||
// Access:
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const string &MilesAudioSound::
|
||||
get_name() const {
|
||||
//audio_debug("MilesAudioSound::get_name() returning "<<_file_name);
|
||||
return _file_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::status
|
||||
// Access:
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioSound::cleanup
|
||||
// Access: Private
|
||||
// Description: Called to release any resources associated with the
|
||||
// sound.
|
||||
// Access: Public, Virtual
|
||||
// Description: Stops the sound from playing and releases any
|
||||
// associated resources, in preparation for releasing
|
||||
// the sound or shutting down the sound system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioSound::
|
||||
cleanup() {
|
||||
if (_audio) {
|
||||
stop();
|
||||
if (MilesAudioManager::_miles_active) {
|
||||
AIL_quick_unload(_audio);
|
||||
}
|
||||
_audio = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //]
|
||||
|
@ -1,6 +1,5 @@
|
||||
// Filename: milesAudioSound.h
|
||||
// Created by: skyler (June 6, 2001)
|
||||
// Prior system by: cary
|
||||
// Created by: drose (30Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@ -17,8 +16,8 @@
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef __MILES_AUDIO_SOUND_H__
|
||||
#define __MILES_AUDIO_SOUND_H__
|
||||
#ifndef MILESAUDIOSOUND_H
|
||||
#define MILESAUDIOSOUND_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
@ -27,116 +26,44 @@
|
||||
#include "milesAudioManager.h"
|
||||
#include "mss.h"
|
||||
|
||||
class AutoAilLock {
|
||||
// This will lock and unlock the Miles AIL timer based
|
||||
// on the current code block. (Auto in the class name
|
||||
// is referring to "auto variable").
|
||||
public:
|
||||
AutoAilLock() {
|
||||
AIL_lock();
|
||||
}
|
||||
~AutoAilLock() {
|
||||
AIL_unlock();
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MilesAudioSound
|
||||
// Description : The base class for both MilesAudioStream and
|
||||
// MilesAudioSample.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_MILES_AUDIO MilesAudioSound : public AudioSound {
|
||||
protected:
|
||||
MilesAudioSound(MilesAudioManager *manager, const string &file_name);
|
||||
|
||||
public:
|
||||
~MilesAudioSound();
|
||||
virtual void set_loop(bool loop=true);
|
||||
virtual bool get_loop() const;
|
||||
|
||||
// For best compatability, set the loop_count,
|
||||
// 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.
|
||||
// - Calling play() a second time on the same sound before it is
|
||||
// finished will start the sound again (creating a skipping or
|
||||
// stuttering effect).
|
||||
void play();
|
||||
void stop();
|
||||
virtual void set_loop_count(unsigned long loop_count=1);
|
||||
virtual unsigned long get_loop_count() const;
|
||||
|
||||
// loop: false = play once; true = play forever.
|
||||
// inits to false.
|
||||
void set_loop(bool loop=true);
|
||||
bool get_loop() const;
|
||||
virtual float get_volume() const;
|
||||
virtual float get_balance() const;
|
||||
virtual float get_play_rate() 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;
|
||||
virtual void set_active(bool active=true);
|
||||
virtual bool get_active() const;
|
||||
|
||||
// Control time position within the sound.
|
||||
// This is similar (in concept) to the seek position within
|
||||
// a file.
|
||||
// time in seconds: 0 = beginning; length() = end.
|
||||
// inits to 0.0.
|
||||
// - Unlike the other get_* and set_* calls for a sound, the
|
||||
// current time position will change while the sound is playing.
|
||||
// To play the same sound from a time offset a second time,
|
||||
// explicitly set the time position again. When looping, the
|
||||
// second and later loops will start from the beginning of the
|
||||
// sound.
|
||||
// - If a sound is playing, calling get_time() repeatedly will
|
||||
// return different results over time. e.g.:
|
||||
// float percent_complete = s.get_time() / s.length();
|
||||
void set_time(float time=0.0f);
|
||||
float get_time() const;
|
||||
virtual void set_finished_event(const string &event);
|
||||
virtual const string &get_finished_event() const;
|
||||
|
||||
// 0 = minimum; 1.0 = maximum.
|
||||
// inits to 1.0.
|
||||
void set_volume(float volume=1.0f);
|
||||
float get_volume() const;
|
||||
virtual const string &get_name() 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.0f);
|
||||
float get_balance() const;
|
||||
virtual void cleanup();
|
||||
|
||||
// play_rate is any positive float value.
|
||||
// inits to 1.0.
|
||||
void set_play_rate(float play_rate=1.0f);
|
||||
float get_play_rate() const;
|
||||
|
||||
// inits to manager's state.
|
||||
void set_active(bool active=true);
|
||||
bool get_active() const;
|
||||
|
||||
// This is the string that throw_event() will throw
|
||||
// when the sound finishes playing. It is not triggered
|
||||
// when the sound is stopped with stop().
|
||||
void set_finished_event(const string& event);
|
||||
const string& get_finished_event() const;
|
||||
|
||||
const string& get_name() const;
|
||||
|
||||
// return: playing time in seconds.
|
||||
float length() const;
|
||||
|
||||
void set_3d_attributes(float* pos, float* vel);
|
||||
void get_3d_attributes(float* pos, float* vel);
|
||||
|
||||
AudioSound::SoundStatus status() const;
|
||||
|
||||
void finished();
|
||||
|
||||
private:
|
||||
PT(MilesAudioManager::SoundData) _sd;
|
||||
HAUDIO _audio;
|
||||
protected:
|
||||
PT(MilesAudioManager) _manager;
|
||||
string _file_name;
|
||||
|
||||
float _volume; // 0..1.0
|
||||
float _balance; // -1..1
|
||||
float _play_rate; // 0..1.0
|
||||
mutable float _length; // in seconds.
|
||||
unsigned long _loop_count;
|
||||
S32 _original_playback_rate;
|
||||
|
||||
// This is the string that throw_event() will throw
|
||||
// when the sound finishes playing. It is not triggered
|
||||
// when the sound is stopped with stop().
|
||||
string _finished_event;
|
||||
|
||||
string _file_name;
|
||||
|
||||
// _active is for things like a 'turn off sound effects' in
|
||||
// a preferences pannel.
|
||||
@ -149,12 +76,10 @@ private:
|
||||
// it was set inactive.
|
||||
bool _paused;
|
||||
|
||||
MilesAudioSound(MilesAudioManager* manager, MilesAudioManager::SoundData *sd,
|
||||
string file_name, float length=0.0f);
|
||||
void cleanup();
|
||||
|
||||
friend class MilesAudioManager;
|
||||
|
||||
// This is the string that throw_event() will throw when the sound
|
||||
// finishes playing. It is not triggered when the sound is stopped
|
||||
// with stop(). Note: no longer implemented.
|
||||
string _finished_event;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
@ -172,10 +97,12 @@ public:
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class MilesAudioManager;
|
||||
};
|
||||
|
||||
#include "milesAudioSound.I"
|
||||
|
||||
#endif //]
|
||||
|
||||
#endif /* __MILES_AUDIO_SOUND_H__ */
|
||||
#endif
|
||||
|
18
panda/src/audiotraits/milesAudioStream.I
Normal file
18
panda/src/audiotraits/milesAudioStream.I
Normal file
@ -0,0 +1,18 @@
|
||||
// Filename: milesAudioStream.I
|
||||
// Created by: drose (26Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
299
panda/src/audiotraits/milesAudioStream.cxx
Normal file
299
panda/src/audiotraits/milesAudioStream.cxx
Normal file
@ -0,0 +1,299 @@
|
||||
// Filename: milesAudioStream.cxx
|
||||
// Created by: drose (26Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 "milesAudioStream.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "milesAudioManager.h"
|
||||
#include "pnotify.h"
|
||||
|
||||
TypeHandle MilesAudioStream::_type_handle;
|
||||
|
||||
#undef miles_audio_debug
|
||||
|
||||
#ifndef NDEBUG //[
|
||||
#define miles_audio_debug(x) \
|
||||
audio_debug("MilesAudioStream \""<<get_name()<<"\" "<< x )
|
||||
#else //][
|
||||
#define miles_audio_debug(x) ((void)0)
|
||||
#endif //]
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::Constructor
|
||||
// Access: Private
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioStream::
|
||||
MilesAudioStream(MilesAudioManager *manager, const string &file_name,
|
||||
const Filename &path) :
|
||||
MilesAudioSound(manager, file_name),
|
||||
_path(path)
|
||||
{
|
||||
_stream = 0;
|
||||
_got_length = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MilesAudioStream::
|
||||
~MilesAudioStream() {
|
||||
miles_audio_debug("~MilesAudioStream()");
|
||||
cleanup();
|
||||
|
||||
_manager->release_sound(this);
|
||||
miles_audio_debug("~MilesAudioStream() done");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::play
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
play() {
|
||||
miles_audio_debug("play()");
|
||||
if (_active) {
|
||||
|
||||
_manager->starting_sound(this);
|
||||
|
||||
if (_stream == 0) {
|
||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||
_stream = AIL_open_stream(mgr->_digital_driver, _path.c_str(), 0);
|
||||
} else {
|
||||
// We already had the stream open. Keep it open; just restart
|
||||
// it.
|
||||
AIL_pause_stream(_stream, 1);
|
||||
_manager->stop_service_stream(_stream);
|
||||
}
|
||||
|
||||
if (_stream == 0) {
|
||||
milesAudio_cat.warning()
|
||||
<< "Could not play " << _file_name << ": too many open streams\n";
|
||||
|
||||
} else {
|
||||
// Start playing:
|
||||
HSAMPLE sample = AIL_stream_sample_handle(_stream);
|
||||
nassertv(sample != 0);
|
||||
|
||||
_original_playback_rate = AIL_sample_playback_rate(sample);
|
||||
set_volume(_volume);
|
||||
set_play_rate(_play_rate);
|
||||
|
||||
AIL_set_stream_loop_count(_stream, _loop_count);
|
||||
|
||||
if (miles_audio_panda_threads) {
|
||||
AIL_auto_service_stream(_stream, 0);
|
||||
_manager->start_service_stream(_stream);
|
||||
} else {
|
||||
AIL_auto_service_stream(_stream, 1);
|
||||
}
|
||||
AIL_start_stream(_stream);
|
||||
}
|
||||
|
||||
} else {
|
||||
// In case _loop_count gets set to forever (zero):
|
||||
audio_debug(" paused "<<_file_name );
|
||||
_paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::stop
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
stop() {
|
||||
miles_audio_debug("stop()");
|
||||
_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
|
||||
// that it was looping when it was set inactive. There is no need to
|
||||
// make this symmetrical with play(). set_active() is the 'owner' of
|
||||
// _paused. play() accesses _paused to help in the situation where
|
||||
// someone calls play on an inactive sound().
|
||||
if (_stream != 0) {
|
||||
_manager->stop_service_stream(_stream);
|
||||
|
||||
AIL_pause_stream(_stream, 1);
|
||||
AIL_close_stream(_stream);
|
||||
_stream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
set_time(float time) {
|
||||
if (_stream != 0) {
|
||||
S32 time_ms = (S32)(1000.0f * time);
|
||||
|
||||
// Ensure we don't inadvertently run off the end of the sound.
|
||||
S32 length_ms;
|
||||
AIL_stream_ms_position(_stream, &length_ms, NULL);
|
||||
time_ms = min(time_ms, length_ms);
|
||||
|
||||
AIL_set_stream_ms_position(_stream, time_ms);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioStream::
|
||||
get_time() const {
|
||||
nassertr(_stream, 0.0f);
|
||||
|
||||
S32 current_ms;
|
||||
AIL_stream_ms_position(_stream, NULL, ¤t_ms);
|
||||
float time = float(current_ms * 0.001f);
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
set_volume(float volume) {
|
||||
_volume = volume;
|
||||
|
||||
if (_stream != 0) {
|
||||
HSAMPLE sample = AIL_stream_sample_handle(_stream);
|
||||
nassertv(sample != 0);
|
||||
|
||||
volume *= _manager->get_volume();
|
||||
|
||||
// Change to Miles volume, range 0 to 1.0:
|
||||
F32 milesVolume = volume;
|
||||
milesVolume = min(milesVolume, 1.0f);
|
||||
milesVolume = max(milesVolume, 0.0f);
|
||||
|
||||
// Convert balance of -1.0..1.0 to 0-1.0:
|
||||
F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f);
|
||||
|
||||
AIL_set_sample_volume_pan(sample, milesVolume, milesBalance);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::set_balance
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
set_balance(float balance_right) {
|
||||
_balance = balance_right;
|
||||
|
||||
// Call set_volume to effect the change:
|
||||
set_volume(_volume);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::set_play_rate
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
set_play_rate(float play_rate) {
|
||||
_play_rate = play_rate;
|
||||
|
||||
if (_stream != 0) {
|
||||
HSAMPLE sample = AIL_stream_sample_handle(_stream);
|
||||
nassertv(sample != 0);
|
||||
|
||||
play_rate *= _manager->get_play_rate();
|
||||
|
||||
// wave and mp3 use sample rate (e.g. 44100)
|
||||
S32 speed = (S32)(play_rate * (float)_original_playback_rate);
|
||||
AIL_set_sample_playback_rate(sample, speed);
|
||||
audio_debug(" play_rate for this wav or mp3 is now " << speed);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::length
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
float MilesAudioStream::
|
||||
length() const {
|
||||
if (!_got_length) {
|
||||
if (_stream == 0) {
|
||||
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
|
||||
((MilesAudioStream *)this)->_stream = AIL_open_stream(mgr->_digital_driver, _path.c_str(), 0);
|
||||
}
|
||||
|
||||
S32 length_ms;
|
||||
AIL_stream_ms_position(_stream, &length_ms, NULL);
|
||||
_length = (float)length_ms * 0.001f;
|
||||
_got_length = true;
|
||||
}
|
||||
|
||||
return _length;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::status
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
AudioSound::SoundStatus MilesAudioStream::
|
||||
status() const {
|
||||
if (!_stream) {
|
||||
return AudioSound::READY;
|
||||
}
|
||||
|
||||
switch (AIL_stream_status(_stream)) {
|
||||
case SMP_STOPPED:
|
||||
case SMP_DONE:
|
||||
return AudioSound::READY;
|
||||
case SMP_PLAYING:
|
||||
case SMP_PLAYINGBUTRELEASED:
|
||||
return AudioSound::PLAYING;
|
||||
default:
|
||||
return AudioSound::BAD;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MilesAudioStream::cleanup
|
||||
// Access: Public, Virtual
|
||||
// Description: Called to release any resources associated with the
|
||||
// sound.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MilesAudioStream::
|
||||
cleanup() {
|
||||
if (_stream) {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif //]
|
91
panda/src/audiotraits/milesAudioStream.h
Normal file
91
panda/src/audiotraits/milesAudioStream.h
Normal file
@ -0,0 +1,91 @@
|
||||
// Filename: milesAudioStream.h
|
||||
// Created by: drose (26Jul07)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MILESAUDIOSTREAM_H
|
||||
#define MILESAUDIOSTREAM_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#ifdef HAVE_RAD_MSS //[
|
||||
|
||||
#include "milesAudioSound.h"
|
||||
#include "milesAudioManager.h"
|
||||
#include "mss.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MilesAudioStream
|
||||
// Description : This represents a sound file played by the Miles
|
||||
// Sound System, similar to MilesAudioSample, except
|
||||
// that it is streamed from disk instead of preloaded
|
||||
// into memory.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_MILES_AUDIO MilesAudioStream : public MilesAudioSound {
|
||||
private:
|
||||
MilesAudioStream(MilesAudioManager *manager, const string &file_name,
|
||||
const Filename &path);
|
||||
|
||||
public:
|
||||
virtual ~MilesAudioStream();
|
||||
|
||||
virtual void play();
|
||||
virtual void stop();
|
||||
|
||||
virtual void set_time(float time=0.0f);
|
||||
virtual float get_time() const;
|
||||
|
||||
virtual void set_volume(float volume=1.0f);
|
||||
virtual void set_balance(float balance_right=0.0f);
|
||||
virtual void set_play_rate(float play_rate=1.0f);
|
||||
|
||||
virtual float length() const;
|
||||
|
||||
virtual AudioSound::SoundStatus status() const;
|
||||
|
||||
virtual void cleanup();
|
||||
|
||||
private:
|
||||
Filename _path;
|
||||
HSTREAM _stream;
|
||||
S32 _original_playback_rate;
|
||||
mutable float _length;
|
||||
mutable bool _got_length;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
MilesAudioSound::init_type();
|
||||
register_type(_type_handle, "MilesAudioStream",
|
||||
MilesAudioSound::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;
|
||||
|
||||
friend class MilesAudioManager;
|
||||
};
|
||||
|
||||
#include "milesAudioStream.I"
|
||||
|
||||
#endif //]
|
||||
|
||||
#endif
|
@ -1,5 +1,9 @@
|
||||
|
||||
#include "config_milesAudio.cxx"
|
||||
#include "milesAudioManager.cxx"
|
||||
#include "milesAudioSample.cxx"
|
||||
#include "milesAudioSequence.cxx"
|
||||
#include "milesAudioSound.cxx"
|
||||
#include "milesAudioStream.cxx"
|
||||
#include "globalMilesManager.cxx"
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user