Remove support for Miles audio system

See #440 for discussion on why this is being removed.

Closes #660
This commit is contained in:
Mitchell Stokes 2019-05-19 20:37:35 -07:00 committed by rdb
parent 0ce25d0e30
commit 1a03d997b2
30 changed files with 5 additions and 3980 deletions

View File

@ -27,8 +27,7 @@ class SoundInterval(Interval.Interval):
# than explicitly restarting the sound every time around. This
# prevents a skip in the sound at every repetition (the gap in
# the sound is caused by the delay between the end of the sound
# and the next taskMgr cycle). There still seems to be a skip
# in Miles when looping MP3s. =(
# and the next taskMgr cycle).
# RAU 03/01/07 add listenerNode in case we don't want to
# use base.camera as the listener, node must not be None
def __init__(self, sound, loop = 0, duration = 0.0, name = None,
@ -62,23 +61,6 @@ class SoundInterval(Interval.Interval):
#if (duration == 0):
# self.notify.warning('zero length duration!')
# MPG - hack for Miles bug
#duration += 1.5
# DCR - hack for Miles bug - adding 1.5 seconds caused
# problems for MG_neg_buzzer.wav
# DCR - what this is all about: Miles is under-reporting the
# length of MP3 files, and they're getting cut off too early.
# This is a temporary hack. We could:
# - hack Miles to fix its MP3 length calculation
# - complain louder about this to RAD
# - precompute MP3 durations and store them in a table
# drose - ok, I've put in a lower-level workaround in the
# MilesAudioManager. This is no longer necessary up here,
# where it pollutes SoundInterval for everyone.
#duration += min(duration * 2.4, 1.5)
# Generate unique name if necessary
if (name == None):

View File

@ -325,11 +325,3 @@ void AudioManager::
write(std::ostream &out) const {
out << (*this) << "\n";
}
/**
* For use only with Miles.
*/
void AudioManager::
set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2, LVecBase3 *speaker3, LVecBase3 *speaker4, LVecBase3 *speaker5, LVecBase3 *speaker6, LVecBase3 *speaker7, LVecBase3 *speaker8, LVecBase3 *speaker9) {
// intentionally blank
}

View File

@ -178,9 +178,6 @@ PUBLISHED:
virtual void output(std::ostream &out) const;
virtual void write(std::ostream &out) const;
// set_speaker_configuration is a Miles only method.
virtual void set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2=nullptr, LVecBase3 *speaker3=nullptr, LVecBase3 *speaker4=nullptr, LVecBase3 *speaker5=nullptr, LVecBase3 *speaker6=nullptr, LVecBase3 *speaker7=nullptr, LVecBase3 *speaker8=nullptr, LVecBase3 *speaker9=nullptr);
public:
static void register_AudioManager_creator(Create_AudioManager_proc* proc);

View File

@ -83,23 +83,6 @@ set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat cente
// intentionally blank
}
/**
* For use only with Miles.
*/
PN_stdfloat AudioSound::
get_speaker_level(int index) {
// intentionally blank
return 0.0;
}
/**
* For use only with Miles.
*/
void AudioSound::
set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2, PN_stdfloat level3, PN_stdfloat level4, PN_stdfloat level5, PN_stdfloat level6, PN_stdfloat level7, PN_stdfloat level8, PN_stdfloat level9) {
// intentionally blank
}
/**
* Configure the local DSP filter chain.
*

View File

@ -104,17 +104,10 @@ PUBLISHED:
virtual void set_3d_max_distance(PN_stdfloat dist);
virtual PN_stdfloat get_3d_max_distance() const;
// *_speaker_mix and *_speaker_level(s) serve the same purpose.
// *_speaker_mix is for use with FMOD. *_speaker_level(s) is for use with
// Miles. Both interfaces exist because of a significant difference in the
// two APIs. Hopefully the difference can be reconciled into a single
// interface at some point.
// *_speaker_mix is for use with FMOD.
virtual PN_stdfloat get_speaker_mix(int speaker);
virtual void set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat sideright);
virtual PN_stdfloat get_speaker_level(int index);
virtual void set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2=-1.0f, PN_stdfloat level3=-1.0f, PN_stdfloat level4=-1.0f, PN_stdfloat level5=-1.0f, PN_stdfloat level6=-1.0f, PN_stdfloat level7=-1.0f, PN_stdfloat level8=-1.0f, PN_stdfloat level9=-1.0f);
virtual int get_priority();
virtual void set_priority(int priority);

View File

@ -100,11 +100,6 @@ ConfigVariableEnum<FmodSpeakerMode> fmod_speaker_mode
"Options: raw, mono, stereo, quad, surround, 5.1 and 7.1. "));
// Config variables for Miles:
ConfigVariableBool audio_software_midi
("audio-software-midi", true);
ConfigVariableFilename audio_dls_file
("audio-dls-file", Filename(),
PRC_DESC("Specifies a DLS file that defines an instrument set to load "
@ -113,24 +108,6 @@ ConfigVariableFilename audio_dls_file
"one is available; the likely success of this depends on the "
"operating system."));
ConfigVariableBool audio_play_midi
("audio-play-midi", true);
ConfigVariableBool audio_play_wave
("audio-play-wave", true);
ConfigVariableBool audio_play_mp3
("audio-play-mp3", true);
ConfigVariableInt audio_output_rate
("audio-output-rate", 22050);
ConfigVariableInt audio_output_bits
("audio-output-bits", 16);
ConfigVariableInt audio_output_channels
("audio-output-channels", 2);
ConfigureFn(config_audio) {
FilterProperties::init_type();
AudioLoadRequest::init_type();

View File

@ -58,6 +58,7 @@ EXPCL_PANDA_AUDIO std::istream &operator >> (std::istream &in, FmodSpeakerMode &
extern EXPCL_PANDA_AUDIO ConfigVariableInt fmod_number_of_sound_channels;
extern EXPCL_PANDA_AUDIO ConfigVariableBool fmod_use_surround_sound;
extern EXPCL_PANDA_AUDIO ConfigVariableEnum<FmodSpeakerMode> fmod_speaker_mode;
extern EXPCL_PANDA_AUDIO ConfigVariableFilename audio_dls_file;
// Config vars for OpenAL:
@ -67,19 +68,6 @@ extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_drop_off_factor;
extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_buffering_seconds;
extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_preload_threshold;
// Config vars for Miles:
extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_software_midi;
extern EXPCL_PANDA_AUDIO ConfigVariableFilename audio_dls_file;
extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_play_midi;
extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_play_wave;
extern EXPCL_PANDA_AUDIO ConfigVariableBool audio_play_mp3;
extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_output_rate;
extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_output_bits;
extern EXPCL_PANDA_AUDIO ConfigVariableInt audio_output_channels;
#ifdef NOTIFY_DEBUG //[
// Non-release build:
#define audio_debug(msg) \

View File

@ -21,7 +21,7 @@
class EXPCL_PANDA_AUDIO NullAudioManager : public AudioManager {
// All of these methods are stubbed out to some degree. If you're looking
// for a starting place for a new AudioManager, please consider looking at
// the milesAudioManager.
// the openalAudioManager.
public:
NullAudioManager();

View File

@ -23,7 +23,7 @@
class EXPCL_PANDA_AUDIO NullAudioSound : public AudioSound {
// All of these methods are stubbed out to some degree. If you're looking
// for a starting place for a new AudioManager, please consider looking at
// the milesAudioManager.
// the openalAudioManager.
public:
~NullAudioSound();

View File

@ -1,102 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file config_milesAudio.cxx
* @author skyler
*/
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#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"
#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_MILES_AUDIO)
#error Buildsystem error: BUILDING_MILES_AUDIO not defined
#endif
ConfigureDef(config_milesAudio);
NotifyCategoryDef(milesAudio, ":audio");
ConfigureFn(config_milesAudio) {
init_libMilesAudio();
}
ConfigVariableBool miles_audio_force_midi_reset
("audio-force-midi-reset", true);
ConfigVariableInt miles_audio_expand_mp3_threshold
("miles-audio-expand-mp3-threshold", 16384,
PRC_DESC("This enables a Miles workaround in which small MP3 files are "
"expanded in-memory at load time into WAV format, which can "
"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 only applies to files "
"within the miles-audio-preload-threshold."));
ConfigVariableInt miles_audio_preload_threshold
("miles-audio-preload-threshold", -1,
PRC_DESC("This should be no smaller "
"than miles-audio-expand-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."));
/**
* Initializes the library. This must be called at least once before any of
* the functions or classes in this library can be used. Normally it will be
* called by the static initializers and need not be called explicitly, but
* special cases exist.
*/
void
init_libMilesAudio() {
static bool initialized = false;
if (initialized) {
return;
}
initialized = true;
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");
ps->add_system("audio");
ps->set_system_tag("audio", "implementation", "Miles");
}
/**
* This function is called when the dynamic library is loaded; it should
* return the Create_AudioManager function appropriate to create a
* MilesAudioManager.
*/
Create_AudioManager_proc *
get_audio_manager_func_miles_audio() {
init_libMilesAudio();
return &Create_MilesAudioManager;
}
#endif //]

