Improvements to audio and creation of UserDataAudio

This commit is contained in:
Josh Yelon 2008-03-31 05:51:11 +00:00
parent 972f0c50e7
commit 03715468ca
24 changed files with 543 additions and 57 deletions

View File

@ -23,6 +23,7 @@
#include "config_audio.h"
#include "audioSound.h"
#include "filterProperties.h"
#include "movieAudio.h"
typedef PT(AudioManager) Create_AudioManager_proc();
@ -59,6 +60,12 @@ PUBLISHED:
SPK_COUNT,
};
enum StreamMode {
SM_heuristic,
SM_sample,
SM_stream,
};
virtual int getSpeakerSetup();
virtual void setSpeakerSetup(SpeakerModeCategory cat);
virtual bool configure_filters(FilterProperties *config);
@ -86,7 +93,8 @@ PUBLISHED:
virtual bool is_valid() = 0;
// Get a sound:
virtual PT(AudioSound) get_sound(const string& file_name, bool positional = false) = 0;
virtual PT(AudioSound) get_sound(const string& file_name, bool positional = false, int mode=SM_heuristic) = 0;
virtual PT(AudioSound) get_sound(MovieAudio *source, bool positional = false, int mode=SM_heuristic) = 0;
PT(AudioSound) get_null_sound();

View File

@ -75,6 +75,14 @@ ConfigVariableDouble audio_buffering_seconds
"correctness over efficiency, but for a commercial application "
"you may wish to lower this."));
ConfigVariableInt audio_preload_threshold
("audio-preload-threshold", 1000000,
PRC_DESC("If the decompressed size of a sound file exceeds this amount, "
"then Panda3D will not attempt to store that sound file in RAM. "
"Instead, it will stream the sound file from disk. It is not "
"practical to stream multiple sound-files from disk at the same "
"time - the hard drive seek time makes it stutter."));
// Unknown
ConfigVariableInt audio_min_hw_channels

View File

@ -48,10 +48,11 @@ extern EXPCL_PANDA_AUDIO ConfigVariableBool fmod_use_surround_sound;
// Config vars for OpenAL:
extern EXPCL_PANDA ConfigVariableDouble audio_doppler_factor;
extern EXPCL_PANDA ConfigVariableDouble audio_distance_factor;
extern EXPCL_PANDA ConfigVariableDouble audio_drop_off_factor;
extern EXPCL_PANDA ConfigVariableDouble audio_buffering_seconds;
extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_doppler_factor;
extern EXPCL_PANDA_AUDIO ConfigVariableDouble audio_distance_factor;
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:

View File

