16 #include "pandabase.h" 19 #include "throw_event.h" 20 #include "openalAudioSound.h" 21 #include "openalAudioManager.h" 27 #define openal_audio_debug(x) \ 28 audio_debug("OpenALAudioSound \""<<get_name() \ 31 #define openal_audio_debug(x) ((void)0) 55 _positional(positional),
57 _max_dist(1000000000.0f),
58 _drop_off_factor(1.0f),
64 _basename(movie->get_filename().get_basename()),
65 _active(manager->get_active()),
78 if (_manager == NULL) {
82 _length = _sd->_length;
84 if (_sd->_channels != 1) {
85 audio_warning(
"stereo sound " << movie->
get_filename() <<
" will not be spatialized");
108 void OpenALAudioSound::
118 _manager->decrement_client_count(_sd);
121 _manager->release_sound(
this);
133 if (_manager == 0)
return;
135 PN_stdfloat px,py,pz,vx,vy,vz;
144 require_sound_data();
145 if (_manager == 0)
return;
146 _manager->starting_sound(
this);
152 _manager->make_current();
157 alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE);
158 al_audio_errcheck(
"alSourcei(_source,AL_SOURCE_RELATIVE)");
170 _playing_loops = _loop_count;
171 if (_playing_loops == 0) {
172 _playing_loops = 1000000000;
174 _loops_completed = 0;
176 double play_rate = _play_rate * _manager->get_play_rate();
177 audio_debug(
"playing. Rate=" << play_rate);
178 alSourcef(_source, AL_PITCH, play_rate);
179 _playing_rate = play_rate;
182 push_fresh_buffers();
183 alSourcef(_source, AL_SEC_OFFSET, _start_time);
184 _stream_queued[0]._time_offset = _start_time;
185 restart_stalled_audio();
187 audio_debug(
"Play: stream tell = " << _sd->_stream->tell() <<
" seeking " << _start_time);
188 if (_sd->_stream->tell() != _start_time) {
189 _sd->_stream->seek(_start_time);
191 push_fresh_buffers();
192 restart_stalled_audio();
195 set_calibrated_clock(rtc, _start_time, 1.0);
196 _current_time = _start_time;
208 if (_manager==0)
return;
211 _manager->make_current();
214 alSourceStop(_source);
215 al_audio_errcheck(
"stopping a source");
216 alSourcei(_source, AL_BUFFER, 0);
217 al_audio_errcheck(
"clear source buffers");
218 for (
int i=0; i<((int)(_stream_queued.size())); i++) {
219 ALuint buffer = _stream_queued[i]._buffer;
220 if (buffer != _sd->_sample) {
221 alDeleteBuffers(1, &buffer);
222 al_audio_errcheck(
"deleting a buffer");
225 _stream_queued.resize(0);
228 _manager->stopping_sound(
this);
229 release_sound_data();
237 void OpenALAudioSound::
241 _current_time = _length;
242 if (!_finished_event.empty()) {
243 throw_event(_finished_event);
255 set_loop_count((loop)?0:1);
265 return (_loop_count == 0);
273 void OpenALAudioSound::
274 set_loop_count(
unsigned long loop_count) {
276 if (_manager==0)
return;
278 if (loop_count >= 1000000000) {
281 _loop_count=loop_count;
305 void OpenALAudioSound::
306 restart_stalled_audio() {
309 if (_stream_queued.size() == 0) {
313 alGetSourcei(_source, AL_SOURCE_STATE, &status);
314 if (status != AL_PLAYING) {
315 alSourcePlay(_source);
324 void OpenALAudioSound::
325 queue_buffer(ALuint buffer,
int samples,
int loop_index,
double time_offset) {
329 alSourceQueueBuffers(_source,1,&buffer);
330 ALenum err = alGetError();
331 if (err != AL_NO_ERROR) {
332 audio_error(
"could not load sample buffer into the queue");
337 buf._buffer = buffer;
338 buf._samples = samples;
339 buf._loop_index = loop_index;
340 buf._time_offset = time_offset;
341 _stream_queued.push_back(buf);
349 ALuint OpenALAudioSound::
350 make_buffer(
int samples,
int channels,
int rate,
unsigned char *data) {
356 alGenBuffers(1, &buffer);
357 if (alGetError() != AL_NO_ERROR) {
358 audio_error(
"could not allocate an OpenAL buffer object");
365 (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
366 data, samples * channels * 2, rate);
367 int err = alGetError();
368 if (err != AL_NO_ERROR) {
369 audio_error(
"could not fill OpenAL buffer object with data");
383 int OpenALAudioSound::
384 read_stream_data(
int bytelen,
unsigned char *buffer) {
388 double length = cursor->length();
389 int channels = cursor->audio_channels();
390 int rate = cursor->audio_rate();
391 int space = bytelen / (channels * 2);
394 while (space && (_loops_completed < _playing_loops)) {
395 double t = cursor->tell();
396 double remain = length - t;
400 int samples = (int)(remain * rate);
402 _loops_completed += 1;
406 if (_sd->_stream->ready() == 0) {
407 if (_sd->_stream->aborted()) {
408 _loops_completed = _playing_loops;
412 if (samples > space) {
415 if (samples > _sd->_stream->ready()) {
416 samples = _sd->_stream->ready();
420 audio_debug(
"Streaming " << cursor->get_source()->get_name() <<
" at " << t <<
" hash " << hval);
423 buffer += (samples * channels * 2);
438 void OpenALAudioSound::
439 correct_calibrated_clock(
double rtc,
double t) {
441 double cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
443 _calibrated_clock_decavg = (_calibrated_clock_decavg * 0.95) + (diff * 0.05);
445 set_calibrated_clock(rtc, t, 1.0);
446 _calibrated_clock_decavg = 0.0;
449 if ((_calibrated_clock_decavg > 0.01) && (diff > 0.01)) {
452 if ((_calibrated_clock_decavg < -0.01) && (diff < -0.01)) {
455 if ((_calibrated_clock_decavg < -0.05) && (diff < -0.05)) {
458 if ((_calibrated_clock_decavg < -0.15) && (diff < -0.15)) {
461 set_calibrated_clock(rtc, cc, scale);
463 cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
471 void OpenALAudioSound::
472 pull_used_buffers() {
474 while (_stream_queued.size()) {
477 alSourceUnqueueBuffers(_source, 1, &buffer);
478 int err = alGetError();
479 if (err == AL_NO_ERROR) {
480 if (_stream_queued[0]._buffer != buffer) {
481 audio_error(
"corruption in stream queue");
485 _stream_queued.pop_front();
486 if (_stream_queued.size()) {
487 double al = _stream_queued[0]._time_offset + _stream_queued[0]._loop_index * _length;
489 correct_calibrated_clock(rtc, al);
491 if (buffer != _sd->_sample) {
492 alDeleteBuffers(1,&buffer);
506 void OpenALAudioSound::
507 push_fresh_buffers() {
509 static unsigned char data[65536];
512 while ((_loops_completed < _playing_loops) &&
513 (_stream_queued.size() < 100)) {
514 queue_buffer(_sd->_sample, 0,_loops_completed, 0.0);
515 _loops_completed += 1;
519 int channels = cursor->audio_channels();
520 int rate = cursor->audio_rate();
523 for (
size_t i = 0; i < _stream_queued.size(); i++) {
524 fill += _stream_queued[i]._samples;
527 while ((_loops_completed < _playing_loops) &&
528 (fill < (int)(audio_buffering_seconds * rate * channels))) {
529 int loop_index = _loops_completed;
530 double time_offset = cursor->tell();
531 int samples = read_stream_data(65536, data);
535 ALuint buffer = make_buffer(samples, channels, rate, data);
536 if (_manager == 0)
return;
537 queue_buffer(buffer, samples, loop_index, time_offset);
538 if (_manager == 0)
return;
567 return _current_time;
575 void OpenALAudioSound::
576 cache_time(
double rtc) {
578 assert(_source != 0);
579 double t=get_calibrated_clock(rtc);
580 double max = _length * _playing_loops;
582 _current_time = _length;
584 _current_time = fmod(t, _length);
600 volume*=_manager->get_volume();
601 _manager->make_current();
603 alSourcef(_source,AL_GAIN,volume);
604 al_audio_errcheck(
"alSourcef(_source,AL_GAIN)");
625 audio_debug(
"OpenALAudioSound::set_balance() not implemented");
637 audio_debug(
"OpenALAudioSound::get_balance() not implemented");
651 _play_rate = play_rate;
653 alSourcef(_source, AL_PITCH, play_rate);
662 PN_stdfloat OpenALAudioSound::
663 get_play_rate()
const {
694 set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
705 _manager->make_current();
708 alSourcefv(_source,AL_POSITION,_location);
709 al_audio_errcheck(
"alSourcefv(_source,AL_POSITION)");
710 alSourcefv(_source,AL_VELOCITY,_velocity);
711 al_audio_errcheck(
"alSourcefv(_source,AL_VELOCITY)");
722 get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
745 _manager->make_current();
748 alSourcef(_source,AL_REFERENCE_DISTANCE,_min_dist*_manager->audio_3d_get_distance_factor());
749 al_audio_errcheck(
"alSourcefv(_source,AL_REFERENCE_DISTANCE)");
774 _manager->make_current();
777 alSourcef(_source,AL_MAX_DISTANCE,_max_dist*_manager->audio_3d_get_distance_factor());
778 al_audio_errcheck(
"alSourcefv(_source,AL_MAX_DISTANCE)");
801 _drop_off_factor = factor;
804 _manager->make_current();
807 alSourcef(_source,AL_ROLLOFF_FACTOR,_drop_off_factor*_manager->audio_3d_get_drop_off_factor());
808 al_audio_errcheck(
"alSourcefv(_source,AL_ROLLOFF_FACTOR)");
820 return _drop_off_factor;
834 if (_active!=active) {
838 if (_paused && _loop_count==0) {
846 if (_loop_count==0) {
872 void OpenALAudioSound::
873 set_finished_event(
const string& event) {
874 _finished_event = event;
882 const string& OpenALAudioSound::
883 get_finished_event()
const {
884 return _finished_event;
909 return AudioSound::READY;
911 if ((_loops_completed >= _playing_loops)&&(_stream_queued.size()==0)) {
912 return AudioSound::READY;
914 return AudioSound::PLAYING;
void set_3d_max_distance(PN_stdfloat dist)
Set the distance that this sound stops falling off.
static TrueClock * get_global_ptr()
Returns a pointer to the one TrueClock object in the world.
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_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.
void read_samples(int n, Datagram *dg)
Read audio samples from the stream into a Datagram.
PN_stdfloat get_time() const
Gets the play position within the sound.
void set_3d_min_distance(PN_stdfloat dist)
Set the distance that this sound begins to fall off.
PN_stdfloat get_3d_drop_off_factor() const
Control the effect distance has on audability.
bool get_loop() const
Returns whether looping is on or off.
static size_t add_hash(size_t start, const PN_uint32 *words, size_t num_words)
Adds a linear sequence of uint32 words to the hash.
void set_3d_drop_off_factor(PN_stdfloat factor)
Control the effect distance has on audability.
void set_active(bool active=true)
Sets whether the sound is marked "active".
PN_stdfloat get_balance() const
-1.0 to 1.0 scale -1 should be all the way left.
const string & get_name() const
Get name of sound file.
A MovieAudio is actually any source that provides a sequence of audio samples.
bool get_active() const
Returns whether the sound has been marked "active".
Similar to MutexHolder, but for a reentrant mutex.
const Filename & get_filename() const
Returns the movie's filename.
void play()
Plays a sound.
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.
PN_stdfloat get_3d_min_distance() const
Get the distance that this sound begins to fall off.
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.
TypeHandle is the identifier used to differentiate C++ class types.
void set_loop(bool loop=true)
Turns looping on and off.
A MovieAudio is actually any source that provides a sequence of audio samples.
PN_stdfloat get_volume() const
Gets the current volume of a sound.
unsigned long get_loop_count() const
Return how many times a sound will loop.
PN_stdfloat length() const
Get length.
void set_balance(PN_stdfloat balance_right=0.0)
-1.0 to 1.0 scale
virtual void seek(double offset)
Skips to the specified offset within the file.
void set_play_rate(PN_stdfloat play_rate=1.0f)
Sets the speed at which a sound plays back.
AudioSound::SoundStatus status() const
Get status of the sound.