View File

@ -1,37 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file config_milesAudio.h
* @author skyler
*/
#ifndef CONFIG_MILESAUDIO_H
#define CONFIG_MILESAUDIO_H
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "notifyCategoryProxy.h"
#include "configVariableBool.h"
#include "configVariableInt.h"
#include "dconfig.h"
#include "audioManager.h"
ConfigureDecl(config_milesAudio, EXPCL_MILES_AUDIO, EXPTP_MILES_AUDIO);
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_preload_threshold;
extern ConfigVariableBool miles_audio_panda_threads;
extern EXPCL_MILES_AUDIO void init_libMilesAudio();
extern "C" EXPCL_MILES_AUDIO Create_AudioManager_proc *get_audio_manager_func_miles_audio();
#endif //]
#endif // CONFIG_MILESAUDIO_H

View File

@ -1,39 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file globalMilesManager.I
* @author drose
* @date 2007-07-30
*/
/**
* 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;
}
/**
* Returns the number of sample handles that have been allocated.
*/
INLINE int GlobalMilesManager::
get_num_samples() const {
LightMutexHolder holder(_samples_lock);
return _samples.size();
}
/**
* Returns the number of sequence handles that have been allocated.
*/
INLINE int GlobalMilesManager::
get_num_sequences() const {
LightMutexHolder holder(_sequences_lock);
return _sequences.size();
}

View File