@ -63,7 +63,17 @@ is_valid() {
// Description:
////////////////////////////////////////////////////////////////////
PT(AudioSound) NullAudioManager::
get_sound(const string&, bool positional) {
get_sound(const string&, bool positional, int mode) {
return get_null_sound();
}
////////////////////////////////////////////////////////////////////
// Function: NullAudioManager::get_sound
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PT(AudioSound) NullAudioManager::
get_sound(MovieAudio *sound, bool positional, int mode) {
return get_null_sound();
}

View File

@ -34,7 +34,8 @@ public:
virtual bool is_valid();
virtual PT(AudioSound) get_sound(const string&, bool positional = false);
virtual PT(AudioSound) get_sound(const string&, 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 string&);
virtual void clear_cache();
virtual void set_cache_limit(unsigned int);

View File

@ -402,12 +402,12 @@ configure_filters(FilterProperties *config) {
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::get_sound()
// Function: FmodAudioManager::get_sound
// Access: Public
// Description: This is what creates a sound instance.
////////////////////////////////////////////////////////////////////
PT(AudioSound) FmodAudioManager::
get_sound(const string &file_name, bool positional) {
get_sound(const string &file_name, bool positional, int) {
//Needed so People use Panda's Generic UNIX Style Paths for Filename.
//path.to_os_specific() converts it back to the proper OS version later on.
@ -428,6 +428,16 @@ get_sound(const string &file_name, bool positional) {
return audioSound;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::get_sound
// Access: Public
// Description: This is what creates a sound instance.
////////////////////////////////////////////////////////////////////
PT(AudioSound) FmodAudioManager::
get_sound(MovieAudio *source, bool positional, int) {
nassert_raise("FMOD audio manager does not support MovieAudio sources");
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: FmodAudioManager::getSpeakerSetup()

View File

@ -103,7 +103,8 @@ class EXPCL_FMOD_AUDIO FmodAudioManager : public AudioManager {
virtual bool is_valid();
virtual PT(AudioSound) get_sound(const string&, bool positional = false);
virtual PT(AudioSound) get_sound(const string&, bool positional = false, int mode=SM_heuristic);
virtual PT(AudioSound) get_sound(MovieAudio *, bool positional = false, int mode=SM_heuristic);
virtual int getSpeakerSetup();
virtual void setSpeakerSetup(SpeakerModeCategory cat);

View File

@ -139,7 +139,7 @@ is_valid() {
// Description:
////////////////////////////////////////////////////////////////////
PT(AudioSound) MilesAudioManager::
get_sound(const string &file_name, bool) {
get_sound(const string &file_name, bool, int) {
ReMutexHolder holder(_lock);
audio_debug("MilesAudioManager::get_sound(file_name=\""<<file_name<<"\")");
@ -223,6 +223,17 @@ get_sound(const string &file_name, bool) {
return audioSound;
}
////////////////////////////////////////////////////////////////////
// Function: MilesAudioManager::get_sound
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
PT(AudioSound) MilesAudioManager::
get_sound(MovieAudio *sound, bool, int) {
nassert_raise("Miles audio manager does not support MovieAudio sources.");
return NULL;
}
////////////////////////////////////////////////////////////////////
// Function: MilesAudioManager::uncache_sound
// Access: Public, Virtual

View File

@ -47,7 +47,8 @@ public:
virtual bool is_valid();
virtual PT(AudioSound) get_sound(const string &file_name, bool positional = false);
virtual PT(AudioSound) get_sound(const string &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 string &file_name);
virtual void clear_cache();
virtual void set_cache_limit(unsigned int count);

View File

@ -244,13 +244,13 @@ can_load_audio(MovieAudioCursor *source) {
if (source->get_source()->get_filename().empty()) {
return false;
}
if (source->length() > 60.0) {
if ((source->length() > 3600.0)||(source->ready() != 0x40000000)) {
return false;
}
int channels = source->audio_channels();
int samples = (int)(source->length() * source->audio_rate());
int bytes = samples * channels * 2;
if (bytes > 200000) {
if (bytes > audio_preload_threshold) {
return false;
}
return true;
@ -344,12 +344,30 @@ get_sound_data(MovieAudio *movie) {
}
////////////////////////////////////////////////////////////////////
// Function: OpenALAudioManager::get_sound()
// Function: OpenALAudioManager::get_sound
// Access: Public
// Description: This is what creates a sound instance.
////////////////////////////////////////////////////////////////////
PT(AudioSound) OpenALAudioManager::
get_sound(const string &file_name, bool positional) {
get_sound(MovieAudio *sound, bool positional, int mode) {
if(!is_valid()) {
return get_null_sound();
}
PT(OpenALAudioSound) oas =
new OpenALAudioSound(this, sound, positional);
_all_sounds.insert(oas);
PT(AudioSound) res = (AudioSound*)(OpenALAudioSound*)oas;
return res;
}
////////////////////////////////////////////////////////////////////
// Function: OpenALAudioManager::get_sound
// Access: Public
// Description: This is what creates a sound instance.
////////////////////////////////////////////////////////////////////
PT(AudioSound) OpenALAudioManager::
get_sound(const string &file_name, bool positional, int mode) {
if(!is_valid()) {
return get_null_sound();
}
@ -844,7 +862,7 @@ update() {
sound->push_fresh_buffers();
sound->restart_stalled_audio();
sound->cache_time(rtc);
if (sound->status()!=AudioSound::PLAYING) {
if ((sound->_source == 0)||(sound->_loops_completed >= sound->_playing_loops)) {
sounds_finished.insert(*i);
}
}

View File

@ -53,7 +53,8 @@ class EXPCL_OPENAL_AUDIO OpenALAudioManager : public AudioManager {
virtual bool is_valid();
virtual PT(AudioSound) get_sound(const string&, bool positional = false);
virtual PT(AudioSound) get_sound(const string&, 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 string&);
virtual void clear_cache();
@ -173,7 +174,7 @@ private:
typedef phash_map<string, SoundData *> SampleCache;
SampleCache _sample_cache;
typedef phash_set<OpenALAudioSound *> SoundsPlaying;
typedef phash_set<PT(OpenALAudioSound)> SoundsPlaying;
SoundsPlaying _sounds_playing;
typedef phash_set<OpenALAudioSound *> AllSounds;

View File

@ -316,7 +316,7 @@ restart_stalled_audio() {
// Description: Pushes a buffer into the source queue.
////////////////////////////////////////////////////////////////////
void OpenALAudioSound::
queue_buffer(ALuint buffer, int loop_index, double time_offset) {
queue_buffer(ALuint buffer, int samples, int loop_index, double time_offset) {
// Now push the buffer into the stream queue.
alGetError();
alSourceQueueBuffers(_source,1,&buffer);
@ -328,10 +328,10 @@ queue_buffer(ALuint buffer, int loop_index, double time_offset) {
}
QueuedBuffer buf;
buf._buffer = buffer;
buf._samples = samples;
buf._loop_index = loop_index;
buf._time_offset = time_offset;
_stream_queued.push_back(buf);
// audio_debug("Buffer queued " << loop_index << " " << time_offset);
}
////////////////////////////////////////////////////////////////////
@ -394,9 +394,18 @@ read_stream_data(int bytelen, unsigned char *buffer) {
cursor->seek(0.0);
continue;
}
if (_sd->_stream->ready() == 0) {
if (_sd->_stream->aborted()) {
_loops_completed = _playing_loops;
}
return fill;
}
if (samples > space) {
samples = space;
}
if (samples > _sd->_stream->ready()) {
samples = _sd->_stream->ready();
}
cursor->read_samples(samples, (PN_int16 *)buffer);
size_t hval = AddHash::add_hash(0, (PN_uint8*)buffer, samples*channels*2);
audio_debug("Streaming " << cursor->get_source()->get_filename().get_basename() << " at " << t << " hash " << hval);
@ -490,23 +499,21 @@ push_fresh_buffers() {
if (_sd->_sample) {
while ((_loops_completed < _playing_loops) &&
(_stream_queued.size() < 100)) {
queue_buffer(_sd->_sample, _loops_completed, 0.0);
queue_buffer(_sd->_sample, 0,_loops_completed, 0.0);
_loops_completed += 1;
}
} else {
MovieAudioCursor *cursor = _sd->_stream;
int channels = cursor->audio_channels();
int rate = cursor->audio_rate();
double space = 65536 / (channels * 2);
// Calculate how many buffers to keep in the queue.
int fill_to = (int)((audio_buffering_seconds * rate) / space) + 1;
if (fill_to < 3) {
fill_to = 3;
int fill = 0;
for (int i=0; i<_stream_queued.size(); i++) {
fill += _stream_queued[i]._samples;
}
while ((_loops_completed < _playing_loops) &&
(((int)(_stream_queued.size())) < fill_to)) {
(fill < (int)(audio_buffering_seconds * rate * channels))) {
int loop_index = _loops_completed;
double time_offset = cursor->tell();
int samples = read_stream_data(65536, data);
@ -515,8 +522,9 @@ push_fresh_buffers() {
}
ALuint buffer = make_buffer(samples, channels, rate, data);
if (_manager == 0) return;
queue_buffer(buffer, loop_index, time_offset);
queue_buffer(buffer, samples, loop_index, time_offset);
if (_manager == 0) return;
fill += samples;
}
}
}
@ -866,17 +874,14 @@ get_name() const {
// Description: Get status of the sound.
//
// This returns the status as of the
// last AudioManager::update.
// last push_fresh_buffers
////////////////////////////////////////////////////////////////////
AudioSound::SoundStatus OpenALAudioSound::
status() const {
if (_source==0) {
return AudioSound::READY;
}
_manager->make_current();
if (_stream_queued.size() == 0) {
if (_loops_completed >= _playing_loops) {
return AudioSound::READY;
} else {
return AudioSound::PLAYING;

View File

@ -125,7 +125,7 @@ private:
void restart_stalled_audio();
void delete_queued_buffers();
ALuint make_buffer(int samples, int channels, int rate, unsigned char *data);
void queue_buffer(ALuint buffer, int loop_index, double time_offset);
void queue_buffer(ALuint buffer, int samples, int loop_index, double time_offset);
int read_stream_data(int bytelen, unsigned char *data);
void pull_used_buffers();
void push_fresh_buffers();
@ -139,6 +139,7 @@ private:
struct QueuedBuffer {
ALuint _buffer;
int _samples;
int _loop_index;
double _time_offset;
};

View File

@ -53,6 +53,8 @@ init_libmovies() {
MovieAudioCursor::init_type();
InkblotVideo::init_type();
InkblotVideoCursor::init_type();
UserDataAudio::init_type();
UserDataAudioCursor::init_type();
WebcamVideo::init_type();
#ifdef HAVE_FFMPEG
FfmpegVideo::init_type();

View File

@ -50,39 +50,64 @@ audio_channels() const {
////////////////////////////////////////////////////////////////////
// Function: MovieAudioCursor::length
// Access: Public
// Description: Returns the length of the movie.
// Description: Returns the length of the movie. Attempting to read
// audio samples beyond the specified length will produce
// silent samples.
//
// Some kinds of Movie, such as internet TV station,
// might not have a predictable length. In that case,
// the length will be set to a very large number: 1.0E10.
// If the internet TV station goes offline, the video
// or audio stream will set its abort flag. Reaching the
// end of the movie (ie, the specified length) normally
// does not cause the abort flag to be set.
//
// The video and audio streams produced by get_video and
// get_audio are always of unlimited duration - you can
// always read another video frame or another audio
// sample. This is true even if the specified length
// is reached, or an abort is flagged. If either stream
// runs out of data, it will synthesize blank video
// frames and silent audio samples as necessary to
// satisfy read requests.
//
// Some AVI files have incorrect length values encoded
// into them - usually, they're a second or two long or
// into them - they may be a second or two long or
// short. When playing such an AVI using the Movie class,
// you may see a slightly truncated video, or a slightly
// elongated video (padded with black frames). There are
// utilities out there to fix the length values in AVI
// files.
//
// An audio consumer needs to check the length, the
// ready status, and the aborted flag.
////////////////////////////////////////////////////////////////////
INLINE double MovieAudioCursor::
length() const {
return _length;
}
////////////////////////////////////////////////////////////////////
// Function: MovieAudioCursor::ready
// Access: Public
// Description: Returns the number of audio samples that are ready
// to read. This is primarily relevant for sources like
// microphones which produce samples at a fixed rate.
// If you try to read more samples than are ready, the
// result will be silent samples.
//
// Some audio streams do not have a limit on how fast
// they can produce samples. Such streams will always
// return 0x40000000 as the ready-count. This may well
// exceed the length of the audio stream. You therefore
// need to check length separately.
//
// If the aborted flag is set, that means the ready count
// is no longer being replenished. For example, a
// MovieAudioCursor might be reading from an internet
// radio station, and it might buffer data to avoid
// underruns. If it loses connection to the radio
// station, it will set the aborted flag to indicate that
// the buffer is no longer being replenished. But it is
// still ok to read the samples that are in the buffer,
// at least until they run out. Once those are gone,
// there will be no more.
//
// An audio consumer needs to check the length, the
// ready status, and the aborted flag.
////////////////////////////////////////////////////////////////////
INLINE int MovieAudioCursor::
ready() const {
return _ready;
}
////////////////////////////////////////////////////////////////////
// Function: MovieAudioCursor::can_seek
// Access: Public
@ -113,11 +138,9 @@ can_seek_fast() const {
////////////////////////////////////////////////////////////////////
// Function: MovieAudioCursor::aborted
// Access: Public
// Description: Returns true if the audio has aborted prematurely.
// For example, this could occur if the Movie was actually
// an internet TV station, and the connection was lost.
// Reaching the normal end of the audio does not
// constitute an 'abort' condition.
// Description: If aborted is true, it means that the "ready" samples
// are not being replenished. See the method "ready"
// for an explanation.
////////////////////////////////////////////////////////////////////
INLINE bool MovieAudioCursor::
aborted() const {

View File

@ -36,6 +36,7 @@ MovieAudioCursor(MovieAudio *src) :
_length(1.0E10),
_can_seek(true),
_can_seek_fast(true),
_ready(0x40000000),
_aborted(false),
_samples_read(0)
{

View File

@ -53,6 +53,7 @@ PUBLISHED:
INLINE bool aborted() const;
INLINE double tell() const;
INLINE void skip_samples(int n);
INLINE int ready() const;
virtual void seek(double offset);
public:
@ -62,6 +63,7 @@ protected:
PT(MovieAudio) _source;
int _audio_rate;
int _audio_channels;
int _ready;
double _length;
bool _can_seek;
bool _can_seek_fast;

View File

@ -15,6 +15,9 @@
#include "ffmpegVirtualFile.cxx"
#include "userDataAudio.cxx"
#include "userDataAudioCursor.cxx"
#include "webcamVideo.cxx"
#include "webcamVideoDS.cxx"

View File

@ -0,0 +1,18 @@
// Filename: userDataAudio.I
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,144 @@
// Filename: userDataAudio.cxx
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2007, 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 "userDataAudio.h"
#include "userDataAudioCursor.h"
TypeHandle UserDataAudio::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::Constructor
// Access: Public
// Description: This constructor returns a UserDataAudio ---
// a means to supply raw audio samples manually.
////////////////////////////////////////////////////////////////////
UserDataAudio::
UserDataAudio(int rate, int channels) :
MovieAudio("User Data Audio"),
_desired_rate(rate),
_desired_channels(channels),
_aborted(false),
_cursor(NULL)
{
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
UserDataAudio::
~UserDataAudio() {
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::update_cursor
// Access: Private
// Description: Make sure that the UserDataAudioCursor's ready
// and aborted status flags are correct.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
update_cursor() {
if (_cursor == 0) return;
_cursor->_ready = _data.size();
_cursor->_aborted = _aborted;
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::open
// Access: Published, Virtual
// Description: Open this audio, returning a UserDataAudioCursor. A
// UserDataAudio can only be opened by one consumer
// at a time.
////////////////////////////////////////////////////////////////////
PT(MovieAudioCursor) UserDataAudio::
open() {
if (_cursor) {
nassert_raise("A UserDataAudio can only be opened by one consumer at a time.");
return NULL;
}
_cursor = new UserDataAudioCursor(this);
update_cursor();
return _cursor;
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::read_samples
// Access: Private
// Description: Read audio samples from the stream. N is the
// number of samples you wish to read. Your buffer
// must be equal in size to N * channels.
// Multiple-channel audio will be interleaved.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
read_samples(int n, PN_int16 *data) {
int nread = n;
if (nread > (int)_data.size()) {
nread = _data.size();
}
for (int i=0; i<nread; i++) {
data[i] = _data[i];
}
for (int i=nread; i<n; i++) {
data[i] = 0;
}
for (int i=0; i<nread; i++) {
_data.pop_front();
}
update_cursor();
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::append
// Access: Published
// Description: Appends audio samples to the buffer.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
append(PN_int16 *data, int len) {
nassertv(!_aborted);
for (int i=0; i<len; i++) {
_data.push_back(data[i]);
}
update_cursor();
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::append
// Access: Published
// Description: Appends audio samples to the buffer.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
append(int val) {
nassertv(!_aborted);
PN_int16 truncated = (PN_int16)val;
nassertv(truncated == val);
_data.push_back(truncated);
update_cursor();
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudio::done
// Access: Published
// Description: Promises not to append any more samples, ie, this
// marks the end of the audio stream.
////////////////////////////////////////////////////////////////////
void UserDataAudio::
done() {
_aborted = true;
update_cursor();
}

View File

@ -0,0 +1,72 @@
// Filename: userDataAudio.h
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// 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 USERDATAAUDIO_H
#define USERDATAAUDIO_H
#include "movieAudio.h"
class MovieAudioCursor;
class UserDataAudioCursor;
////////////////////////////////////////////////////////////////////
// Class : UserDataAudio
// Description : A UserDataAudio is a way for the user to manually
// supply raw audio samples.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_MOVIES UserDataAudio : public MovieAudio {
PUBLISHED:
UserDataAudio(int rate, int channels);
virtual ~UserDataAudio();
virtual PT(MovieAudioCursor) open();
void append(PN_int16 *data, int len);
void append(int value); // Not fast enough, but useful for debugging.
void done(); // A promise not to write any more samples.
private:
void read_samples(int n, PN_int16 *data);
void update_cursor();
int _desired_rate;
int _desired_channels;
UserDataAudioCursor *_cursor;
pdeque<PN_int16> _data;
bool _aborted;
friend class UserDataAudioCursor;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
MovieAudio::init_type();
register_type(_type_handle, "UserDataAudio",
MovieAudio::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;
};
#include "userDataAudio.I"
#endif

View File

@ -0,0 +1,18 @@
// Filename: userDataAudioCursor.I
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// 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 .
//
////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,63 @@
// Filename: userDataAudioCursor.cxx
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) 2001 - 2007, 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 "userDataAudioCursor.h"
TypeHandle UserDataAudioCursor::_type_handle;
////////////////////////////////////////////////////////////////////
// Function: UserDataAudioCursor::Constructor
// Access:
// Description:
////////////////////////////////////////////////////////////////////
UserDataAudioCursor::
UserDataAudioCursor(UserDataAudio *src) :
MovieAudioCursor(src)
{
_audio_rate = src->_desired_rate;
_audio_channels = src->_desired_channels;
_can_seek = false;
_can_seek_fast = false;
_ready = 0;
_aborted = false;
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudioCursor::Destructor
// Access: Public, Virtual
// Description:
////////////////////////////////////////////////////////////////////
UserDataAudioCursor::
~UserDataAudioCursor() {
UserDataAudio *source = (UserDataAudio*)(MovieAudio*)_source;
source->_cursor = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: UserDataAudioCursor::read_samples
// Access: Private
// Description: Read audio samples from the stream. N is the
// number of samples you wish to read. Your buffer
// must be equal in size to N * channels.
// Multiple-channel audio will be interleaved.
////////////////////////////////////////////////////////////////////
void UserDataAudioCursor::
read_samples(int n, PN_int16 *data) {
UserDataAudio *source = (UserDataAudio*)(MovieAudio*)_source;
source->read_samples(n, data);
}

View File

@ -0,0 +1,64 @@
// Filename: userDataAudioCursor.h
// Created by: jyelon (02Jul07)
//
////////////////////////////////////////////////////////////////////
//
// 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 USERDATAAUDIOCURSOR_H
#define USERDATAAUDIOCURSOR_H
#include "pandabase.h"
#include "luse.h"
#include "pointerTo.h"
#include "pointerToArray.h"
class UserDataAudio;
////////////////////////////////////////////////////////////////////
// Class : UserDataAudioCursor
// Description : A UserDataAudioCursor is a means to manually
// supply a sequence of raw audio samples.
////////////////////////////////////////////////////////////////////
class EXPCL_PANDA_MOVIES UserDataAudioCursor : public MovieAudioCursor {
PUBLISHED:
UserDataAudioCursor(UserDataAudio *src);
virtual ~UserDataAudioCursor();
public:
virtual void read_samples(int n, PN_int16 *data);
friend class UserDataAudio;
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
MovieAudioCursor::init_type();
register_type(_type_handle, "UserDataAudioCursor",
MovieAudioCursor::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;
};
#include "userDataAudioCursor.I"
#include "userDataAudio.h"
#endif