Panda3D
|
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 //]