@ -1,446 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file globalMilesManager.cxx
* @author drose
* @date 2007-07-26
*/
#include "globalMilesManager.h"
#ifdef HAVE_RAD_MSS //[
#include "lightMutexHolder.h"
#include "milesAudioManager.h"
#include "milesAudioSample.h"
#include "milesAudioSequence.h"
#ifdef WIN32
// For midiOutReset()
#include <windows.h>
#include <mmsystem.h>
#endif
using std::istream;
using std::string;
GlobalMilesManager *GlobalMilesManager::_global_ptr;
/**
*
*/
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;
}
/**
* 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) {
LightMutexHolder holder(_managers_lock);
_managers.insert(manager);
if (!_is_open) {
open_api();
}
}
/**
* 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) {
LightMutexHolder holder(_managers_lock);
_managers.erase(manager);
if (_managers.empty() && _is_open) {
close_api();
}
}
/**
* Calls cleanup() on all MilesAudioManagers, to cause a clean shutdown.
*/
void GlobalMilesManager::
cleanup() {
LightMutexHolder holder(_managers_lock);
Managers::iterator mi;
for (mi = _managers.begin(); mi != _managers.end(); ++mi) {
(*mi)->cleanup();
}
}
/**
* 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) {
LightMutexHolder 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 != nullptr) {
// 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;
}
/**
* Indicates that the indicated AudioSound no longer needs this sample.
*/
void GlobalMilesManager::
release_sample(size_t index, MilesAudioSample *sound) {
LightMutexHolder holder(_samples_lock);
nassertv(index < _samples.size());
SampleData &smp = _samples[index];
if (smp._sound == sound) {
smp._sound = nullptr;
}
}
/**
* 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) {
LightMutexHolder 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 != nullptr) {
// 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;
}
/**
* Indicates that the indicated AudioSound no longer needs this sequence.
*/
void GlobalMilesManager::
release_sequence(size_t index, MilesAudioSequence *sound) {
LightMutexHolder holder(_sequences_lock);
nassertv(index < _sequences.size());
SequenceData &seq = _sequences[index];
if (seq._sound == sound) {
seq._sound = nullptr;
}
}
/**
* 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!=nullptr) && (_midi_driver->deviceid != MIDI_nullptr_DRIVER) && (_midi_driver->hMidiOut != nullptr)) {
audio_debug("MilesAudioManager::calling midiOutReset");
midiOutReset(_midi_driver->hMidiOut);
}
#endif
}
/**
* Returns the pointer to the one GlobalMilesManager object.
*/
GlobalMilesManager *GlobalMilesManager::
get_global_ptr() {
if (_global_ptr == nullptr) {
_global_ptr = new GlobalMilesManager;
}
return _global_ptr;
}
/**
* 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, nullptr, 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_model_path());
_dls_data.clear();
PT(VirtualFile) file = vfs->get_file(dls_pathname);
if (file == nullptr) {
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;
}
/**
* 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;
}
/**
* 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(string(filename)), true);
if (strm == nullptr) {
// Failure.
return 0;
}
// Success.
(*file_handle) = (UINTa)strm;
return 1;
}
/**
* 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);
}
/**
* 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, std::ios::beg);
break;
case AIL_FILE_SEEK_CURRENT:
strm->seekg(offset, std::ios::cur);
break;
case AIL_FILE_SEEK_END:
strm->seekg(offset, std::ios::end);
break;
}
return strm->tellg();
}
/**
* 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 //]

View File

@ -1,117 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file globalMilesManager.h
* @author drose
* @date 2007-07-26
*/
#ifndef GLOBALMILESMANAGER_H
#define GLOBALMILESMANAGER_H
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "pset.h"
#include "lightMutex.h"
#include "lightMutexHolder.h"
#include <mss.h>
#ifndef UINTa
#define UINTa U32
#endif
#ifndef SINTa
#define SINTa S32
#endif
class MilesAudioSample;
class MilesAudioSequence;
/**
* 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);
INLINE int get_num_samples() const;
bool get_sequence(HSEQUENCE &sequence, size_t &index, MilesAudioSequence *sound);
void release_sequence(size_t index, MilesAudioSequence *sound);
INLINE int get_num_sequences() const;
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;
vector_uchar _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;
LightMutex _managers_lock;
class SampleData {
public:
HSAMPLE _sample;
MilesAudioSample *_sound;
};
typedef pvector<SampleData> Samples;
Samples _samples;
LightMutex _samples_lock;
class SequenceData {
public:
HSEQUENCE _sequence;
MilesAudioSequence *_sound;
};
typedef pvector<SequenceData> Sequences;
Sequences _sequences;
LightMutex _sequences_lock;
static GlobalMilesManager *_global_ptr;
};
#include "globalMilesManager.I"
#endif //]
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,198 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioManager.h
* @author skyler
* @date 2001-06-06
* Prior system by: cary
*/
#ifndef __MILES_AUDIO_MANAGER_H__ //[
#define __MILES_AUDIO_MANAGER_H__
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "audioManager.h"
#include "pset.h"
#include "pmap.h"
#include "pdeque.h"
#include "pvector.h"
#include "thread.h"
#include "pmutex.h"
#include "lightReMutex.h"
#include "conditionVar.h"
#include "vector_uchar.h"
#include <mss.h>
class MilesAudioSound;
class EXPCL_MILES_AUDIO MilesAudioManager: public AudioManager {
public:
// See AudioManager.h for documentation.
MilesAudioManager();
virtual ~MilesAudioManager();
virtual void shutdown();
virtual bool is_valid();
virtual PT(AudioSound) get_sound(const Filename &file_name, bool positional = false, int mode=SM_heuristic);
virtual PT(AudioSound) get_sound(MovieAudio *sound, bool positional = false, int mode=SM_heuristic);
virtual void uncache_sound(const Filename &file_name);
virtual void clear_cache();
virtual void set_cache_limit(unsigned int count);
virtual unsigned int get_cache_limit() const;
virtual void set_volume(PN_stdfloat volume);
virtual PN_stdfloat get_volume() const;
void set_play_rate(PN_stdfloat play_rate);
PN_stdfloat get_play_rate() const;
virtual void set_active(bool active);
virtual bool get_active() const;
virtual void set_concurrent_sound_limit(unsigned int limit = 0);
virtual unsigned int get_concurrent_sound_limit() const;
virtual void reduce_sounds_playing_to(unsigned int count);
virtual void stop_all_sounds();
virtual void update();
// Tell the manager that the sound dtor was called.
void release_sound(MilesAudioSound *audioSound);
void cleanup();
// 3D spatialized sound support. Spatialized sound was originally added for
// FMOD, so there are parts of the interface in the Miles implementation
// that are a little more awkward than they would be otherwise.
virtual void audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat xy, PN_stdfloat xz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz);
virtual void audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz);
virtual void audio_3d_set_distance_factor(PN_stdfloat factor);
virtual PN_stdfloat audio_3d_get_distance_factor() const;
virtual void audio_3d_set_doppler_factor(PN_stdfloat factor);
virtual PN_stdfloat audio_3d_get_doppler_factor() const;
virtual void audio_3d_set_drop_off_factor(PN_stdfloat factor);
virtual PN_stdfloat audio_3d_get_drop_off_factor() const;
virtual void set_speaker_configuration(LVecBase3 *speaker1, LVecBase3 *speaker2=nullptr, LVecBase3 *speaker3=nullptr, LVecBase3 *speaker4=nullptr, LVecBase3 *speaker5=nullptr, LVecBase3 *speaker6=nullptr, LVecBase3 *speaker7=nullptr, LVecBase3 *speaker8=nullptr, LVecBase3 *speaker9=nullptr);
virtual void output(std::ostream &out) const;
virtual void write(std::ostream &out) const;
private:
bool do_is_valid();
void do_reduce_sounds_playing_to(unsigned int count);
void do_clear_cache();
void start_service_stream(HSTREAM stream);
void stop_service_stream(HSTREAM stream);
void most_recently_used(const std::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:
SoundData();
~SoundData();
PN_stdfloat get_length();
void set_length(PN_stdfloat length);
Filename _basename;
S32 _file_type;
vector_uchar _raw_data;
bool _has_length;
PN_stdfloat _length; // in seconds.
};
typedef pmap<std::string, PT(SoundData) > SoundMap;
SoundMap _sounds;
typedef pset<MilesAudioSound *> AudioSet;
// The offspring of this manager:
AudioSet _sounds_on_loan;
typedef pset<MilesAudioSound *> SoundsPlaying;
// The sounds from this manager that are currently playing:
SoundsPlaying _sounds_playing;
// The Least Recently Used mechanism:
typedef pdeque<const std::string *> LRU;
LRU _lru;
// State:
PN_stdfloat _volume;
PN_stdfloat _play_rate;
bool _active;
int _cache_limit;
bool _cleanup_required;
unsigned int _concurrent_sound_limit;
bool _is_valid;
bool _hasMidiSounds;
// This mutex protects everything above.
LightReMutex _lock;
bool _sounds_finished;
typedef pvector<HSTREAM> Streams;
PT(StreamThread) _stream_thread;
Streams _streams;
Mutex _streams_lock;
ConditionVar _streams_cvar;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
AudioManager::init_type();
register_type(_type_handle, "MilesAudioManager",
AudioManager::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 MilesAudioSound;
friend class MilesAudioSample;
friend class MilesAudioSequence;
friend class MilesAudioStream;
};
EXPCL_MILES_AUDIO AudioManager *Create_MilesAudioManager();
#endif //]
#endif //]

