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