Panda3D
openalAudioSound.cxx
1 // Filename: openalAudioSound.cxx
2 // Created by: Ben Buchwald <bb2@alumni.cmu.edu>
3 //
4 //
5 ////////////////////////////////////////////////////////////////////
6 //
7 // PANDA 3D SOFTWARE
8 // Copyright (c) Carnegie Mellon University. All rights reserved.
9 //
10 // All use of this software is subject to the terms of the revised BSD
11 // license. You should have received a copy of this license along
12 // with this source code in a file named "LICENSE."
13 //
14 ////////////////////////////////////////////////////////////////////
15 
16 #include "pandabase.h"
17 
18 //Panda Headers
19 #include "throw_event.h"
20 #include "openalAudioSound.h"
21 #include "openalAudioManager.h"
22 
23 TypeHandle OpenALAudioSound::_type_handle;
24 
25 
26 #ifndef NDEBUG //[
27  #define openal_audio_debug(x) \
28  audio_debug("OpenALAudioSound \""<<get_name() \
29  <<"\" "<< x )
30 #else //][
31 #define openal_audio_debug(x) ((void)0)
32 #endif //]
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: OpenALAudioSound::Constructor
36 // Access: Private
37 // Description:
38 ////////////////////////////////////////////////////////////////////
39 
40 OpenALAudioSound::
41 OpenALAudioSound(OpenALAudioManager* manager,
42  MovieAudio *movie,
43  bool positional,
44  int mode) :
45  _movie(movie),
46  _sd(NULL),
47  _playing_loops(0),
48  _playing_rate(0.0),
49  _loops_completed(0),
50  _source(0),
51  _manager(manager),
52  _volume(1.0f),
53  _balance(0),
54  _play_rate(1.0),
55  _positional(positional),
56  _min_dist(3.28f),
57  _max_dist(1000000000.0f),
58  _drop_off_factor(1.0f),
59  _length(0.0),
60  _loop_count(1),
61  _desired_mode(mode),
62  _start_time(0.0),
63  _current_time(0.0),
64  _basename(movie->get_filename().get_basename()),
65  _active(manager->get_active()),
66  _paused(false)
67 {
68  _location[0] = 0.0f;
69  _location[1] = 0.0f;
70  _location[2] = 0.0f;
71  _velocity[0] = 0.0f;
72  _velocity[1] = 0.0f;
73  _velocity[2] = 0.0f;
74 
75  ReMutexHolder holder(OpenALAudioManager::_lock);
76 
77  require_sound_data();
78  if (_manager == NULL) {
79  return;
80  }
81 
82  _length = _sd->_length;
83  if (positional) {
84  if (_sd->_channels != 1) {
85  audio_warning("stereo sound " << movie->get_filename() << " will not be spatialized");
86  }
87  }
88  release_sound_data();
89 }
90 
91 
92 ////////////////////////////////////////////////////////////////////
93 // Function: OpenALAudioSound::Destructor
94 // Access: public
95 // Description:
96 ////////////////////////////////////////////////////////////////////
97 OpenALAudioSound::
98 ~OpenALAudioSound() {
99  cleanup();
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: OpenALAudioSound::cleanup
104 // Access: Private
105 // Description: Disables the sound forever. Releases resources and
106 // detaches the sound from its audio manager.
107 ////////////////////////////////////////////////////////////////////
108 void OpenALAudioSound::
109 cleanup() {
110  ReMutexHolder holder(OpenALAudioManager::_lock);
111  if (_manager == 0) {
112  return;
113  }
114  if (_source) {
115  stop();
116  }
117  if (_sd) {
118  _manager->decrement_client_count(_sd);
119  _sd = 0;
120  }
121  _manager->release_sound(this);
122  _manager = 0;
123 }
124 
125 ////////////////////////////////////////////////////////////////////
126 // Function: OpenALAudioSound::play
127 // Access: public
128 // Description: Plays a sound.
129 ////////////////////////////////////////////////////////////////////
131 play() {
132  ReMutexHolder holder(OpenALAudioManager::_lock);
133  if (_manager == 0) return;
134 
135  PN_stdfloat px,py,pz,vx,vy,vz;
136 
137  if (!_active) {
138  _paused = true;
139  return;
140  }
141 
142  stop();
143 
144  require_sound_data();
145  if (_manager == 0) return;
146  _manager->starting_sound(this);
147 
148  if (!_source) {
149  return;
150  }
151 
152  _manager->make_current();
153 
154  alGetError(); // clear errors
155 
156  // nonpositional sources are made relative to the listener so they don't move
157  alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE);
158  al_audio_errcheck("alSourcei(_source,AL_SOURCE_RELATIVE)");
159 
160  // set source properties that we have stored
161  set_volume(_volume);
162  //set_balance(_balance);
163 
164  set_3d_min_distance(_min_dist);
165  set_3d_max_distance(_max_dist);
166  set_3d_drop_off_factor(_drop_off_factor);
167  get_3d_attributes(&px,&py,&pz,&vx,&vy,&vz);
168  set_3d_attributes(px, py, pz, vx, vy, vz);
169 
170  _playing_loops = _loop_count;
171  if (_playing_loops == 0) {
172  _playing_loops = 1000000000;
173  }
174  _loops_completed = 0;
175 
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;
180 
181  if (_sd->_sample) {
182  push_fresh_buffers();
183  alSourcef(_source, AL_SEC_OFFSET, _start_time);
184  _stream_queued[0]._time_offset = _start_time;
185  restart_stalled_audio();
186  } else {
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);
190  }
191  push_fresh_buffers();
192  restart_stalled_audio();
193  }
194  double rtc = TrueClock::get_global_ptr()->get_short_time();
195  set_calibrated_clock(rtc, _start_time, 1.0);
196  _current_time = _start_time;
197  _start_time = 0.0;
198 }
199 
200 ////////////////////////////////////////////////////////////////////
201 // Function: OpenALAudioSound::stop
202 // Access: public
203 // Description: Stop a sound
204 ////////////////////////////////////////////////////////////////////
206 stop() {
207  ReMutexHolder holder(OpenALAudioManager::_lock);
208  if (_manager==0) return;
209 
210  if (_source) {
211  _manager->make_current();
212 
213  alGetError(); // clear errors
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");
223  }
224  }
225  _stream_queued.resize(0);
226  }
227 
228  _manager->stopping_sound(this);
229  release_sound_data();
230 }
231 
232 ////////////////////////////////////////////////////////////////////
233 // Function: OpenALAudioSound::finished
234 // Access:
235 // Description:
236 ////////////////////////////////////////////////////////////////////
237 void OpenALAudioSound::
238 finished() {
239  ReMutexHolder holder(OpenALAudioManager::_lock);
240  stop();
241  _current_time = _length;
242  if (!_finished_event.empty()) {
243  throw_event(_finished_event);
244  }
245 }
246 
247 ////////////////////////////////////////////////////////////////////
248 // Function: OpenALAudioSound::set_loop
249 // Access: public
250 // Description: Turns looping on and off
251 ////////////////////////////////////////////////////////////////////
253 set_loop(bool loop) {
254  ReMutexHolder holder(OpenALAudioManager::_lock);
255  set_loop_count((loop)?0:1);
256 }
257 
258 ////////////////////////////////////////////////////////////////////
259 // Function: OpenALAudioSound::get_loop
260 // Access: public
261 // Description: Returns whether looping is on or off
262 ////////////////////////////////////////////////////////////////////
264 get_loop() const {
265  return (_loop_count == 0);
266 }
267 
268 ////////////////////////////////////////////////////////////////////
269 // Function: OpenALAudioSound::set_loop_count
270 // Access: public
271 // Description:
272 ////////////////////////////////////////////////////////////////////
273 void OpenALAudioSound::
274 set_loop_count(unsigned long loop_count) {
275  ReMutexHolder holder(OpenALAudioManager::_lock);
276  if (_manager==0) return;
277 
278  if (loop_count >= 1000000000) {
279  loop_count = 0;
280  }
281  _loop_count=loop_count;
282 }
283 
284 ////////////////////////////////////////////////////////////////////
285 // Function: OpenALAudioSound::get_loop_count
286 // Access: public
287 // Description: Return how many times a sound will loop.
288 ////////////////////////////////////////////////////////////////////
289 unsigned long OpenALAudioSound::
290 get_loop_count() const {
291  return _loop_count;
292 }
293 
294 ////////////////////////////////////////////////////////////////////
295 // Function: OpenALAudioSound::restart_stalled_audio
296 // Access: public
297 // Description: When streaming audio, the computer is supposed to
298 // keep OpenAL's queue full. However, there are times
299 // when the computer is running slow and the queue
300 // empties prematurely. In that case, OpenAL will stop.
301 // When the computer finally gets around to refilling
302 // the queue, it is necessary to tell OpenAL to resume
303 // playing.
304 ////////////////////////////////////////////////////////////////////
305 void OpenALAudioSound::
306 restart_stalled_audio() {
307  ReMutexHolder holder(OpenALAudioManager::_lock);
308  ALenum status;
309  if (_stream_queued.size() == 0) {
310  return;
311  }
312  alGetError();
313  alGetSourcei(_source, AL_SOURCE_STATE, &status);
314  if (status != AL_PLAYING) {
315  alSourcePlay(_source);
316  }
317 }
318 
319 ////////////////////////////////////////////////////////////////////
320 // Function: OpenALAudioSound::queue_buffer
321 // Access: public
322 // Description: Pushes a buffer into the source queue.
323 ////////////////////////////////////////////////////////////////////
324 void OpenALAudioSound::
325 queue_buffer(ALuint buffer, int samples, int loop_index, double time_offset) {
326  ReMutexHolder holder(OpenALAudioManager::_lock);
327  // Now push the buffer into the stream queue.
328  alGetError();
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");
333  cleanup();
334  return;
335  }
336  QueuedBuffer buf;
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);
342 }
343 
344 ////////////////////////////////////////////////////////////////////
345 // Function: OpenALAudioSound::make_buffer
346 // Access: public
347 // Description: Creates an OpenAL buffer object.
348 ////////////////////////////////////////////////////////////////////
349 ALuint OpenALAudioSound::
350 make_buffer(int samples, int channels, int rate, unsigned char *data) {
351  ReMutexHolder holder(OpenALAudioManager::_lock);
352 
353  // Allocate a buffer to hold the data.
354  alGetError();
355  ALuint buffer;
356  alGenBuffers(1, &buffer);
357  if (alGetError() != AL_NO_ERROR) {
358  audio_error("could not allocate an OpenAL buffer object");
359  cleanup();
360  return 0;
361  }
362 
363  // Now fill the buffer with the data provided.
364  alBufferData(buffer,
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");
370  cleanup();
371  return 0;
372  }
373 
374  return buffer;
375 }
376 
377 ////////////////////////////////////////////////////////////////////
378 // Function: OpenALAudioSound::read_stream_data
379 // Access: public
380 // Description: Fills a buffer with data from the stream.
381 // Returns the number of samples stored in the buffer.
382 ////////////////////////////////////////////////////////////////////
383 int OpenALAudioSound::
384 read_stream_data(int bytelen, unsigned char *buffer) {
385  ReMutexHolder holder(OpenALAudioManager::_lock);
386 
387  MovieAudioCursor *cursor = _sd->_stream;
388  double length = cursor->length();
389  int channels = cursor->audio_channels();
390  int rate = cursor->audio_rate();
391  int space = bytelen / (channels * 2);
392  int fill = 0;
393 
394  while (space && (_loops_completed < _playing_loops)) {
395  double t = cursor->tell();
396  double remain = length - t;
397  if (remain > 60.0) {
398  remain = 60.0;
399  }
400  int samples = (int)(remain * rate);
401  if (samples <= 0) {
402  _loops_completed += 1;
403  cursor->seek(0.0);
404  continue;
405  }
406  if (_sd->_stream->ready() == 0) {
407  if (_sd->_stream->aborted()) {
408  _loops_completed = _playing_loops;
409  }
410  return fill;
411  }
412  if (samples > space) {
413  samples = space;
414  }
415  if (samples > _sd->_stream->ready()) {
416  samples = _sd->_stream->ready();
417  }
418  cursor->read_samples(samples, (PN_int16 *)buffer);
419  size_t hval = AddHash::add_hash(0, (PN_uint8*)buffer, samples*channels*2);
420  audio_debug("Streaming " << cursor->get_source()->get_name() << " at " << t << " hash " << hval);
421  fill += samples;
422  space -= samples;
423  buffer += (samples * channels * 2);
424  }
425  return fill;
426 }
427 
428 ////////////////////////////////////////////////////////////////////
429 // Function: OpenALAudioSound::correct_calibrated_clock
430 // Access: public
431 // Description: Compares the specified time to the value of the
432 // calibrated clock, and adjusts the calibrated
433 // clock speed to make it closer to the target value.
434 // This routine is quite careful to make sure that
435 // the calibrated clock moves in a smooth, monotonic
436 // way.
437 ////////////////////////////////////////////////////////////////////
438 void OpenALAudioSound::
439 correct_calibrated_clock(double rtc, double t) {
440  ReMutexHolder holder(OpenALAudioManager::_lock);
441  double cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
442  double diff = cc-t;
443  _calibrated_clock_decavg = (_calibrated_clock_decavg * 0.95) + (diff * 0.05);
444  if (diff > 0.5) {
445  set_calibrated_clock(rtc, t, 1.0);
446  _calibrated_clock_decavg = 0.0;
447  } else {
448  double scale = 1.0;
449  if ((_calibrated_clock_decavg > 0.01) && (diff > 0.01)) {
450  scale = 0.98;
451  }
452  if ((_calibrated_clock_decavg < -0.01) && (diff < -0.01)) {
453  scale = 1.03;
454  }
455  if ((_calibrated_clock_decavg < -0.05) && (diff < -0.05)) {
456  scale = 1.2;
457  }
458  if ((_calibrated_clock_decavg < -0.15) && (diff < -0.15)) {
459  scale = 1.5;
460  }
461  set_calibrated_clock(rtc, cc, scale);
462  }
463  cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
464 }
465 
466 ////////////////////////////////////////////////////////////////////
467 // Function: OpenALAudioSound::pull_used_buffers
468 // Access: public
469 // Description: Pulls any used buffers out of OpenAL's queue.
470 ////////////////////////////////////////////////////////////////////
471 void OpenALAudioSound::
472 pull_used_buffers() {
473  ReMutexHolder holder(OpenALAudioManager::_lock);
474  while (_stream_queued.size()) {
475  ALuint buffer = 0;
476  alGetError();
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");
482  cleanup();
483  return;
484  }
485  _stream_queued.pop_front();
486  if (_stream_queued.size()) {
487  double al = _stream_queued[0]._time_offset + _stream_queued[0]._loop_index * _length;
488  double rtc = TrueClock::get_global_ptr()->get_short_time();
489  correct_calibrated_clock(rtc, al);
490  }
491  if (buffer != _sd->_sample) {
492  alDeleteBuffers(1,&buffer);
493  }
494  } else {
495  break;
496  }
497  }
498 }
499 
500 ////////////////////////////////////////////////////////////////////
501 // Function: OpenALAudioSound::push_fresh_buffers
502 // Access: public
503 // Description: Pushes fresh buffers into OpenAL's queue until
504 // the queue is "full" (ie, has plenty of data).
505 ////////////////////////////////////////////////////////////////////
506 void OpenALAudioSound::
507 push_fresh_buffers() {
508  ReMutexHolder holder(OpenALAudioManager::_lock);
509  static unsigned char data[65536];
510 
511  if (_sd->_sample) {
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;
516  }
517  } else {
518  MovieAudioCursor *cursor = _sd->_stream;
519  int channels = cursor->audio_channels();
520  int rate = cursor->audio_rate();
521 
522  int fill = 0;
523  for (size_t i = 0; i < _stream_queued.size(); i++) {
524  fill += _stream_queued[i]._samples;
525  }
526 
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);
532  if (samples == 0) {
533  break;
534  }
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;
539  fill += samples;
540  }
541  }
542 }
543 
544 ////////////////////////////////////////////////////////////////////
545 // Function: OpenALAudioSound::set_time
546 // Access: public
547 // Description: The next time you call play, the sound will
548 // start from the specified offset.
549 ////////////////////////////////////////////////////////////////////
551 set_time(PN_stdfloat time) {
552  ReMutexHolder holder(OpenALAudioManager::_lock);
553  _start_time = time;
554 }
555 
556 ////////////////////////////////////////////////////////////////////
557 // Function: OpenALAudioSound::get_time
558 // Access: public
559 // Description: Gets the play position within the sound
560 ////////////////////////////////////////////////////////////////////
561 PN_stdfloat OpenALAudioSound::
562 get_time() const {
563  ReMutexHolder holder(OpenALAudioManager::_lock);
564  if (_manager == 0) {
565  return 0.0;
566  }
567  return _current_time;
568 }
569 
570 ////////////////////////////////////////////////////////////////////
571 // Function: OpenALAudioSound::cache_time
572 // Access: Private
573 // Description: Updates the current_time field of a playing sound.
574 ////////////////////////////////////////////////////////////////////
575 void OpenALAudioSound::
576 cache_time(double rtc) {
577  ReMutexHolder holder(OpenALAudioManager::_lock);
578  assert(_source != 0);
579  double t=get_calibrated_clock(rtc);
580  double max = _length * _playing_loops;
581  if (t >= max) {
582  _current_time = _length;
583  } else {
584  _current_time = fmod(t, _length);
585  }
586 }
587 
588 ////////////////////////////////////////////////////////////////////
589 // Function: OpenALAudioSound::set_volume(PN_stdfloat vol)
590 // Access: public
591 // Description: 0.0 to 1.0 scale of volume converted to Fmod's
592 // internal 0.0 to 255.0 scale.
593 ////////////////////////////////////////////////////////////////////
595 set_volume(PN_stdfloat volume) {
596  ReMutexHolder holder(OpenALAudioManager::_lock);
597  _volume=volume;
598 
599  if (_source) {
600  volume*=_manager->get_volume();
601  _manager->make_current();
602  alGetError(); // clear errors
603  alSourcef(_source,AL_GAIN,volume);
604  al_audio_errcheck("alSourcef(_source,AL_GAIN)");
605  }
606 }
607 
608 ////////////////////////////////////////////////////////////////////
609 // Function: OpenALAudioSound::get_volume
610 // Access: public
611 // Description: Gets the current volume of a sound. 1 is Max. O is Min.
612 ////////////////////////////////////////////////////////////////////
613 PN_stdfloat OpenALAudioSound::
614 get_volume() const {
615  return _volume;
616 }
617 
618 ////////////////////////////////////////////////////////////////////
619 // Function: OpenALAudioSound::set_balance(PN_stdfloat bal)
620 // Access: public
621 // Description: -1.0 to 1.0 scale
622 ////////////////////////////////////////////////////////////////////
624 set_balance(PN_stdfloat balance_right) {
625  audio_debug("OpenALAudioSound::set_balance() not implemented");
626 }
627 
628 ////////////////////////////////////////////////////////////////////
629 // Function: OpenALAudioSound::get_balance
630 // Access: public
631 // Description: -1.0 to 1.0 scale
632 // -1 should be all the way left.
633 // 1 is all the way to the right.
634 ////////////////////////////////////////////////////////////////////
635 PN_stdfloat OpenALAudioSound::
636 get_balance() const {
637  audio_debug("OpenALAudioSound::get_balance() not implemented");
638  return 0;
639 }
640 
641 ////////////////////////////////////////////////////////////////////
642 // Function: OpenALAudioSound::set_play_rate(PN_stdfloat rate)
643 // Access: public
644 // Description: Sets the speed at which a sound plays back.
645 // The rate is a multiple of the sound, normal playback speed.
646 // IE 2 would play back 2 times fast, 3 would play 3 times, and so on.
647 ////////////////////////////////////////////////////////////////////
649 set_play_rate(PN_stdfloat play_rate) {
650  ReMutexHolder holder(OpenALAudioManager::_lock);
651  _play_rate = play_rate;
652  if (_source) {
653  alSourcef(_source, AL_PITCH, play_rate);
654  }
655 }
656 
657 ////////////////////////////////////////////////////////////////////
658 // Function: OpenALAudioSound::get_play_rate
659 // Access: public
660 // Description:
661 ////////////////////////////////////////////////////////////////////
662 PN_stdfloat OpenALAudioSound::
663 get_play_rate() const {
664  return _play_rate;
665 }
666 
667 ////////////////////////////////////////////////////////////////////
668 // Function: OpenALAudioSound::length
669 // Access: public
670 // Description: Get length
671 ////////////////////////////////////////////////////////////////////
672 PN_stdfloat OpenALAudioSound::
673 length() const {
674  return _length;
675 }
676 
677 ////////////////////////////////////////////////////////////////////
678 // Function: OpenALAudioSound::set_3d_attributes
679 // Access: public
680 // Description: Set position and velocity of this sound
681 //
682 // Both Panda3D and OpenAL use a right handed
683 // coordinate system. However, in Panda3D the
684 // Y-Axis is going into the Screen and the
685 // Z-Axis is going up. In OpenAL the Y-Axis is
686 // going up and the Z-Axis is coming out of
687 // the screen.
688 //
689 // The solution is simple, we just flip the Y
690 // and Z axis and negate the Z, as we move
691 // coordinates from Panda to OpenAL and back.
692 ////////////////////////////////////////////////////////////////////
694 set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
695  ReMutexHolder holder(OpenALAudioManager::_lock);
696  _location[0] = px;
697  _location[1] = pz;
698  _location[2] = -py;
699 
700  _velocity[0] = vx;
701  _velocity[1] = vz;
702  _velocity[2] = -vy;
703 
704  if (_source) {
705  _manager->make_current();
706 
707  alGetError(); // clear errors
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)");
712  }
713 }
714 
715 ////////////////////////////////////////////////////////////////////
716 // Function: OpenALAudioSound::get_3d_attributes
717 // Access: public
718 // Description: Get position and velocity of this sound
719 // Currently unimplemented. Get the attributes of the attached object.
720 ////////////////////////////////////////////////////////////////////
722 get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
723  ReMutexHolder holder(OpenALAudioManager::_lock);
724  *px = _location[0];
725  *py = -_location[2];
726  *pz = _location[1];
727 
728  *vx = _velocity[0];
729  *vy = -_velocity[2];
730  *vz = _velocity[1];
731 }
732 
733 ////////////////////////////////////////////////////////////////////
734 // Function: OpenALAudioSound::set_3d_min_distance
735 // Access: public
736 // Description: Set the distance that this sound begins to fall off. Also
737 // affects the rate it falls off.
738 ////////////////////////////////////////////////////////////////////
740 set_3d_min_distance(PN_stdfloat dist) {
741  ReMutexHolder holder(OpenALAudioManager::_lock);
742  _min_dist = dist;
743 
744  if (_source) {
745  _manager->make_current();
746 
747  alGetError(); // clear errors
748  alSourcef(_source,AL_REFERENCE_DISTANCE,_min_dist*_manager->audio_3d_get_distance_factor());
749  al_audio_errcheck("alSourcefv(_source,AL_REFERENCE_DISTANCE)");
750  }
751 }
752 
753 ////////////////////////////////////////////////////////////////////
754 // Function: OpenALAudioSound::get_3d_min_distance
755 // Access: public
756 // Description: Get the distance that this sound begins to fall off
757 ////////////////////////////////////////////////////////////////////
758 PN_stdfloat OpenALAudioSound::
760  return _min_dist;
761 }
762 
763 ////////////////////////////////////////////////////////////////////
764 // Function: OpenALAudioSound::set_3d_max_distance
765 // Access: public
766 // Description: Set the distance that this sound stops falling off
767 ////////////////////////////////////////////////////////////////////
769 set_3d_max_distance(PN_stdfloat dist) {
770  ReMutexHolder holder(OpenALAudioManager::_lock);
771  _max_dist = dist;
772 
773  if (_source) {
774  _manager->make_current();
775 
776  alGetError(); // clear errors
777  alSourcef(_source,AL_MAX_DISTANCE,_max_dist*_manager->audio_3d_get_distance_factor());
778  al_audio_errcheck("alSourcefv(_source,AL_MAX_DISTANCE)");
779  }
780 }
781 
782 ////////////////////////////////////////////////////////////////////
783 // Function: OpenALAudioSound::get_3d_max_distance
784 // Access: public
785 // Description: Get the distance that this sound stops falling off
786 ////////////////////////////////////////////////////////////////////
787 PN_stdfloat OpenALAudioSound::
789  return _max_dist;
790 }
791 
792 ////////////////////////////////////////////////////////////////////
793 // Function: OpenALAudioSound::set_3d_drop_off_factor
794 // Access: public
795 // Description: Control the effect distance has on audability.
796 // Defaults to 1.0
797 ////////////////////////////////////////////////////////////////////
799 set_3d_drop_off_factor(PN_stdfloat factor) {
800  ReMutexHolder holder(OpenALAudioManager::_lock);
801  _drop_off_factor = factor;
802 
803  if (_source) {
804  _manager->make_current();
805 
806  alGetError(); // clear errors
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)");
809  }
810 }
811 
812 ////////////////////////////////////////////////////////////////////
813 // Function: OpenALAudioSound::get_3d_drop_off_factor
814 // Access: public
815 // Description: Control the effect distance has on audability.
816 // Defaults to 1.0
817 ////////////////////////////////////////////////////////////////////
818 PN_stdfloat OpenALAudioSound::
820  return _drop_off_factor;
821 }
822 
823 ////////////////////////////////////////////////////////////////////
824 // Function: OpenALAudioSound::set_active
825 // Access: public
826 // Description: Sets whether the sound is marked "active". By
827 // default, the active flag true for all sounds. If the
828 // active flag is set to false for any particular sound,
829 // the sound will not be heard.
830 ////////////////////////////////////////////////////////////////////
832 set_active(bool active) {
833  ReMutexHolder holder(OpenALAudioManager::_lock);
834  if (_active!=active) {
835  _active=active;
836  if (_active) {
837  // ...activate the sound.
838  if (_paused && _loop_count==0) {
839  // ...this sound was looping when it was paused.
840  _paused=false;
841  play();
842  }
843  } else {
844  // ...deactivate the sound.
845  if (status()==PLAYING) {
846  if (_loop_count==0) {
847  // ...we're pausing a looping sound.
848  _paused=true;
849  }
850  stop();
851  }
852  }
853  }
854 }
855 
856 
857 ////////////////////////////////////////////////////////////////////
858 // Function: OpenALAudioSound::get_active
859 // Access: public
860 // Description: Returns whether the sound has been marked "active".
861 ////////////////////////////////////////////////////////////////////
863 get_active() const {
864  return _active;
865 }
866 
867 ////////////////////////////////////////////////////////////////////
868 // Function: OpenALAudioSound::set_finished_event
869 // Access:
870 // Description:
871 ////////////////////////////////////////////////////////////////////
872 void OpenALAudioSound::
873 set_finished_event(const string& event) {
874  _finished_event = event;
875 }
876 
877 ////////////////////////////////////////////////////////////////////
878 // Function: OpenALAudioSound::get_finished_event
879 // Access:
880 // Description:
881 ////////////////////////////////////////////////////////////////////
882 const string& OpenALAudioSound::
883 get_finished_event() const {
884  return _finished_event;
885 }
886 
887 ////////////////////////////////////////////////////////////////////
888 // Function: OpenALAudioSound::get_name
889 // Access: public
890 // Description: Get name of sound file
891 ////////////////////////////////////////////////////////////////////
892 const string& OpenALAudioSound::
893 get_name() const {
894  return _basename;
895 }
896 
897 ////////////////////////////////////////////////////////////////////
898 // Function: OpenALAudioSound::status
899 // Access: public
900 // Description: Get status of the sound.
901 //
902 // This returns the status as of the
903 // last push_fresh_buffers
904 ////////////////////////////////////////////////////////////////////
905 AudioSound::SoundStatus OpenALAudioSound::
906 status() const {
907  ReMutexHolder holder(OpenALAudioManager::_lock);
908  if (_source==0) {
909  return AudioSound::READY;
910  }
911  if ((_loops_completed >= _playing_loops)&&(_stream_queued.size()==0)) {
912  return AudioSound::READY;
913  } else {
914  return AudioSound::PLAYING;
915  }
916 }
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.
Definition: trueClock.I:81
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.
Definition: addHash.I:22
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.
void stop()
Stop a sound.
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.
Definition: reMutexHolder.h:27
const Filename & get_filename() const
Returns the movie&#39;s filename.
Definition: movieAudio.I:23
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&#39;s internal 0.0 to 255.0 scale.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
void set_loop(bool loop=true)
Turns looping on and off.
A MovieAudio is actually any source that provides a sequence of audio samples.
Definition: movieAudio.h:48
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.