View File

@ -1,13 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSample.I
* @author skyler
* @date 2001-06-06
* Prior system by: cary
*/

View File

@ -1,530 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSample.cxx
* @author skyler
* @date 2001-06-06
*/
#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 //]
/**
* This constructor is called only by the MilesAudioManager.
*/
MilesAudioSample::
MilesAudioSample(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
const std::string &file_name) :
MilesAudioSound(manager, file_name),
_sd(sd)
{
nassertv(sd != nullptr);
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;
}
/**
*
*/
MilesAudioSample::
~MilesAudioSample() {
miles_audio_debug("~MilesAudioSample()");
cleanup();
miles_audio_debug("~MilesAudioSample() done");
}
/**
*
*/
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);
AIL_set_sample_user_data(_sample, 0, (SINTa)this);
AIL_register_EOS_callback(_sample, finish_callback);
set_volume(_volume);
set_play_rate(_play_rate);
AIL_set_sample_loop_count(_sample, _loop_count);
if (_got_start_time) {
do_set_time(_start_time);
AIL_resume_sample(_sample);
} else {
AIL_start_sample(_sample);
}
}
_got_start_time = false;
}
} else {
// In case _loop_count gets set to forever (zero):
audio_debug(" paused "<<_file_name );
_paused = true;
}
}
/**
*
*/
void MilesAudioSample::
stop() {
if (_manager == nullptr) {
return;
}
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 cddvd 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().
// it fixes audio bug, I don't understand the reasoning of the above comment
_paused = false;
if (_sample != 0) {
AIL_end_sample(_sample);
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
mgr->release_sample(_sample_index, this);
_sample = 0;
_sample_index = 0;
}
}
/**
*
*/
PN_stdfloat MilesAudioSample::
get_time() const {
if (_sample == 0) {
if (_got_start_time) {
return _start_time;
}
return 0.0f;
}
S32 current_ms;
AIL_sample_ms_position(_sample, nullptr, &current_ms);
PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
return time;
}
/**
*
*/
void MilesAudioSample::
set_volume(PN_stdfloat 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 = std::min(milesVolume, 1.0f);
milesVolume = std::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);
}
}
/**
*
*/
void MilesAudioSample::
set_balance(PN_stdfloat balance_right) {
miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
_balance = balance_right;
// Call set_volume to effect the change:
set_volume(_volume);
}
/**
*
*/
void MilesAudioSample::
set_play_rate(PN_stdfloat 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 * (PN_stdfloat)_original_playback_rate);
AIL_set_sample_playback_rate(_sample, speed);
audio_debug(" play_rate for this wav or mp3 is now " << speed);
}
}
/**
*
*/
PN_stdfloat MilesAudioSample::
length() const {
return _sd->get_length();
}
/**
*
*/
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;
}
}
/**
* 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();
set_active(false);
nassertv(_sample == 0);
if (_manager != nullptr) {
_manager->release_sound(this);
_manager = nullptr;
}
}
/**
*
*/
void MilesAudioSample::
output(std::ostream &out) const {
out << get_type() << " " << get_name() << " " << status();
if (!_sd.is_null()) {
out << " " << (_sd->_raw_data.size() + 1023) / 1024 << "K";
}
}
/**
* Set position and velocity of this sound. Note that Y and Z are switched to
* translate from Miles's coordinate system.
*/
void MilesAudioSample::set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
audio_debug("MilesAudioSample::set_3d_attributes() Setting a sound's 3D Coordinates.");
if(_sample != 0) {
AIL_set_sample_3D_position(_sample, px, pz, py);
AIL_set_sample_3D_velocity_vector(_sample, vx, vz, vy);
} else {
audio_warning("_sample == 0 in MilesAudioSample::set_3d_attributes().");
}
}
/**
* Get position and velocity of this sound.
*/
void MilesAudioSample::get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
audio_debug("MilesAudioSample::get_3d_attributes().");
if(_sample != 0) {
float lpx, lpy, lpz, lvx, lvy, lvz;
AIL_sample_3D_position(_sample, &lpx, &lpz, &lpy);
AIL_sample_3D_velocity(_sample, &lvx, &lvz, &lvy);
*px = lpx;
*py = lpy;
*pz = lpz;
*vx = lvx;
*vy = lvy;
*vz = lvz;
} else {
audio_warning("_sample == 0 in MilesAudioSample::get_3d_attributes().");
}
}
/**
* Set the distance that this sound begins to fall off. With Miles's default
* falloff behavior, when the distance between the sound and the listener is
* doubled, the volume is halved, and vice versa.
*/
void MilesAudioSample::set_3d_min_distance(PN_stdfloat dist) {
audio_debug("MilesAudioSample::set_3d_min_distance() Setting the sound's 3D min distance ( min= " << dist << " ) ");
if(_sample != 0) {
// Implementation is awkward, since Miles gets and sets min and max
// distances in a single operation.
float max_dist;
int auto_3D_wet_atten;
AIL_sample_3D_distances(_sample, &max_dist, nullptr, &auto_3D_wet_atten);
AIL_set_sample_3D_distances(_sample, max_dist, dist, auto_3D_wet_atten);
} else {
audio_warning("_sample == 0 in MilesAudioSample::set_3d_min_distance().");
}
}
/**
* Get the distance that this sound begins to fall off.
*/
PN_stdfloat MilesAudioSample::get_3d_min_distance() const {
audio_debug("MilesAudioSample::get_3d_min_distance() ");
if(_sample != 0) {
float min_dist;
AIL_sample_3D_distances(_sample, nullptr, &min_dist, nullptr);
return (PN_stdfloat)min_dist;
} else {
audio_warning("_sample == 0 in MilesAudioSample::get_3d_min_distance().");
return -1.0;
}
}
/**
* Set the distance at which this sound is clipped to silence. Note that this
* value does not affect the rate at which the sound falls off, but only the
* distance at which it gets clipped.
*/
void MilesAudioSample::set_3d_max_distance(PN_stdfloat dist) {
audio_debug("MilesAudioSample::set_3d_max_distance() Setting the sound's 3D max distance ( max= " << dist << " ) ");
if(_sample != 0) {
// Implementation is awkward, since Miles gets and sets min and max
// distances in a single operation.
float min_dist;
int auto_3D_wet_atten;
AIL_sample_3D_distances(_sample, nullptr, &min_dist, &auto_3D_wet_atten);
AIL_set_sample_3D_distances(_sample, dist, min_dist, auto_3D_wet_atten);
} else {
audio_warning("_sample == 0 in MilesAudioSample::set_3d_max_distance().");
}
}
/**
* Get the distance at which this sound is clipped to silence.
*/
PN_stdfloat MilesAudioSample::get_3d_max_distance() const {
audio_debug("MilesAudioSample::get_3d_max_distance() ");
if(_sample != 0) {
float max_dist;
AIL_sample_3D_distances(_sample, &max_dist, nullptr, nullptr);
return (PN_stdfloat)max_dist;
} else {
audio_warning("_sample == 0 in MilesAudioSample::get_3d_max_distance().");
return -1.0;
}
}
/**
* Get the level of a particular logical channel (speaker). "index" specifies
* which speaker in an array of all the logical channels currently in use to
* retrieve the level of.
*
* For instance, in a standard 4.0 channel setup, speakers are setup as
* [frontLeft, frontRight, backLeft, backRight]. Thus, get_speaker_level(2)
* will retrieve the level of the backLeft speaker.
*
* The order in which speakers appear in the array for standard speaker setups
* is defined to be:
*
* FRONT_LEFT FRONT_RIGHT FRONT_CENTER LOW_FREQUENCY (sub woofer) BACK_LEFT
* BACK_RIGHT FRONT_LEFT_OF_CENTER FRONT_RIGHT_OF_CENTER BACK_CENTER SIDE_LEFT
* SIDE_RIGHT TOP_CENTER TOP_FRONT_LEFT TOP_FRONT_CENTER TOP_FRONT_RIGHT
* TOP_BACK_LEFT TOP_BACK_CENTER TOP_BACK_RIGHT
*
*/
PN_stdfloat MilesAudioSample::
get_speaker_level(int index) {
audio_debug("MilesAudioSample::get_speaker_level(" << index << ")");
if(_sample != 0) {
int numLevels;
float *levels = AIL_sample_channel_levels(_sample, &numLevels);
if(index < numLevels) {
return (PN_stdfloat)levels[index];
} else {
audio_error("index out of range in MilesAudioSample::get_speaker_level. numLevels: " << numLevels);
return -1.0;
}
} else {
audio_warning("Warning: MilesAudioSample::get_speaker_level only works for sounds that are currently playing");
return -1.0;
}
}
/**
* Set the output levels on the logical channels (speakers) for this sound.
* Values should be in the range 0.0 to 1.0. Levels for up to nine channels
* may be specified. As soon as a level is reached that falls outside the
* range 0.0 to 1.0, the levels specified up to that point will be sent and
* all other levels will be ignored.
*
* The user must know what the current speaker setup is in order to know which
* level corresponds to which speaker.
*
* This method will have no effect if 3D attributes have been set for this
* sound.
*
* The order in which speakers appear in the array for standard speaker setups
* is defined to be:
*
* FRONT_LEFT FRONT_RIGHT FRONT_CENTER LOW_FREQUENCY (sub woofer) BACK_LEFT
* BACK_RIGHT FRONT_LEFT_OF_CENTER FRONT_RIGHT_OF_CENTER BACK_CENTER SIDE_LEFT
* SIDE_RIGHT TOP_CENTER TOP_FRONT_LEFT TOP_FRONT_CENTER TOP_FRONT_RIGHT
* TOP_BACK_LEFT TOP_BACK_CENTER TOP_BACK_RIGHT
*
*/
void MilesAudioSample::
set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2, PN_stdfloat level3, PN_stdfloat level4, PN_stdfloat level5, PN_stdfloat level6, PN_stdfloat level7, PN_stdfloat level8, PN_stdfloat level9) {
audio_debug("MilesAudioSample::set_speaker_levels()");
if(_sample != 0) {
float levels[9] = {level1, level2, level3, level4, level5, level6, level7, level8, level9};
if((level1 < 0.0) || (level1 > 1.0)) {
audio_error("No valid levels specified in MilesAudioSample::set_speaker_levels().");
} else if((level2 < 0.0) || (level2 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 1);
} else if((level3 < 0.0) || (level3 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 2);
} else if((level4 < 0.0) || (level4 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 3);
} else if((level5 < 0.0) || (level5 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 4);
} else if((level6 < 0.0) || (level6 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 5);
} else if((level7 < 0.0) || (level7 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 6);
} else if((level8 < 0.0) || (level8 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 7);
} else if((level9 < 0.0) || (level9 > 1.0)) {
AIL_set_sample_channel_levels(_sample, levels, 8);
} else {
AIL_set_sample_channel_levels(_sample, levels, 9);
}
} else {
audio_warning("Warning: MilesAudioSample::set_speaker_levels only works for sounds that are currently playing");
}
}
/**
* 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;
}
/**
* This callback is made by Miles (possibly in a sub-thread) when the sample
* finishes.
*/
void AILCALLBACK MilesAudioSample::
finish_callback(HSAMPLE sample) {
MilesAudioSample *self = (MilesAudioSample *)AIL_sample_user_data(sample, 0);
if (milesAudio_cat.is_debug()) {
milesAudio_cat.debug()
<< "finished " << *self << "\n";
}
if (self->_manager == nullptr) {
return;
}
self->_manager->_sounds_finished = true;
}
/**
* Sets the start time of an already allocated sample.
*/
void MilesAudioSample::
do_set_time(PN_stdfloat time) {
miles_audio_debug("do_set_time(time="<<time<<")");
nassertv(_sample != 0);
// Ensure we don't inadvertently run off the end of the sound.
PN_stdfloat 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);
}
#endif //]

