25 #define openal_audio_debug(x) \
26 audio_debug("OpenALAudioSound \""<<get_name() \
29#define openal_audio_debug(x) ((void)0)
51 _positional(positional),
53 _max_dist(1000000000.0f),
54 _drop_off_factor(1.0f),
60 _basename(movie->get_filename().get_basename()),
61 _active(manager->get_active()),
73 if (!require_sound_data()) {
78 _length = _sd->_length;
80 if (_sd->_channels != 1) {
81 audio_warning(
"stereo sound " << movie->
get_filename() <<
" will not be spatialized");
84 release_sound_data(
false);
100void OpenALAudioSound::
102 ReMutexHolder holder(OpenALAudioManager::_lock);
109 if (has_sound_data()) {
110 release_sound_data(
true);
112 _manager->release_sound(
this);
123 if (!is_valid())
return;
125 PN_stdfloat px,py,pz,vx,vy,vz;
134 if (!require_sound_data()) {
139 _manager->starting_sound(
this);
144 _manager->make_current();
150 alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE);
151 al_audio_errcheck(
"alSourcei(_source,AL_SOURCE_RELATIVE)");
163 _playing_loops = _loop_count;
164 if (_playing_loops == 0) {
165 _playing_loops = 1000000000;
167 _loops_completed = 0;
169 double play_rate = _play_rate * _manager->get_play_rate();
170 audio_debug(
"playing. Rate=" << play_rate);
171 alSourcef(_source, AL_PITCH, play_rate);
172 _playing_rate = play_rate;
175 push_fresh_buffers();
178#ifdef HAVE_OPENAL_FRAMEWORK
180 alGetSourcei(_source, AL_SOURCE_STATE, &
status);
181 if (
status != AL_PLAYING) {
182 alSourcePlay(_source);
185 alSourcef(_source, AL_SEC_OFFSET, _start_time);
186 _stream_queued[0]._time_offset = _start_time;
187#ifndef HAVE_OPENAL_FRAMEWORK
188 restart_stalled_audio();
191 audio_debug(
"Play: stream tell = " << _sd->_stream->tell() <<
" seeking " << _start_time);
192 if (_sd->_stream->tell() != _start_time) {
193 _sd->_stream->seek(_start_time);
195 push_fresh_buffers();
196 restart_stalled_audio();
199 set_calibrated_clock(rtc, _start_time, 1.0);
200 _current_time = _start_time;
211 if (!is_valid())
return;
214 _manager->make_current();
216 nassertv(has_sound_data());
219 alSourceStop(_source);
220 al_audio_errcheck(
"stopping a source");
221 alSourcei(_source, AL_BUFFER, 0);
222 al_audio_errcheck(
"clear source buffers");
223 for (
int i=0; i<((int)(_stream_queued.size())); i++) {
224 ALuint buffer = _stream_queued[i]._buffer;
225 if (buffer != _sd->_sample) {
226 _manager->delete_buffer(buffer);
229 _stream_queued.resize(0);
234 _manager->stopping_sound(
this);
235 release_sound_data(
false);
241void OpenALAudioSound::
245 if (!is_valid())
return;
248 _current_time = _length;
249 if (!_finished_event.empty()) {
250 throw_event(_finished_event);
260 set_loop_count((loop)?0:1);
268 return (_loop_count == 0);
274void OpenALAudioSound::
275set_loop_count(
unsigned long loop_count) {
278 if (!is_valid())
return;
280 if (loop_count >= 1000000000) {
283 _loop_count=loop_count;
301void OpenALAudioSound::
302restart_stalled_audio() {
306 if (!is_valid())
return;
307 nassertv(is_playing());
309 if (_stream_queued.size() == 0) {
314 alGetSourcei(_source, AL_SOURCE_STATE, &
status);
315 if (
status != AL_PLAYING) {
316 alSourcePlay(_source);
323void OpenALAudioSound::
324queue_buffer(ALuint buffer,
int samples,
int loop_index,
double time_offset) {
325 ReMutexHolder holder(OpenALAudioManager::_lock);
327 nassertv(is_playing());
331 alSourceQueueBuffers(_source,1,&buffer);
332 ALenum err = alGetError();
333 if (err != AL_NO_ERROR) {
334 audio_error(
"could not load sample buffer into the queue");
339 buf._buffer = buffer;
340 buf._samples = samples;
341 buf._loop_index = loop_index;
342 buf._time_offset = time_offset;
343 _stream_queued.push_back(buf);
349ALuint OpenALAudioSound::
350make_buffer(
int samples,
int channels,
int rate,
unsigned char *data) {
351 ReMutexHolder holder(OpenALAudioManager::_lock);
353 nassertr(is_playing(), 0);
358 alGenBuffers(1, &buffer);
359 if (alGetError() != AL_NO_ERROR) {
360 audio_error(
"could not allocate an OpenAL buffer object");
367 (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
368 data, samples * channels * 2, rate);
369 int err = alGetError();
370 if (err != AL_NO_ERROR) {
371 audio_error(
"could not fill OpenAL buffer object with data");
383int OpenALAudioSound::
384read_stream_data(
int bytelen,
unsigned char *buffer) {
385 ReMutexHolder holder(OpenALAudioManager::_lock);
387 nassertr(has_sound_data(), 0);
389 MovieAudioCursor *cursor = _sd->_stream;
390 double length = cursor->length();
391 int channels = cursor->audio_channels();
392 int rate = cursor->audio_rate();
393 int space = bytelen / (channels * 2);
396 while (space && (_loops_completed < _playing_loops)) {
397 double t = cursor->tell();
398 double remain =
length - t;
402 int samples = (int)(remain * rate);
404 _loops_completed += 1;
408 if (_sd->_stream->ready() == 0) {
409 if (_sd->_stream->aborted()) {
410 _loops_completed = _playing_loops;
414 if (samples > space) {
417 if (samples > _sd->_stream->ready()) {
418 samples = _sd->_stream->ready();
422 audio_debug(
"Streaming " << cursor->get_source()->get_name() <<
" at " << t <<
" hash " << hval);
425 buffer += (samples * channels * 2);
436void OpenALAudioSound::
437correct_calibrated_clock(
double rtc,
double t) {
438 ReMutexHolder holder(OpenALAudioManager::_lock);
440 nassertv(is_playing());
442 double cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
444 _calibrated_clock_decavg = (_calibrated_clock_decavg * 0.95) + (diff * 0.05);
446 set_calibrated_clock(rtc, t, 1.0);
447 _calibrated_clock_decavg = 0.0;
450 if ((_calibrated_clock_decavg > 0.01) && (diff > 0.01)) {
453 if ((_calibrated_clock_decavg < -0.01) && (diff < -0.01)) {
456 if ((_calibrated_clock_decavg < -0.05) && (diff < -0.05)) {
459 if ((_calibrated_clock_decavg < -0.15) && (diff < -0.15)) {
462 set_calibrated_clock(rtc, cc, scale);
464 cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
470void OpenALAudioSound::
472 ReMutexHolder holder(OpenALAudioManager::_lock);
474 if (!is_valid())
return;
475 nassertv(is_playing());
476 nassertv(has_sound_data());
478 while (_stream_queued.size()) {
480 ALint num_buffers = 0;
481 alGetSourcei(_source, AL_BUFFERS_PROCESSED, &num_buffers);
482 if (num_buffers <= 0) {
485 alSourceUnqueueBuffers(_source, 1, &buffer);
486 int err = alGetError();
487 if (err == AL_NO_ERROR) {
488 if (_stream_queued[0]._buffer != buffer) {
493 bool found_culprit =
false;
494 for (
auto it = _stream_queued.begin(); it != _stream_queued.end(); ++it) {
495 if (it->_buffer == buffer) {
497 _stream_queued.erase(it);
498 found_culprit =
true;
502 if (!found_culprit) {
503 audio_error(
"corruption in stream queue");
508 _stream_queued.pop_front();
509 if (_stream_queued.size()) {
510 double al = _stream_queued[0]._time_offset + _stream_queued[0]._loop_index * _length;
512 correct_calibrated_clock(rtc, al);
514 if (buffer != _sd->_sample) {
515 _manager->delete_buffer(buffer);
528void OpenALAudioSound::
529push_fresh_buffers() {
530 ReMutexHolder holder(OpenALAudioManager::_lock);
531 static unsigned char data[65536];
533 if (!is_valid())
return;
534 nassertv(is_playing());
535 nassertv(has_sound_data());
538 while ((_loops_completed < _playing_loops) &&
539 (_stream_queued.size() < 100)) {
540 queue_buffer(_sd->_sample, 0,_loops_completed, 0.0);
541 _loops_completed += 1;
544 MovieAudioCursor *cursor = _sd->_stream;
545 int channels = cursor->audio_channels();
546 int rate = cursor->audio_rate();
549 for (
size_t i = 0; i < _stream_queued.size(); i++) {
550 fill += _stream_queued[i]._samples;
553 while ((_loops_completed < _playing_loops) &&
554 (fill < (
int)(audio_buffering_seconds * rate * channels))) {
555 int loop_index = _loops_completed;
556 double time_offset = cursor->tell();
557 int samples = read_stream_data(65536, data);
561 ALuint buffer = make_buffer(samples, channels, rate, data);
562 if (!is_valid() || !buffer)
return;
563 queue_buffer(buffer, samples, loop_index, time_offset);
564 if (!is_valid())
return;
589 return _current_time;
595void OpenALAudioSound::
596cache_time(
double rtc) {
599 nassertv(is_playing());
601 double t=get_calibrated_clock(rtc);
602 double max = _length * _playing_loops;
604 _current_time = _length;
606 _current_time = fmod(t, _length);
619 volume*=_manager->get_volume();
620 _manager->make_current();
622 alSourcef(_source,AL_GAIN,volume);
623 al_audio_errcheck(
"alSourcef(_source,AL_GAIN)");
640 audio_debug(
"OpenALAudioSound::set_balance() not implemented");
649 audio_debug(
"OpenALAudioSound::get_balance() not implemented");
661 _play_rate = play_rate;
663 alSourcef(_source, AL_PITCH, play_rate);
670PN_stdfloat OpenALAudioSound::
671get_play_rate()
const {
694set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
696 CoordinateSystem cs = get_default_coordinate_system();
740 nassert_raise(
"invalid coordinate system");
745 _manager->make_current();
748 alSourcefv(_source,AL_POSITION,_location);
749 al_audio_errcheck(
"alSourcefv(_source,AL_POSITION)");
750 alSourcefv(_source,AL_VELOCITY,_velocity);
751 al_audio_errcheck(
"alSourcefv(_source,AL_VELOCITY)");
760get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
781 _manager->make_current();
784 alSourcef(_source,AL_REFERENCE_DISTANCE,_min_dist);
785 al_audio_errcheck(
"alSourcefv(_source,AL_REFERENCE_DISTANCE)");
806 _manager->make_current();
809 alSourcef(_source,AL_MAX_DISTANCE,_max_dist);
810 al_audio_errcheck(
"alSourcefv(_source,AL_MAX_DISTANCE)");
828 _drop_off_factor = factor;
831 _manager->make_current();
834 alSourcef(_source,AL_ROLLOFF_FACTOR,_drop_off_factor*_manager->audio_3d_get_drop_off_factor());
835 al_audio_errcheck(
"alSourcefv(_source,AL_ROLLOFF_FACTOR)");
844 return _drop_off_factor;
856 if (!is_valid())
return;
858 if (_active!=active) {
862 if (_paused && _loop_count==0) {
871 if (_loop_count==0) {
892void OpenALAudioSound::
893set_finished_event(
const std::string& event) {
894 _finished_event = event;
900const std::string& OpenALAudioSound::
901get_finished_event()
const {
902 return _finished_event;
922 return AudioSound::READY;
924 if ((_loops_completed >= _playing_loops)&&(_stream_queued.size()==0)) {
925 return AudioSound::READY;
927 return AudioSound::PLAYING;
static size_t add_hash(size_t start, const uint32_t *words, size_t num_words)
Adds a linear sequence of uint32 words to the hash.
virtual void seek(double offset)
Skips to the specified offset within the file.
void read_samples(int n, Datagram *dg)
Read audio samples from the stream into a Datagram.
A MovieAudio is actually any source that provides a sequence of audio samples.
get_filename
Returns the movie's filename.
AudioSound::SoundStatus status() const
Get status of the sound.
void set_loop(bool loop=true)
Turns looping on and off.
void get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz)
Get position and velocity of this sound Currently unimplemented.
void set_3d_min_distance(PN_stdfloat dist)
Set the distance that this sound begins to fall off.
bool get_loop() const
Returns whether looping is on or off.
void set_3d_max_distance(PN_stdfloat dist)
Set the distance that this sound stops falling off.
PN_stdfloat get_time() const
Gets the play position within the sound.
void set_active(bool active=true)
Sets whether the sound is marked "active".
void play()
Plays a sound.
const std::string & get_name() const
Get name of sound file.
PN_stdfloat get_3d_drop_off_factor() const
Control the effect distance has on audability.
bool get_active() const
Returns whether the sound has been marked "active".
PN_stdfloat get_volume() const
Gets the current volume of a sound.
void set_play_rate(PN_stdfloat play_rate=1.0f)
Sets the speed at which a sound plays back.
PN_stdfloat length() const
Get length.
void set_time(PN_stdfloat time=0.0)
The next time you call play, the sound will start from the specified offset.
PN_stdfloat get_3d_max_distance() const
Get the distance that this sound stops falling off.
void set_3d_drop_off_factor(PN_stdfloat factor)
Control the effect distance has on audability.
PN_stdfloat get_balance() const
-1.0 to 1.0 scale -1 should be all the way left.
void set_volume(PN_stdfloat volume=1.0)
0.0 to 1.0 scale of volume converted to Fmod's internal 0.0 to 255.0 scale.
void set_balance(PN_stdfloat balance_right=0.0)
-1.0 to 1.0 scale
PN_stdfloat get_3d_min_distance() const
Get the distance that this sound begins to fall off.
void set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz)
Set position and velocity of this sound.
unsigned long get_loop_count() const
Return how many times a sound will loop.
Similar to MutexHolder, but for a reentrant mutex.
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
TypeHandle is the identifier used to differentiate C++ class types.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.