00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "pandabase.h"
00017
00018 #ifdef HAVE_OPENAL //[
00019
00020
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
00038
00039
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
00096
00097
00098
00099 OpenALAudioSound::
00100 ~OpenALAudioSound() {
00101 cleanup();
00102 }
00103
00104
00105
00106
00107
00108
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
00129
00130
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();
00157
00158
00159 alSourcei(_source,AL_SOURCE_RELATIVE,_positional?AL_FALSE:AL_TRUE);
00160 al_audio_errcheck("alSourcei(_source,AL_SOURCE_RELATIVE)");
00161
00162
00163 set_volume(_volume);
00164
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
00204
00205
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();
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
00236
00237
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
00251
00252
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
00262
00263
00264
00265 bool OpenALAudioSound::
00266 get_loop() const {
00267 return (_loop_count == 0);
00268 }
00269
00270
00271
00272
00273
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
00288
00289
00290
00291 unsigned long OpenALAudioSound::
00292 get_loop_count() const {
00293 return _loop_count;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
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
00323
00324
00325
00326 void OpenALAudioSound::
00327 queue_buffer(ALuint buffer, int samples, int loop_index, double time_offset) {
00328 ReMutexHolder holder(OpenALAudioManager::_lock);
00329
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
00348
00349
00350
00351 ALuint OpenALAudioSound::
00352 make_buffer(int samples, int channels, int rate, unsigned char *data) {
00353 ReMutexHolder holder(OpenALAudioManager::_lock);
00354
00355
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
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
00381
00382
00383
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
00432
00433
00434
00435
00436
00437
00438
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
00470
00471
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
00504
00505
00506
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
00548
00549
00550
00551
00552 void OpenALAudioSound::
00553 set_time(PN_stdfloat time) {
00554 ReMutexHolder holder(OpenALAudioManager::_lock);
00555 _start_time = time;
00556 }
00557
00558
00559
00560
00561
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
00574
00575
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
00592
00593
00594
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();
00605 alSourcef(_source,AL_GAIN,volume);
00606 al_audio_errcheck("alSourcef(_source,AL_GAIN)");
00607 }
00608 }
00609
00610
00611
00612
00613
00614
00615 PN_stdfloat OpenALAudioSound::
00616 get_volume() const {
00617 return _volume;
00618 }
00619
00620
00621
00622
00623
00624
00625 void OpenALAudioSound::
00626 set_balance(PN_stdfloat balance_right) {
00627 audio_debug("OpenALAudioSound::set_balance() not implemented");
00628 }
00629
00630
00631
00632
00633
00634
00635
00636
00637 PN_stdfloat OpenALAudioSound::
00638 get_balance() const {
00639 audio_debug("OpenALAudioSound::get_balance() not implemented");
00640 return 0;
00641 }
00642
00643
00644
00645
00646
00647
00648
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
00661
00662
00663
00664 PN_stdfloat OpenALAudioSound::
00665 get_play_rate() const {
00666 return _play_rate;
00667 }
00668
00669
00670
00671
00672
00673
00674 PN_stdfloat OpenALAudioSound::
00675 length() const {
00676 return _length;
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
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();
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
00719
00720
00721
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
00737
00738
00739
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();
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
00757
00758
00759
00760 PN_stdfloat OpenALAudioSound::
00761 get_3d_min_distance() const {
00762 return _min_dist;
00763 }
00764
00765
00766
00767
00768
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();
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
00786
00787
00788
00789 PN_stdfloat OpenALAudioSound::
00790 get_3d_max_distance() const {
00791 return _max_dist;
00792 }
00793
00794
00795
00796
00797
00798
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();
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
00816
00817
00818
00819
00820 PN_stdfloat OpenALAudioSound::
00821 get_3d_drop_off_factor() const {
00822 return _drop_off_factor;
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
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
00840 if (_paused && _loop_count==0) {
00841
00842 _paused=false;
00843 play();
00844 }
00845 } else {
00846
00847 if (status()==PLAYING) {
00848 if (_loop_count==0) {
00849
00850 _paused=true;
00851 }
00852 stop();
00853 }
00854 }
00855 }
00856 }
00857
00858
00859
00860
00861
00862
00863
00864 bool OpenALAudioSound::
00865 get_active() const {
00866 return _active;
00867 }
00868
00869
00870
00871
00872
00873
00874 void OpenALAudioSound::
00875 set_finished_event(const string& event) {
00876 _finished_event = event;
00877 }
00878
00879
00880
00881
00882
00883
00884 const string& OpenALAudioSound::
00885 get_finished_event() const {
00886 return _finished_event;
00887 }
00888
00889
00890
00891
00892
00893
00894 const string& OpenALAudioSound::
00895 get_name() const {
00896 return _basename;
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
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 //]