View File

@ -1,103 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSample.h
* @author skyler
* @date 2001-06-06
* Prior system by: cary
*/
#ifndef MILESAUDIOSAMPLE_H
#define MILESAUDIOSAMPLE_H
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "milesAudioSound.h"
#include "milesAudioManager.h"
#include <mss.h>
/**
* 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 std::string &file_name);
public:
virtual ~MilesAudioSample();
virtual void play();
virtual void stop();
virtual PN_stdfloat get_time() const;
virtual void set_volume(PN_stdfloat volume=1.0f);
virtual void set_balance(PN_stdfloat balance_right=0.0f);
virtual void set_play_rate(PN_stdfloat play_rate=1.0f);
virtual PN_stdfloat length() const;
virtual AudioSound::SoundStatus status() const;
virtual void cleanup();
virtual void output(std::ostream &out) const;
// 3D spatialized sound support. Spatialized sound was originally added for
// FMOD, so there are parts of the interface in the Miles implementation
// that are a little more awkward than they would be otherwise.
void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz);
void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz);
void set_3d_min_distance(PN_stdfloat dist);
PN_stdfloat get_3d_min_distance() const;
void set_3d_max_distance(PN_stdfloat dist);
PN_stdfloat get_3d_max_distance() const;
virtual PN_stdfloat get_speaker_level(int index);
virtual void set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2=-1.0f, PN_stdfloat level3=-1.0f, PN_stdfloat level4=-1.0f, PN_stdfloat level5=-1.0f, PN_stdfloat level6=-1.0f, PN_stdfloat level7=-1.0f, PN_stdfloat level8=-1.0f, PN_stdfloat level9=-1.0f);
private:
void internal_stop();
static void AILCALLBACK finish_callback(HSAMPLE sample);
void do_set_time(PN_stdfloat time);
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 */

