Panda3D

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