Panda3D
 All Classes Functions Variables Enumerations
openalAudioSound.cxx
00001 // Filename: openalAudioSound.cxx
00002 // Created by:  Ben Buchwald <bb2@alumni.cmu.edu>
00003 //
00004 //
00005 ////////////////////////////////////////////////////////////////////
00006 //
00007 // PANDA 3D SOFTWARE
00008 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00009 //
00010 // All use of this software is subject to the terms of the revised BSD
00011 // license.  You should have received a copy of this license along
00012 // with this source code in a file named "LICENSE."
00013 //
00014 ////////////////////////////////////////////////////////////////////
00015 
00016 #include "pandabase.h"
00017 
00018 #ifdef HAVE_OPENAL //[
00019 
00020 //Panda Headers
00021 #include "throw_event.h"
00022 #include "openalAudioSound.h"
00023 #include "openalAudioManager.h"
00024 
00025 TypeHandle OpenALAudioSound::_type_handle;
00026 
00027 
00028 #ifndef NDEBUG //[
00029   #define openal_audio_debug(x) \
00030       audio_debug("OpenALAudioSound \""<<get_name() \
00031       <<"\" "<< x )
00032 #else //][
00033 #define openal_audio_debug(x) ((void)0)
00034 #endif //]
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: OpenALAudioSound::Constructor
00038 //       Access: Private
00039 //  Description: 
00040 ////////////////////////////////////////////////////////////////////
00041 
00042 OpenALAudioSound::
00043 OpenALAudioSound(OpenALAudioManager* manager,
00044                  MovieAudio *movie,
00045                  bool positional,
00046                  int mode) :
00047   _movie(movie),
00048   _sd(NULL),
00049   _playing_loops(0),
00050   _playing_rate(0.0),
00051   _loops_completed(0),
00052   _source(0),
00053   _manager(manager),
00054   _volume(1.0f),
00055   _balance(0),
00056   _play_rate(1.0),
00057   _positional(positional),
00058   _min_dist(3.28f),
00059   _max_dist(1000000000.0f),
00060   _drop_off_factor(1.0f),
00061   _length(0.0),
00062   _loop_count(1),
00063   _desired_mode(mode),
00064   _start_time(0.0),
00065   _current_time(0.0),
00066   _basename(movie->get_filename().get_basename()),
00067   _active(true),
00068   _paused(false)
00069 {
00070   _location[0] = 0.0f;
00071   _location[1] = 0.0f;
00072   _location[2] = 0.0f;
00073   _velocity[0] = 0.0f;
00074   _velocity[1] = 0.0f;
00075   _velocity[2] = 0.0f;
00076 
00077   ReMutexHolder holder(OpenALAudioManager::_lock);
00078 
00079   require_sound_data();
00080   if (_manager == NULL) {
00081     return;
00082   }
00083 
00084   _length = _sd->_length;
00085   if (positional) {
00086     if (_sd->_channels != 1) {
00087       audio_warning("stereo sound " << movie->get_filename() << " will not be spatialized");
00088     }
00089   }
00090   release_sound_data();
00091 }
00092 
00093 
00094 ////////////////////////////////////////////////////////////////////
00095 //     Function: OpenALAudioSound::Destructor
00096 //       Access: public
00097 //  Description: 
00098 ////////////////////////////////////////////////////////////////////
00099 OpenALAudioSound::
00100 ~OpenALAudioSound() {
00101   cleanup();
00102 }
00103 
00104 ////////////////////////////////////////////////////////////////////
00105 //     Function: OpenALAudioSound::cleanup
00106 //       Access: Private
00107 //  Description: Disables the sound forever.  Releases resources and
00108 //               detaches the sound from its audio manager.
00109 ////////////////////////////////////////////////////////////////////
00110 void OpenALAudioSound::
00111 cleanup() {
00112   ReMutexHolder holder(OpenALAudioManager::_lock);
00113   if (_manager == 0) {
00114     return;
00115   }
00116   if (_source) {
00117     stop();
00118   }
00119   if (_sd) {
00120     _manager->decrement_client_count(_sd);
00121     _sd = 0;
00122   }
00123   _manager->release_sound(this);
00124   _manager = 0;
00125 }
00126 
00127 ////////////////////////////////////////////////////////////////////
00128 //     Function: OpenALAudioSound::play
00129 //       Access: public
00130 //  Description: Plays a sound.
00131 ////////////////////////////////////////////////////////////////////
00132 void OpenALAudioSound::
00133 play() {
00134   ReMutexHolder holder(OpenALAudioManager::_lock);
00135   if (_manager == 0) return;
00136 
00137   PN_stdfloat px,py,pz,vx,vy,vz;
00138   
00139   if (!_active) {
00140     _paused = true;
00141     return;
00142   }
00143   
00144   stop();
00145 
00146   require_sound_data();
00147   if (_manager == 0) return;
00148   _manager->starting_sound(this);
00149 
00150   if (!_source) {
00151     return;
00152   }
00153   
00154   _manager->make_current();
00155   
00156   alGetError(); // clear errors
00157   
00158   // nonpositional sources are made relative to the listener so they don't move
00159   alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE);
00160   al_audio_errcheck("alSourcei(_source,AL_SOURCE_RELATIVE)");
00161   
00162   // set source properties that we have stored
00163   set_volume(_volume);
00164   //set_balance(_balance);
00165 
00166   set_3d_min_distance(_min_dist);
00167   set_3d_max_distance(_max_dist);
00168   set_3d_drop_off_factor(_drop_off_factor);
00169   get_3d_attributes(&px,&py,&pz,&vx,&vy,&vz);
00170   set_3d_attributes(px, py, pz, vx, vy, vz);
00171   
00172   _playing_loops = _loop_count;
00173   if (_playing_loops == 0) {
00174     _playing_loops = 1000000000;
00175   }
00176   _loops_completed = 0;
00177 
00178   double play_rate = _play_rate * _manager->get_play_rate();
00179   audio_debug("playing. Rate=" << play_rate);
00180   alSourcef(_source, AL_PITCH, play_rate);
00181   _playing_rate = play_rate;
00182   
00183   if (_sd->_sample) {
00184     push_fresh_buffers();
00185     alSourcef(_source, AL_SEC_OFFSET, _start_time);
00186     _stream_queued[0]._time_offset = _start_time;
00187     restart_stalled_audio();
00188   } else {
00189     audio_debug("Play: stream tell = " << _sd->_stream->tell() << " seeking " << _start_time); 
00190     if (_sd->_stream->tell() != _start_time) {
00191       _sd->_stream->seek(_start_time);
00192     }
00193     push_fresh_buffers();
00194     restart_stalled_audio();
00195   }
00196   double rtc = TrueClock::get_global_ptr()->get_short_time();
00197   set_calibrated_clock(rtc, _start_time, 1.0);
00198   _current_time = _start_time;
00199   _start_time = 0.0;
00200 }
00201 
00202 ////////////////////////////////////////////////////////////////////
00203 //     Function: OpenALAudioSound::stop
00204 //       Access: public
00205 //  Description: Stop a sound
00206 ////////////////////////////////////////////////////////////////////
00207 void OpenALAudioSound::
00208 stop() {
00209   ReMutexHolder holder(OpenALAudioManager::_lock);
00210   if (_manager==0) return;
00211 
00212   if (_source) {
00213     _manager->make_current();
00214 
00215     alGetError(); // clear errors
00216     alSourceStop(_source);
00217     al_audio_errcheck("stopping a source");
00218     alSourcei(_source, AL_BUFFER, 0);
00219     al_audio_errcheck("clear source buffers");
00220     for (int i=0; i<((int)(_stream_queued.size())); i++) {
00221       ALuint buffer = _stream_queued[i]._buffer;
00222       if (buffer != _sd->_sample) {
00223         alDeleteBuffers(1, &buffer);
00224         al_audio_errcheck("deleting a buffer");
00225       }
00226     }
00227     _stream_queued.resize(0);
00228   }
00229   
00230   _manager->stopping_sound(this);
00231   release_sound_data();
00232 }
00233 
00234 ////////////////////////////////////////////////////////////////////
00235 //     Function: OpenALAudioSound::finished
00236 //       Access: 
00237 //  Description: 
00238 ////////////////////////////////////////////////////////////////////
00239 void OpenALAudioSound::
00240 finished() {
00241   ReMutexHolder holder(OpenALAudioManager::_lock);
00242   stop();
00243   _current_time = _length;
00244   if (!_finished_event.empty()) {
00245     throw_event(_finished_event);
00246   }
00247 }
00248 
00249 ////////////////////////////////////////////////////////////////////
00250 //     Function: OpenALAudioSound::set_loop
00251 //       Access: public
00252 //  Description: Turns looping on and off
00253 ////////////////////////////////////////////////////////////////////
00254 void OpenALAudioSound::
00255 set_loop(bool loop) {
00256   ReMutexHolder holder(OpenALAudioManager::_lock);
00257   set_loop_count((loop)?0:1);
00258 }
00259 
00260 ////////////////////////////////////////////////////////////////////
00261 //     Function: OpenALAudioSound::get_loop
00262 //       Access: public
00263 //  Description: Returns whether looping is on or off
00264 ////////////////////////////////////////////////////////////////////
00265 bool OpenALAudioSound::
00266 get_loop() const {
00267   return (_loop_count == 0);
00268 }
00269 
00270 ////////////////////////////////////////////////////////////////////
00271 //     Function: OpenALAudioSound::set_loop_count
00272 //       Access: public
00273 //  Description: 
00274 ////////////////////////////////////////////////////////////////////
00275 void OpenALAudioSound::
00276 set_loop_count(unsigned long loop_count) {
00277   ReMutexHolder holder(OpenALAudioManager::_lock);
00278   if (_manager==0) return;
00279   
00280   if (loop_count >= 1000000000) {
00281     loop_count = 0;
00282   }
00283   _loop_count=loop_count;
00284 }
00285 
00286 ////////////////////////////////////////////////////////////////////
00287 //     Function: OpenALAudioSound::get_loop_count
00288 //       Access: public
00289 //  Description: Return how many times a sound will loop.
00290 ////////////////////////////////////////////////////////////////////
00291 unsigned long OpenALAudioSound::
00292 get_loop_count() const {
00293   return _loop_count;
00294 }
00295 
00296 ////////////////////////////////////////////////////////////////////
00297 //     Function: OpenALAudioSound::restart_stalled_audio
00298 //       Access: public
00299 //  Description: When streaming audio, the computer is supposed to 
00300 //               keep OpenAL's queue full.  However, there are times
00301 //               when the computer is running slow and the queue 
00302 //               empties prematurely.  In that case, OpenAL will stop.
00303 //               When the computer finally gets around to refilling
00304 //               the queue, it is necessary to tell OpenAL to resume
00305 //               playing.
00306 ////////////////////////////////////////////////////////////////////
00307 void OpenALAudioSound::
00308 restart_stalled_audio() {
00309   ReMutexHolder holder(OpenALAudioManager::_lock);
00310   ALenum status;
00311   if (_stream_queued.size() == 0) {
00312     return;
00313   }
00314   alGetError();
00315   alGetSourcei(_source, AL_SOURCE_STATE, &status);
00316   if (status != AL_PLAYING) {
00317     alSourcePlay(_source);
00318   }
00319 }
00320 
00321 ////////////////////////////////////////////////////////////////////
00322 //     Function: OpenALAudioSound::queue_buffer
00323 //       Access: public
00324 //  Description: Pushes a buffer into the source queue.
00325 ////////////////////////////////////////////////////////////////////
00326 void OpenALAudioSound::
00327 queue_buffer(ALuint buffer, int samples, int loop_index, double time_offset) {
00328   ReMutexHolder holder(OpenALAudioManager::_lock);
00329   // Now push the buffer into the stream queue.
00330   alGetError();
00331   alSourceQueueBuffers(_source,1,&buffer);
00332   ALenum err = alGetError();
00333   if (err != AL_NO_ERROR) {
00334     audio_error("could not load sample buffer into the queue");
00335     cleanup();
00336     return;
00337   }
00338   QueuedBuffer buf;
00339   buf._buffer = buffer;
00340   buf._samples = samples;
00341   buf._loop_index = loop_index;
00342   buf._time_offset = time_offset;
00343   _stream_queued.push_back(buf);
00344 }
00345 
00346 ////////////////////////////////////////////////////////////////////
00347 //     Function: OpenALAudioSound::make_buffer
00348 //       Access: public
00349 //  Description: Creates an OpenAL buffer object.
00350 ////////////////////////////////////////////////////////////////////
00351 ALuint OpenALAudioSound::
00352 make_buffer(int samples, int channels, int rate, unsigned char *data) {
00353   ReMutexHolder holder(OpenALAudioManager::_lock);
00354   
00355   // Allocate a buffer to hold the data.
00356   alGetError();
00357   ALuint buffer;
00358   alGenBuffers(1, &buffer);
00359   if (alGetError() != AL_NO_ERROR) {
00360     audio_error("could not allocate an OpenAL buffer object");
00361     cleanup();
00362     return 0;
00363   }
00364   
00365   // Now fill the buffer with the data provided.
00366   alBufferData(buffer,
00367                (channels>1) ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16,
00368                data, samples * channels * 2, rate);
00369   int err = alGetError();
00370   if (err != AL_NO_ERROR) {
00371     audio_error("could not fill OpenAL buffer object with data");
00372     cleanup();
00373     return 0;
00374   }
00375   
00376   return buffer;
00377 }
00378 
00379 ////////////////////////////////////////////////////////////////////
00380 //     Function: OpenALAudioSound::read_stream_data
00381 //       Access: public
00382 //  Description: Fills a buffer with data from the stream.
00383 //               Returns the number of samples stored in the buffer.
00384 ////////////////////////////////////////////////////////////////////
00385 int OpenALAudioSound::
00386 read_stream_data(int bytelen, unsigned char *buffer) {
00387   ReMutexHolder holder(OpenALAudioManager::_lock);
00388 
00389   MovieAudioCursor *cursor = _sd->_stream;
00390   double length = cursor->length();
00391   int channels = cursor->audio_channels();
00392   int rate = cursor->audio_rate();
00393   int space = bytelen / (channels * 2);
00394   int fill = 0;
00395   
00396   while (space && (_loops_completed < _playing_loops)) {
00397     double t = cursor->tell();
00398     double remain = length - t;
00399     if (remain > 60.0) {
00400       remain = 60.0;
00401     }
00402     int samples = (int)(remain * rate);
00403     if (samples <= 0) {
00404       _loops_completed += 1;
00405       cursor->seek(0.0);
00406       continue;
00407     }
00408     if (_sd->_stream->ready() == 0) {
00409       if (_sd->_stream->aborted()) {
00410         _loops_completed = _playing_loops;
00411       }
00412       return fill;
00413     }
00414     if (samples > space) {
00415       samples = space;
00416     }
00417     if (samples > _sd->_stream->ready()) {
00418       samples = _sd->_stream->ready();
00419     }
00420     cursor->read_samples(samples, (PN_int16 *)buffer);
00421     size_t hval = AddHash::add_hash(0, (PN_uint8*)buffer, samples*channels*2);
00422     audio_debug("Streaming " << cursor->get_source()->get_name() << " at " << t << " hash " << hval);
00423     fill += samples;
00424     space -= samples;
00425     buffer += (samples * channels * 2);
00426   }
00427   return fill; 
00428 }
00429 
00430 ////////////////////////////////////////////////////////////////////
00431 //     Function: OpenALAudioSound::correct_calibrated_clock
00432 //       Access: public
00433 //  Description: Compares the specified time to the value of the
00434 //               calibrated clock, and adjusts the calibrated
00435 //               clock speed to make it closer to the target value.
00436 //               This routine is quite careful to make sure that
00437 //               the calibrated clock moves in a smooth, monotonic
00438 //               way.
00439 ////////////////////////////////////////////////////////////////////
00440 void OpenALAudioSound::
00441 correct_calibrated_clock(double rtc, double t) {
00442   ReMutexHolder holder(OpenALAudioManager::_lock);
00443   double cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
00444   double diff = cc-t;
00445   _calibrated_clock_decavg = (_calibrated_clock_decavg * 0.95) + (diff * 0.05);
00446   if (diff > 0.5) {
00447     set_calibrated_clock(rtc, t, 1.0);
00448     _calibrated_clock_decavg = 0.0;
00449   } else {
00450     double scale = 1.0;
00451     if ((_calibrated_clock_decavg > 0.01) && (diff > 0.01)) {
00452       scale = 0.98;
00453     }
00454     if ((_calibrated_clock_decavg < -0.01) && (diff < -0.01)) {
00455       scale = 1.03;
00456     }
00457     if ((_calibrated_clock_decavg < -0.05) && (diff < -0.05)) {
00458       scale = 1.2;
00459     }
00460     if ((_calibrated_clock_decavg < -0.15) && (diff < -0.15)) {
00461       scale = 1.5;
00462     }
00463     set_calibrated_clock(rtc, cc, scale);
00464   }
00465   cc = (rtc - _calibrated_clock_base) * _calibrated_clock_scale;
00466 }
00467 
00468 ////////////////////////////////////////////////////////////////////
00469 //     Function: OpenALAudioSound::pull_used_buffers
00470 //       Access: public
00471 //  Description: Pulls any used buffers out of OpenAL's queue.
00472 ////////////////////////////////////////////////////////////////////
00473 void OpenALAudioSound::
00474 pull_used_buffers() {
00475   ReMutexHolder holder(OpenALAudioManager::_lock);
00476   while (_stream_queued.size()) {
00477     ALuint buffer = 0;
00478     alGetError();
00479     alSourceUnqueueBuffers(_source, 1, &buffer);
00480     int err = alGetError();
00481     if (err == AL_NO_ERROR) {
00482       if (_stream_queued[0]._buffer != buffer) {
00483         audio_error("corruption in stream queue");
00484         cleanup();
00485         return;
00486       }
00487       _stream_queued.pop_front();
00488       if (_stream_queued.size()) {
00489         double al = _stream_queued[0]._time_offset + _stream_queued[0]._loop_index * _length;
00490         double rtc = TrueClock::get_global_ptr()->get_short_time();
00491         correct_calibrated_clock(rtc, al);
00492       }
00493       if (buffer != _sd->_sample) {
00494         alDeleteBuffers(1,&buffer);
00495       }
00496     } else {
00497       break;
00498     }
00499   }
00500 }
00501 
00502 ////////////////////////////////////////////////////////////////////
00503 //     Function: OpenALAudioSound::push_fresh_buffers
00504 //       Access: public
00505 //  Description: Pushes fresh buffers into OpenAL's queue until
00506 //               the queue is "full" (ie, has plenty of data).
00507 ////////////////////////////////////////////////////////////////////
00508 void OpenALAudioSound::
00509 push_fresh_buffers() {
00510   ReMutexHolder holder(OpenALAudioManager::_lock);
00511   static unsigned char data[65536];
00512   
00513   if (_sd->_sample) {
00514     while ((_loops_completed < _playing_loops) &&
00515            (_stream_queued.size() < 100)) {
00516       queue_buffer(_sd->_sample, 0,_loops_completed, 0.0);
00517       _loops_completed += 1;
00518     }
00519   } else {
00520     MovieAudioCursor *cursor = _sd->_stream;
00521     int channels = cursor->audio_channels();
00522     int rate = cursor->audio_rate();
00523     
00524     int fill = 0;
00525     for (size_t i = 0; i < _stream_queued.size(); i++) {
00526       fill += _stream_queued[i]._samples;
00527     }
00528     
00529     while ((_loops_completed < _playing_loops) &&
00530            (fill < (int)(audio_buffering_seconds * rate * channels))) {
00531       int loop_index = _loops_completed;
00532       double time_offset = cursor->tell();
00533       int samples = read_stream_data(65536, data);
00534       if (samples == 0) {
00535         break;
00536       }
00537       ALuint buffer = make_buffer(samples, channels, rate, data);
00538       if (_manager == 0) return;
00539       queue_buffer(buffer, samples, loop_index, time_offset);
00540       if (_manager == 0) return;
00541       fill += samples;
00542     }
00543   }
00544 }
00545 
00546 ////////////////////////////////////////////////////////////////////
00547 //     Function: OpenALAudioSound::set_time
00548 //       Access: public
00549 //  Description: The next time you call play, the sound will
00550 //               start from the specified offset.
00551 ////////////////////////////////////////////////////////////////////
00552 void OpenALAudioSound::
00553 set_time(PN_stdfloat time) {
00554   ReMutexHolder holder(OpenALAudioManager::_lock);
00555   _start_time = time;
00556 }
00557 
00558 ////////////////////////////////////////////////////////////////////
00559 //     Function: OpenALAudioSound::get_time
00560 //       Access: public
00561 //  Description: Gets the play position within the sound
00562 ////////////////////////////////////////////////////////////////////
00563 PN_stdfloat OpenALAudioSound::
00564 get_time() const {
00565   ReMutexHolder holder(OpenALAudioManager::_lock);
00566   if (_manager == 0) {
00567     return 0.0;
00568   }
00569   return _current_time;
00570 }
00571 
00572 ////////////////////////////////////////////////////////////////////
00573 //     Function: OpenALAudioSound::cache_time
00574 //       Access: Private
00575 //  Description: Updates the current_time field of a playing sound.
00576 ////////////////////////////////////////////////////////////////////
00577 void OpenALAudioSound::
00578 cache_time(double rtc) {
00579   ReMutexHolder holder(OpenALAudioManager::_lock);
00580   assert(_source != 0);
00581   double t=get_calibrated_clock(rtc);
00582   double max = _length * _playing_loops;
00583   if (t >= max) {
00584     _current_time = _length;
00585   } else {
00586     _current_time = fmod(t, _length);
00587   }
00588 }
00589 
00590 ////////////////////////////////////////////////////////////////////
00591 //     Function: OpenALAudioSound::set_volume(PN_stdfloat vol)
00592 //       Access: public
00593 //  Description: 0.0 to 1.0 scale of volume converted to Fmod's
00594 //               internal 0.0 to 255.0 scale.
00595 ////////////////////////////////////////////////////////////////////
00596 void OpenALAudioSound::
00597 set_volume(PN_stdfloat volume) {
00598   ReMutexHolder holder(OpenALAudioManager::_lock);
00599   _volume=volume;
00600 
00601   if (_source) {
00602     volume*=_manager->get_volume();
00603     _manager->make_current();
00604     alGetError(); // clear errors
00605     alSourcef(_source,AL_GAIN,volume);
00606     al_audio_errcheck("alSourcef(_source,AL_GAIN)");
00607   }
00608 }
00609 
00610 ////////////////////////////////////////////////////////////////////
00611 //     Function: OpenALAudioSound::get_volume
00612 //       Access: public
00613 //  Description: Gets the current volume of a sound.  1 is Max. O is Min.
00614 ////////////////////////////////////////////////////////////////////
00615 PN_stdfloat OpenALAudioSound::
00616 get_volume() const {
00617   return _volume;
00618 }
00619 
00620 ////////////////////////////////////////////////////////////////////
00621 //     Function: OpenALAudioSound::set_balance(PN_stdfloat bal)
00622 //       Access: public
00623 //  Description: -1.0 to 1.0 scale
00624 ////////////////////////////////////////////////////////////////////
00625 void OpenALAudioSound::
00626 set_balance(PN_stdfloat balance_right) {
00627   audio_debug("OpenALAudioSound::set_balance() not implemented");
00628 }
00629 
00630 ////////////////////////////////////////////////////////////////////
00631 //     Function: OpenALAudioSound::get_balance
00632 //       Access: public
00633 //  Description: -1.0 to 1.0 scale 
00634 //        -1 should be all the way left.
00635 //        1 is all the way to the right.
00636 ////////////////////////////////////////////////////////////////////
00637 PN_stdfloat OpenALAudioSound::
00638 get_balance() const {
00639   audio_debug("OpenALAudioSound::get_balance() not implemented");
00640   return 0;
00641 }
00642 
00643 ////////////////////////////////////////////////////////////////////
00644 //     Function: OpenALAudioSound::set_play_rate(PN_stdfloat rate)
00645 //       Access: public
00646 //  Description: Sets the speed at which a sound plays back.
00647 //        The rate is a multiple of the sound, normal playback speed.
00648 //        IE 2 would play back 2 times fast, 3 would play 3 times, and so on.
00649 ////////////////////////////////////////////////////////////////////
00650 void OpenALAudioSound::
00651 set_play_rate(PN_stdfloat play_rate) {
00652   ReMutexHolder holder(OpenALAudioManager::_lock);
00653   _play_rate = play_rate;
00654   if (_source) {
00655     alSourcef(_source, AL_PITCH, play_rate);
00656   }
00657 }
00658 
00659 ////////////////////////////////////////////////////////////////////
00660 //     Function: OpenALAudioSound::get_play_rate
00661 //       Access: public
00662 //  Description: 
00663 ////////////////////////////////////////////////////////////////////
00664 PN_stdfloat OpenALAudioSound::
00665 get_play_rate() const {
00666   return _play_rate;
00667 }
00668 
00669 ////////////////////////////////////////////////////////////////////
00670 //     Function: OpenALAudioSound::length
00671 //       Access: public
00672 //  Description: Get length
00673 ////////////////////////////////////////////////////////////////////
00674 PN_stdfloat OpenALAudioSound::
00675 length() const {
00676   return _length;
00677 }
00678 
00679 ////////////////////////////////////////////////////////////////////
00680 //     Function: OpenALAudioSound::set_3d_attributes
00681 //       Access: public
00682 //  Description: Set position and velocity of this sound
00683 //
00684 //               Both Panda3D and OpenAL use a right handed
00685 //               coordinate system.  However, in Panda3D the
00686 //               Y-Axis is going into the Screen and the
00687 //               Z-Axis is going up.  In OpenAL the Y-Axis is
00688 //               going up and the Z-Axis is coming out of
00689 //               the screen.
00690 //
00691 //               The solution is simple, we just flip the Y
00692 //               and Z axis and negate the Z, as we move
00693 //               coordinates from Panda to OpenAL and back.
00694 ////////////////////////////////////////////////////////////////////
00695 void OpenALAudioSound::
00696 set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
00697   ReMutexHolder holder(OpenALAudioManager::_lock);
00698   _location[0] = px;
00699   _location[1] = pz;
00700   _location[2] = -py; 
00701 
00702   _velocity[0] = vx;
00703   _velocity[1] = vz;
00704   _velocity[2] = -vy;
00705 
00706   if (_source) {
00707     _manager->make_current();
00708 
00709     alGetError(); // clear errors
00710     alSourcefv(_source,AL_POSITION,_location);
00711     al_audio_errcheck("alSourcefv(_source,AL_POSITION)");
00712     alSourcefv(_source,AL_VELOCITY,_velocity);
00713     al_audio_errcheck("alSourcefv(_source,AL_VELOCITY)");
00714   }
00715 }
00716 
00717 ////////////////////////////////////////////////////////////////////
00718 //     Function: OpenALAudioSound::get_3d_attributes
00719 //       Access: public
00720 //  Description: Get position and velocity of this sound
00721 //         Currently unimplemented. Get the attributes of the attached object.
00722 ////////////////////////////////////////////////////////////////////
00723 void OpenALAudioSound::
00724 get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
00725   ReMutexHolder holder(OpenALAudioManager::_lock);
00726   *px = _location[0];
00727   *py = -_location[2];
00728   *pz = _location[1];
00729 
00730   *vx = _velocity[0];
00731   *vy = -_velocity[2];
00732   *vz = _velocity[1];
00733 }
00734 
00735 ////////////////////////////////////////////////////////////////////
00736 //     Function: OpenALAudioSound::set_3d_min_distance
00737 //       Access: public
00738 //  Description: Set the distance that this sound begins to fall off. Also
00739 //               affects the rate it falls off.
00740 ////////////////////////////////////////////////////////////////////
00741 void OpenALAudioSound::
00742 set_3d_min_distance(PN_stdfloat dist) {
00743   ReMutexHolder holder(OpenALAudioManager::_lock);
00744   _min_dist = dist;
00745 
00746   if (_source) {
00747     _manager->make_current();
00748 
00749     alGetError(); // clear errors
00750     alSourcef(_source,AL_REFERENCE_DISTANCE,_min_dist*_manager->audio_3d_get_distance_factor());
00751     al_audio_errcheck("alSourcefv(_source,AL_REFERENCE_DISTANCE)");
00752   }
00753 }
00754 
00755 ////////////////////////////////////////////////////////////////////
00756 //     Function: OpenALAudioSound::get_3d_min_distance
00757 //       Access: public
00758 //  Description: Get the distance that this sound begins to fall off
00759 ////////////////////////////////////////////////////////////////////
00760 PN_stdfloat OpenALAudioSound::
00761 get_3d_min_distance() const {
00762   return _min_dist;
00763 }
00764 
00765 ////////////////////////////////////////////////////////////////////
00766 //     Function: OpenALAudioSound::set_3d_max_distance
00767 //       Access: public
00768 //  Description: Set the distance that this sound stops falling off
00769 ////////////////////////////////////////////////////////////////////
00770 void OpenALAudioSound::
00771 set_3d_max_distance(PN_stdfloat dist) {
00772   ReMutexHolder holder(OpenALAudioManager::_lock);
00773   _max_dist = dist;
00774 
00775   if (_source) {
00776     _manager->make_current();
00777 
00778     alGetError(); // clear errors
00779     alSourcef(_source,AL_MAX_DISTANCE,_max_dist*_manager->audio_3d_get_distance_factor());
00780     al_audio_errcheck("alSourcefv(_source,AL_MAX_DISTANCE)");
00781   }
00782 }
00783 
00784 ////////////////////////////////////////////////////////////////////
00785 //     Function: OpenALAudioSound::get_3d_max_distance
00786 //       Access: public
00787 //  Description: Get the distance that this sound stops falling off
00788 ////////////////////////////////////////////////////////////////////
00789 PN_stdfloat OpenALAudioSound::
00790 get_3d_max_distance() const {
00791   return _max_dist;
00792 }
00793 
00794 ////////////////////////////////////////////////////////////////////
00795 //     Function: OpenALAudioSound::set_3d_drop_off_factor
00796 //       Access: public
00797 //  Description: Control the effect distance has on audability.
00798 //               Defaults to 1.0
00799 ////////////////////////////////////////////////////////////////////
00800 void OpenALAudioSound::
00801 set_3d_drop_off_factor(PN_stdfloat factor) {
00802   ReMutexHolder holder(OpenALAudioManager::_lock);
00803   _drop_off_factor = factor;
00804 
00805   if (_source) {
00806     _manager->make_current();
00807 
00808     alGetError(); // clear errors
00809     alSourcef(_source,AL_ROLLOFF_FACTOR,_drop_off_factor*_manager->audio_3d_get_drop_off_factor());
00810     al_audio_errcheck("alSourcefv(_source,AL_ROLLOFF_FACTOR)");
00811   }
00812 }
00813 
00814 ////////////////////////////////////////////////////////////////////
00815 //     Function: OpenALAudioSound::get_3d_drop_off_factor
00816 //       Access: public
00817 //  Description: Control the effect distance has on audability.
00818 //               Defaults to 1.0
00819 ////////////////////////////////////////////////////////////////////
00820 PN_stdfloat OpenALAudioSound::
00821 get_3d_drop_off_factor() const {
00822   return _drop_off_factor;
00823 }
00824 
00825 ////////////////////////////////////////////////////////////////////
00826 //     Function: OpenALAudioSound::set_active
00827 //       Access: public
00828 //  Description: Sets whether the sound is marked "active".  By
00829 //               default, the active flag true for all sounds.  If the
00830 //               active flag is set to false for any particular sound,
00831 //               the sound will not be heard.
00832 ////////////////////////////////////////////////////////////////////
00833 void OpenALAudioSound::
00834 set_active(bool active) {
00835   ReMutexHolder holder(OpenALAudioManager::_lock);
00836   if (_active!=active) {
00837     _active=active;
00838     if (_active) {
00839       // ...activate the sound.
00840       if (_paused && _loop_count==0) {
00841         // ...this sound was looping when it was paused.
00842         _paused=false;
00843         play();
00844       }
00845     } else {
00846       // ...deactivate the sound.
00847       if (status()==PLAYING) {
00848         if (_loop_count==0) {
00849           // ...we're pausing a looping sound.
00850           _paused=true;
00851         }
00852         stop();
00853       }
00854     }
00855   }
00856 }
00857 
00858 
00859 ////////////////////////////////////////////////////////////////////
00860 //     Function: OpenALAudioSound::get_active 
00861 //       Access: public
00862 //  Description: Returns whether the sound has been marked "active".
00863 ////////////////////////////////////////////////////////////////////
00864 bool OpenALAudioSound::
00865 get_active() const {
00866   return _active;
00867 }
00868 
00869 ////////////////////////////////////////////////////////////////////
00870 //     Function: OpenALAudioSound::set_finished_event
00871 //       Access: 
00872 //  Description: 
00873 ////////////////////////////////////////////////////////////////////
00874 void OpenALAudioSound::
00875 set_finished_event(const string& event) {
00876   _finished_event = event;
00877 }
00878 
00879 ////////////////////////////////////////////////////////////////////
00880 //     Function: OpenALAudioSound::get_finished_event
00881 //       Access: 
00882 //  Description: 
00883 ////////////////////////////////////////////////////////////////////
00884 const string& OpenALAudioSound::
00885 get_finished_event() const {
00886   return _finished_event;
00887 }
00888 
00889 ////////////////////////////////////////////////////////////////////
00890 //     Function: OpenALAudioSound::get_name
00891 //       Access: public
00892 //  Description: Get name of sound file
00893 ////////////////////////////////////////////////////////////////////
00894 const string& OpenALAudioSound::
00895 get_name() const {
00896   return _basename;
00897 }
00898 
00899 ////////////////////////////////////////////////////////////////////
00900 //     Function: OpenALAudioSound::status
00901 //       Access: public
00902 //  Description: Get status of the sound.
00903 //
00904 //               This returns the status as of the
00905 //               last push_fresh_buffers
00906 ////////////////////////////////////////////////////////////////////
00907 AudioSound::SoundStatus OpenALAudioSound::
00908 status() const {
00909   ReMutexHolder holder(OpenALAudioManager::_lock);
00910   if (_source==0) {
00911     return AudioSound::READY;
00912   }
00913   if ((_loops_completed >= _playing_loops)&&(_stream_queued.size()==0)) {
00914     return AudioSound::READY;
00915   } else {
00916     return AudioSound::PLAYING;
00917   }
00918 }
00919 
00920 #endif //]
 All Classes Functions Variables Enumerations