View File

@ -1,12 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSequence.I
* @author drose
* @date 2007-07-31
*/

View File

@ -1,331 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSequence.cxx
* @author drose
* @date 2007-07-31
*/
#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 //]
/**
* This constructor is called only by the MilesAudioManager.
*/
MilesAudioSequence::
MilesAudioSequence(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
const std::string &file_name) :
MilesAudioSound(manager, file_name),
_sd(sd)
{
nassertv(sd != nullptr);
audio_debug("MilesAudioSequence(manager=0x"<<(void*)&manager
<<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
_sequence = 0;
_sequence_index = 0;
}
/**
*
*/
MilesAudioSequence::
~MilesAudioSequence() {
miles_audio_debug("~MilesAudioSequence()");
cleanup();
_manager->release_sound(this);
miles_audio_debug("~MilesAudioSequence() done");
}
/**
*
*/
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);
AIL_set_sequence_user_data(_sequence, 0, (SINTa)this);
AIL_register_sequence_callback(_sequence, finish_callback);
set_volume(_volume);
set_play_rate(_play_rate);
AIL_set_sequence_loop_count(_sequence, _loop_count);
if (_got_start_time) {
do_set_time(_start_time);
AIL_resume_sequence(_sequence);
} else {
AIL_start_sequence(_sequence);
}
}
_got_start_time = false;
}
} else {
// In case _loop_count gets set to forever (zero):
audio_debug(" paused "<<_file_name );
_paused = true;
}
}
/**
*
*/
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 cddvd 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;
}
}
/**
*
*/
PN_stdfloat MilesAudioSequence::
get_time() const {
if (_sequence == 0) {
if (_got_start_time) {
return _start_time;
}
return 0.0f;
}
S32 current_ms;
AIL_sequence_ms_position(_sequence, nullptr, &current_ms);
PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
return time;
}
/**
*
*/
void MilesAudioSequence::
set_volume(PN_stdfloat 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 = std::min(milesVolume, 127);
milesVolume = std::max(milesVolume, 0);
AIL_set_sequence_volume(_sequence, milesVolume, 0);
}
}
/**
*
*/
void MilesAudioSequence::
set_balance(PN_stdfloat balance_right) {
miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
_balance = balance_right;
// Balance has no effect on a MIDI file.
}
/**
*
*/
void MilesAudioSequence::
set_play_rate(PN_stdfloat 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);
}
}
/**
*
*/
PN_stdfloat MilesAudioSequence::
length() const {
if (_sequence == 0) {
// The MIDI file hasn't been started yet. See if the length is cached in
// the SoundData.
if (!_sd->_has_length) {
// It isn't cached, so load the sequence temporarily to determine its
// length.
((MilesAudioSequence *)this)->determine_length();
}
return _sd->get_length();
}
// The MIDI file has already been started, so we can ask it directly.
S32 length_ms;
AIL_sequence_ms_position(_sequence, &length_ms, nullptr);
PN_stdfloat time = (PN_stdfloat)length_ms * 0.001f;
return time;
}
/**
*
*/
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;
}
}
/**
* 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();
}
/**
* 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;
}
/**
* This callback is made by Miles (possibly in a sub-thread) when the sequence
* finishes.
*/
void AILCALLBACK MilesAudioSequence::
finish_callback(HSEQUENCE sequence) {
MilesAudioSequence *self = (MilesAudioSequence *)AIL_sequence_user_data(sequence, 0);
if (milesAudio_cat.is_debug()) {
milesAudio_cat.debug()
<< "finished " << *self << "\n";
}
self->_manager->_sounds_finished = true;
}
/**
* Sets the start time of an already allocated stream.
*/
void MilesAudioSequence::
do_set_time(PN_stdfloat time) {
miles_audio_debug("do_set_time(time="<<time<<")");
nassertv(_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, nullptr);
time_ms = std::min(time_ms, length_ms);
AIL_set_sequence_ms_position(_sequence, time_ms);
}
/**
* Temporarily loads the sequence to determine its length. Stores the result
* on the _sd.
*/
void MilesAudioSequence::
determine_length() {
nassertv(_sequence == 0);
GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
if (!mgr->get_sequence(_sequence, _sequence_index, this)){
milesAudio_cat.warning()
<< "Could not determine length of " << _file_name << ": too many open sequences\n";
_sequence = 0;
} else {
AIL_init_sequence(_sequence, &_sd->_raw_data[0], 0);
S32 length_ms;
AIL_sequence_ms_position(_sequence, &length_ms, nullptr);
PN_stdfloat time = (PN_stdfloat)length_ms * 0.001f;
mgr->release_sequence(_sequence_index, this);
_sequence = 0;
_sequence_index = 0;
_sd->set_length(time);
}
}
#endif //]

