mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-02 09:52:27 -04:00
Improvements to audio and creation of UserDataAudio
This commit is contained in:
parent
972f0c50e7
commit
03715468ca
@ -23,6 +23,7 @@
|
||||
#include "config_audio.h"
|
||||
#include "audioSound.h"
|
||||
#include "filterProperties.h"
|
||||
#include "movieAudio.h"
|
||||
|
||||
typedef PT(AudioManager) Create_AudioManager_proc();
|
||||
|
||||
@ -58,6 +59,12 @@ PUBLISHED:
|
||||
SPK_sideright,
|
||||
SPK_COUNT,
|
||||
};
|
||||
|
||||
enum StreamMode {
|
||||
SM_heuristic,
|
||||
SM_sample,
|
||||
SM_stream,
|
||||
};
|
||||
|
||||
virtual int getSpeakerSetup();
|
||||
virtual void setSpeakerSetup(SpeakerModeCategory cat);
|
||||
@ -86,8 +93,9 @@ 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();
|
||||
|
||||
// Tell the AudioManager there is no need to keep this one cached.
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
@ -363,7 +381,7 @@ get_sound(const string &file_name, bool positional) {
|
||||
audio_error("get_sound - invalid filename");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PT(MovieAudio) mva = MovieAudio::get(path);
|
||||
|
||||
PT(OpenALAudioSound) oas =
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -36,6 +36,7 @@ MovieAudioCursor(MovieAudio *src) :
|
||||
_length(1.0E10),
|
||||
_can_seek(true),
|
||||
_can_seek_fast(true),
|
||||
_ready(0x40000000),
|
||||
_aborted(false),
|
||||
_samples_read(0)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -15,6 +15,9 @@
|
||||
|
||||
#include "ffmpegVirtualFile.cxx"
|
||||
|
||||
#include "userDataAudio.cxx"
|
||||
#include "userDataAudioCursor.cxx"
|
||||
|
||||
#include "webcamVideo.cxx"
|
||||
#include "webcamVideoDS.cxx"
|
||||
|
||||
|
18
panda/src/movies/userDataAudio.I
Normal file
18
panda/src/movies/userDataAudio.I
Normal 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
144
panda/src/movies/userDataAudio.cxx
Normal file
144
panda/src/movies/userDataAudio.cxx
Normal 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();
|
||||
}
|
72
panda/src/movies/userDataAudio.h
Normal file
72
panda/src/movies/userDataAudio.h
Normal 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
|
18
panda/src/movies/userDataAudioCursor.I
Normal file
18
panda/src/movies/userDataAudioCursor.I
Normal 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 .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
63
panda/src/movies/userDataAudioCursor.cxx
Normal file
63
panda/src/movies/userDataAudioCursor.cxx
Normal 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);
|
||||
}
|
64
panda/src/movies/userDataAudioCursor.h
Normal file
64
panda/src/movies/userDataAudioCursor.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user