View File

@ -1,88 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSequence.h
* @author drose
* @date 2007-07-31
*/
#ifndef MILESAUDIOSEQUENCE_H
#define MILESAUDIOSEQUENCE_H
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "milesAudioSound.h"
#include "milesAudioManager.h"
#include <mss.h>
/**
* 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 std::string &file_name);
public:
virtual ~MilesAudioSequence();
virtual void play();
virtual void stop();
virtual PN_stdfloat get_time() const;
virtual void set_volume(PN_stdfloat volume=1.0f);
virtual void set_balance(PN_stdfloat balance_right=0.0f);
virtual void set_play_rate(PN_stdfloat play_rate=1.0f);
virtual PN_stdfloat length() const;
virtual AudioSound::SoundStatus status() const;
virtual void cleanup();
private:
void internal_stop();
static void AILCALLBACK finish_callback(HSEQUENCE sequence);
void do_set_time(PN_stdfloat time);
void determine_length();
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 */

View File

@ -1,12 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSound.I
* @author drose
* @date 2007-07-30
*/

View File

@ -1,205 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSound.cxx
* @author drose
* @date 2007-07-30
*/
#include "milesAudioSound.h"
#ifdef HAVE_RAD_MSS //[
#include "milesAudioManager.h"
using std::string;
TypeHandle MilesAudioSound::_type_handle;
#undef miles_audio_debug
#ifndef NDEBUG //[
#define miles_audio_debug(x) \
audio_debug("MilesAudioSound \""<<get_name()<<"\" "<< x )
#else //][
#define miles_audio_debug(x) ((void)0)
#endif //]
/**
*
*/
MilesAudioSound::
MilesAudioSound(MilesAudioManager *manager,
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),
_start_time(0.0f),
_got_start_time(false)
{
nassertv(!file_name.empty());
}
/**
*
*/
void MilesAudioSound::
set_loop(bool loop) {
// loop count of 0 means always loop
set_loop_count((loop)?0:1);
}
/**
*
*/
bool MilesAudioSound::
get_loop() const {
return (_loop_count == 0);
}
/**
*
*/
void MilesAudioSound::
set_loop_count(unsigned long loop_count) {
if (_loop_count != loop_count) {
_loop_count = loop_count;
if (status() == PLAYING) {
// hack: For now, the loop count is picked up when the sound starts
// playing. There may be a way to change the loop count of a playing
// sound, but I'm going to focus on other things. If you would like to
// change the 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.
play();
}
}
}
/**
*
*/
unsigned long MilesAudioSound::
get_loop_count() const {
return _loop_count;
}
/**
*
*/
PN_stdfloat MilesAudioSound::
get_volume() const {
return _volume;
}
/**
*
*/
PN_stdfloat MilesAudioSound::
get_balance() const {
return _balance;
}
/**
*
*/
PN_stdfloat MilesAudioSound::
get_play_rate() const {
return _play_rate;
}
/**
*
*/
void MilesAudioSound::
set_time(PN_stdfloat time) {
miles_audio_debug("set_time(time="<<time<<")");
// Mark this position for the next play().
_start_time = time;
_got_start_time = true;
}
/**
*
*/
void MilesAudioSound::
set_active(bool active) {
if (_manager == nullptr) {
return;
}
miles_audio_debug("set_active(active="<<active<<")");
if (_active != active) {
_active = active;
if (_active) {
// ...activate the sound.
if (_paused && _loop_count==0) {
// ...this sound was looping when it was paused.
_paused = false;
play();
}
} else {
// ...deactivate the sound.
if (status() == PLAYING) {
if (_loop_count == 0) {
// ...we're pausing a looping sound.
_paused = true;
}
_start_time = get_time();
_got_start_time = true;
stop();
}
}
}
}
/**
*
*/
bool MilesAudioSound::
get_active() const {
return _active;
}
/**
* This is no longer implemented.
*/
void MilesAudioSound::
set_finished_event(const string &event) {
_finished_event = event;
}
/**
* This is no longer implemented.
*/
const string &MilesAudioSound::
get_finished_event() const {
return _finished_event;
}
/**
*
*/
const string &MilesAudioSound::
get_name() const {
return _file_name;
}
/**
* 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() {
}
#endif //]

View File

@ -1,107 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioSound.h
* @author drose
* @date 2007-07-30
*/
#ifndef MILESAUDIOSOUND_H
#define MILESAUDIOSOUND_H
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "audioSound.h"
#include "milesAudioManager.h"
#include <mss.h>
/**
* The base class for both MilesAudioStream and MilesAudioSample.
*/
class EXPCL_MILES_AUDIO MilesAudioSound : public AudioSound {
protected:
MilesAudioSound(MilesAudioManager *manager, const std::string &file_name);
public:
virtual void set_loop(bool loop=true);
virtual bool get_loop() const;
virtual void set_loop_count(unsigned long loop_count=1);
virtual unsigned long get_loop_count() const;
virtual PN_stdfloat get_volume() const;
virtual PN_stdfloat get_balance() const;
virtual PN_stdfloat get_play_rate() const;
virtual void set_time(PN_stdfloat start_time=0.0);
virtual void set_active(bool active=true);
virtual bool get_active() const;
virtual void set_finished_event(const std::string &event);
virtual const std::string &get_finished_event() const;
virtual const std::string &get_name() const;
virtual void cleanup();
protected:
PT(MilesAudioManager) _manager;
std::string _file_name;
PN_stdfloat _volume; // 0..1.0
PN_stdfloat _balance; // -1..1
PN_stdfloat _play_rate; // 0..1.0
unsigned long _loop_count;
// _active is for things like a 'turn off sound effects' in a preferences
// pannel. _active is not about whether a sound is currently playing. Use
// status() for info on whether the sound is playing.
bool _active;
// _paused is not like the Pause button on a cddvd player. It is used as a
// flag to say that the sound was looping when it was set inactive.
bool _paused;
// 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.
std::string _finished_event;
// This is set whenever we call set_time(). Calling play() will respect
// this if it is set, and then reset it.
PN_stdfloat _start_time;
bool _got_start_time;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
AudioSound::init_type();
register_type(_type_handle, "MilesAudioSound",
AudioSound::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 "milesAudioSound.I"
#endif //]
#endif

View File

@ -1,12 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioStream.I
* @author drose
* @date 2007-07-26
*/

View File

@ -1,310 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioStream.cxx
* @author drose
* @date 2007-07-26
*/
#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 //]
/**
*
*/
MilesAudioStream::
MilesAudioStream(MilesAudioManager *manager, const std::string &file_name,
const Filename &path) :
MilesAudioSound(manager, file_name),
_path(path)
{
_stream = 0;
_got_length = false;
}
/**
*
*/
MilesAudioStream::
~MilesAudioStream() {
miles_audio_debug("~MilesAudioStream()");
cleanup();
miles_audio_debug("~MilesAudioStream() done");
}
/**
*
*/
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);
if (_stream == 0) {
milesAudio_cat.warning()
<< "Could not play " << _file_name << ": too many open streams\n";
return;
}
AIL_set_stream_user_data(_stream, 0, (SINTa)this);
AIL_register_stream_callback(_stream, finish_callback);
} else {
// We already had the stream open. Keep it open; just restart it.
AIL_pause_stream(_stream, 1);
_manager->stop_service_stream(_stream);
}
// Start playing:
nassertv(_stream != 0);
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);
AIL_start_stream(_stream);
if (_got_start_time) {
// There's no AIL_resume_stream(), so we start in the middle by starting
// normally, then immediately skipping to the middle.
do_set_time(_start_time);
}
if (miles_audio_panda_threads) {
AIL_auto_service_stream(_stream, 0);
_manager->start_service_stream(_stream);
} else {
AIL_auto_service_stream(_stream, 1);
}
_got_start_time = false;
} else {
// In case _loop_count gets set to forever (zero):
audio_debug(" paused "<<_file_name );
_paused = true;
}
}
/**
*
*/
void MilesAudioStream::
stop() {
if (_manager == nullptr) {
return;
}
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 cddvd 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;
}
}
/**
*
*/
PN_stdfloat MilesAudioStream::
get_time() const {
if (_stream == 0) {
if (_got_start_time) {
return _start_time;
}
return 0.0f;
}
S32 current_ms;
AIL_stream_ms_position(_stream, nullptr, &current_ms);
PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
return time;
}
/**
*
*/
void MilesAudioStream::
set_volume(PN_stdfloat 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 = std::min(milesVolume, 1.0f);
milesVolume = std::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);
}
}
/**
*
*/
void MilesAudioStream::
set_balance(PN_stdfloat balance_right) {
_balance = balance_right;
// Call set_volume to effect the change:
set_volume(_volume);
}
/**
*
*/
void MilesAudioStream::
set_play_rate(PN_stdfloat 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 * (PN_stdfloat)_original_playback_rate);
AIL_set_sample_playback_rate(sample, speed);
audio_debug(" play_rate for this wav or mp3 is now " << speed);
}
}
/**
*
*/
PN_stdfloat 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, nullptr);
_length = (PN_stdfloat)length_ms * 0.001f;
_got_length = true;
}
return _length;
}
/**
*
*/
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;
}
}
/**
* Called to release any resources associated with the sound.
*/
void MilesAudioStream::
cleanup() {
if (_stream) {
stop();
}
set_active(false);
nassertv(_stream == 0);
if (_manager != nullptr) {
_manager->release_sound(this);
_manager = nullptr;
}
}
/**
* This callback is made by Miles (possibly in a sub-thread) when the stream
* finishes.
*/
void AILCALLBACK MilesAudioStream::
finish_callback(HSTREAM stream) {
MilesAudioStream *self = (MilesAudioStream *)AIL_stream_user_data(stream, 0);
if (milesAudio_cat.is_debug()) {
milesAudio_cat.debug()
<< "finished " << *self << "\n";
}
if (self->_manager == nullptr) {
return;
}
self->_manager->_sounds_finished = true;
}
/**
* Sets the start time of an already allocated stream.
*/
void MilesAudioStream::
do_set_time(PN_stdfloat time) {
nassertv(_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, nullptr);
time_ms = std::min(time_ms, length_ms);
AIL_set_stream_ms_position(_stream, time_ms);
}
#endif //]

View File

@ -1,87 +0,0 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file milesAudioStream.h
* @author drose
* @date 2007-07-26
*/
#ifndef MILESAUDIOSTREAM_H
#define MILESAUDIOSTREAM_H
#include "pandabase.h"
#ifdef HAVE_RAD_MSS //[
#include "milesAudioSound.h"
#include "milesAudioManager.h"
#include <mss.h>
/**
* 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 std::string &file_name,
const Filename &path);
public:
virtual ~MilesAudioStream();
virtual void play();
virtual void stop();
virtual PN_stdfloat get_time() const;
virtual void set_volume(PN_stdfloat volume=1.0f);
virtual void set_balance(PN_stdfloat balance_right=0.0f);
virtual void set_play_rate(PN_stdfloat play_rate=1.0f);
virtual PN_stdfloat length() const;
virtual AudioSound::SoundStatus status() const;
virtual void cleanup();
private:
static void AILCALLBACK finish_callback(HSTREAM stream);
void do_set_time(PN_stdfloat time);
Filename _path;
HSTREAM _stream;
S32 _original_playback_rate;
mutable PN_stdfloat _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

View File

@ -1,9 +0,0 @@
#include "config_milesAudio.cxx"
#include "milesAudioManager.cxx"
#include "milesAudioSample.cxx"
#include "milesAudioSequence.cxx"
#include "milesAudioSound.cxx"
#include "milesAudioStream.cxx"
#include "globalMilesManager.cxx"

View File

@ -53,14 +53,6 @@
#define EXPTP_FRAMEWORK IMPORT_TEMPL
#endif
#ifdef BUILDING_MILES_AUDIO
#define EXPCL_MILES_AUDIO EXPORT_CLASS
#define EXPTP_MILES_AUDIO EXPORT_TEMPL
#else
#define EXPCL_MILES_AUDIO IMPORT_CLASS
#define EXPTP_MILES_AUDIO IMPORT_TEMPL
#endif
#ifdef BUILDING_OPENAL_AUDIO
#define EXPCL_OPENAL_AUDIO EXPORT_CLASS
#define EXPTP_OPENAL_AUDIO EXPORT_TEMPL