00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "milesAudioSample.h"
00016
00017 #ifdef HAVE_RAD_MSS //[
00018
00019 #include "milesAudioManager.h"
00020
00021
00022 TypeHandle MilesAudioSample::_type_handle;
00023
00024 #undef miles_audio_debug
00025
00026 #ifndef NDEBUG //[
00027 #define miles_audio_debug(x) \
00028 audio_debug("MilesAudioSample \""<<get_name()<<"\" "<< x )
00029 #else //][
00030 #define miles_audio_debug(x) ((void)0)
00031 #endif //]
00032
00033
00034
00035
00036
00037
00038
00039 MilesAudioSample::
00040 MilesAudioSample(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
00041 const string &file_name) :
00042 MilesAudioSound(manager, file_name),
00043 _sd(sd)
00044 {
00045 nassertv(sd != NULL);
00046 audio_debug("MilesAudioSample(manager=0x"<<(void*)&manager
00047 <<", sd=0x"<<(void*)sd<<", file_name="<<file_name<<")");
00048
00049 _sample = 0;
00050 _sample_index = 0;
00051 _original_playback_rate = 1.0f;
00052 }
00053
00054
00055
00056
00057
00058
00059 MilesAudioSample::
00060 ~MilesAudioSample() {
00061 miles_audio_debug("~MilesAudioSample()");
00062 cleanup();
00063 miles_audio_debug("~MilesAudioSample() done");
00064 }
00065
00066
00067
00068
00069
00070
00071 void MilesAudioSample::
00072 play() {
00073 miles_audio_debug("play()");
00074 if (_active) {
00075 if (_sd->_raw_data.empty()) {
00076 milesAudio_cat.warning()
00077 << "Could not play " << _file_name << ": no data\n";
00078 } else {
00079 stop();
00080 _manager->starting_sound(this);
00081
00082 nassertv(_sample == 0);
00083
00084 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
00085 if (!mgr->get_sample(_sample, _sample_index, this)){
00086 milesAudio_cat.warning()
00087 << "Could not play " << _file_name << ": too many open samples\n";
00088 _sample = 0;
00089 } else {
00090 AIL_set_named_sample_file(_sample, _sd->_basename.c_str(),
00091 &_sd->_raw_data[0], _sd->_raw_data.size(),
00092 0);
00093 _original_playback_rate = AIL_sample_playback_rate(_sample);
00094 AIL_set_sample_user_data(_sample, 0, (SINTa)this);
00095 AIL_register_EOS_callback(_sample, finish_callback);
00096
00097 set_volume(_volume);
00098 set_play_rate(_play_rate);
00099 AIL_set_sample_loop_count(_sample, _loop_count);
00100
00101 if (_got_start_time) {
00102 do_set_time(_start_time);
00103 AIL_resume_sample(_sample);
00104 } else {
00105 AIL_start_sample(_sample);
00106 }
00107 }
00108
00109 _got_start_time = false;
00110 }
00111 } else {
00112
00113 audio_debug(" paused "<<_file_name );
00114 _paused = true;
00115 }
00116 }
00117
00118
00119
00120
00121
00122
00123 void MilesAudioSample::
00124 stop() {
00125 if (_manager == (MilesAudioManager *)NULL) {
00126 return;
00127 }
00128
00129 miles_audio_debug("stop()");
00130 _manager->stopping_sound(this);
00131
00132
00133
00134
00135
00136
00137
00138
00139 _paused = false;
00140
00141 if (_sample != 0) {
00142 AIL_end_sample(_sample);
00143
00144 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
00145 mgr->release_sample(_sample_index, this);
00146
00147 _sample = 0;
00148 _sample_index = 0;
00149 }
00150 }
00151
00152
00153
00154
00155
00156
00157 PN_stdfloat MilesAudioSample::
00158 get_time() const {
00159 if (_sample == 0) {
00160 if (_got_start_time) {
00161 return _start_time;
00162 }
00163 return 0.0f;
00164 }
00165
00166 S32 current_ms;
00167 AIL_sample_ms_position(_sample, NULL, ¤t_ms);
00168 PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
00169
00170 return time;
00171 }
00172
00173
00174
00175
00176
00177
00178 void MilesAudioSample::
00179 set_volume(PN_stdfloat volume) {
00180 miles_audio_debug("set_volume(volume="<<volume<<")");
00181
00182
00183
00184
00185
00186
00187 _volume = volume;
00188
00189 if (_sample != 0) {
00190 volume *= _manager->get_volume();
00191
00192
00193 F32 milesVolume = volume;
00194 milesVolume = min(milesVolume, 1.0f);
00195 milesVolume = max(milesVolume, 0.0f);
00196
00197
00198 F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f);
00199
00200 AIL_set_sample_volume_pan(_sample, milesVolume, milesBalance);
00201 }
00202 }
00203
00204
00205
00206
00207
00208
00209 void MilesAudioSample::
00210 set_balance(PN_stdfloat balance_right) {
00211 miles_audio_debug("set_balance(balance_right="<<balance_right<<")");
00212 _balance = balance_right;
00213
00214
00215 set_volume(_volume);
00216 }
00217
00218
00219
00220
00221
00222
00223 void MilesAudioSample::
00224 set_play_rate(PN_stdfloat play_rate) {
00225 miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")");
00226
00227
00228 _play_rate = play_rate;
00229
00230 if (_sample != 0) {
00231 play_rate *= _manager->get_play_rate();
00232
00233
00234 S32 speed = (S32)(play_rate * (PN_stdfloat)_original_playback_rate);
00235 AIL_set_sample_playback_rate(_sample, speed);
00236 audio_debug(" play_rate for this wav or mp3 is now " << speed);
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245 PN_stdfloat MilesAudioSample::
00246 length() const {
00247 return _sd->get_length();
00248 }
00249
00250
00251
00252
00253
00254
00255 AudioSound::SoundStatus MilesAudioSample::
00256 status() const {
00257 if (_sample == 0) {
00258 return AudioSound::READY;
00259 }
00260 switch (AIL_sample_status(_sample)) {
00261 case SMP_DONE:
00262 case SMP_STOPPED:
00263 case SMP_FREE:
00264 return AudioSound::READY;
00265
00266 case SMP_PLAYING:
00267 case SMP_PLAYINGBUTRELEASED:
00268 return AudioSound::PLAYING;
00269
00270 default:
00271 return AudioSound::BAD;
00272 }
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282 void MilesAudioSample::
00283 cleanup() {
00284 stop();
00285 set_active(false);
00286 nassertv(_sample == 0);
00287
00288 if (_manager != (MilesAudioManager *)NULL) {
00289 _manager->release_sound(this);
00290 _manager = NULL;
00291 }
00292 }
00293
00294
00295
00296
00297
00298
00299 void MilesAudioSample::
00300 output(ostream &out) const {
00301 out << get_type() << " " << get_name() << " " << status();
00302 if (!_sd.is_null()) {
00303 out << " " << (_sd->_raw_data.size() + 1023) / 1024 << "K";
00304 }
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314 void MilesAudioSample::set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
00315 audio_debug("MilesAudioSample::set_3d_attributes() Setting a sound's 3D Coordinates.");
00316
00317 if(_sample != 0) {
00318 AIL_set_sample_3D_position(_sample, px, pz, py);
00319 AIL_set_sample_3D_velocity_vector(_sample, vx, vz, vy);
00320 } else {
00321 audio_warning("_sample == 0 in MilesAudioSample::set_3d_attributes().");
00322 }
00323 }
00324
00325
00326
00327
00328
00329
00330 void MilesAudioSample::get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
00331 audio_debug("MilesAudioSample::get_3d_attributes().");
00332
00333 if(_sample != 0) {
00334 float lpx, lpy, lpz, lvx, lvy, lvz;
00335 AIL_sample_3D_position(_sample, &lpx, &lpz, &lpy);
00336 AIL_sample_3D_velocity(_sample, &lvx, &lvz, &lvy);
00337 *px = lpx;
00338 *py = lpy;
00339 *pz = lpz;
00340 *vx = lvx;
00341 *vy = lvy;
00342 *vz = lvz;
00343 } else {
00344 audio_warning("_sample == 0 in MilesAudioSample::get_3d_attributes().");
00345 }
00346 }
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 void MilesAudioSample::set_3d_min_distance(PN_stdfloat dist) {
00357 audio_debug("MilesAudioSample::set_3d_min_distance() Setting the sound's 3D min distance ( min= " << dist << " ) ");
00358
00359 if(_sample != 0) {
00360
00361
00362 float max_dist;
00363 int auto_3D_wet_atten;
00364 AIL_sample_3D_distances(_sample, &max_dist, NULL, &auto_3D_wet_atten);
00365
00366 AIL_set_sample_3D_distances(_sample, max_dist, dist, auto_3D_wet_atten);
00367 } else {
00368 audio_warning("_sample == 0 in MilesAudioSample::set_3d_min_distance().");
00369 }
00370 }
00371
00372
00373
00374
00375
00376
00377 PN_stdfloat MilesAudioSample::get_3d_min_distance() const {
00378 audio_debug("MilesAudioSample::get_3d_min_distance() ");
00379
00380 if(_sample != 0) {
00381 float min_dist;
00382 AIL_sample_3D_distances(_sample, NULL, &min_dist, NULL);
00383 return (PN_stdfloat)min_dist;
00384 } else {
00385 audio_warning("_sample == 0 in MilesAudioSample::get_3d_min_distance().");
00386 return -1.0;
00387 }
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398 void MilesAudioSample::set_3d_max_distance(PN_stdfloat dist) {
00399 audio_debug("MilesAudioSample::set_3d_max_distance() Setting the sound's 3D max distance ( max= " << dist << " ) ");
00400
00401 if(_sample != 0) {
00402
00403
00404 float min_dist;
00405 int auto_3D_wet_atten;
00406 AIL_sample_3D_distances(_sample, NULL, &min_dist, &auto_3D_wet_atten);
00407
00408 AIL_set_sample_3D_distances(_sample, dist, min_dist, auto_3D_wet_atten);
00409 } else {
00410 audio_warning("_sample == 0 in MilesAudioSample::set_3d_max_distance().");
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419
00420 PN_stdfloat MilesAudioSample::get_3d_max_distance() const {
00421 audio_debug("MilesAudioSample::get_3d_max_distance() ");
00422
00423 if(_sample != 0) {
00424 float max_dist;
00425 AIL_sample_3D_distances(_sample, &max_dist, NULL, NULL);
00426 return (PN_stdfloat)max_dist;
00427 } else {
00428 audio_warning("_sample == 0 in MilesAudioSample::get_3d_max_distance().");
00429 return -1.0;
00430 }
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 PN_stdfloat MilesAudioSample::
00470 get_speaker_level(int index) {
00471 audio_debug("MilesAudioSample::get_speaker_level(" << index << ")");
00472
00473 if(_sample != 0) {
00474 int numLevels;
00475 float *levels = AIL_sample_channel_levels(_sample, &numLevels);
00476
00477 if(index < numLevels) {
00478 return (PN_stdfloat)levels[index];
00479 } else {
00480 audio_error("index out of range in MilesAudioSample::get_speaker_level. numLevels: " << numLevels);
00481 return -1.0;
00482 }
00483 } else {
00484 audio_warning("Warning: MilesAudioSample::get_speaker_level only works for sounds that are currently playing");
00485 return -1.0;
00486 }
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528 void MilesAudioSample::
00529 set_speaker_levels(PN_stdfloat level1, PN_stdfloat level2, PN_stdfloat level3, PN_stdfloat level4, PN_stdfloat level5, PN_stdfloat level6, PN_stdfloat level7, PN_stdfloat level8, PN_stdfloat level9) {
00530 audio_debug("MilesAudioSample::set_speaker_levels()");
00531
00532 if(_sample != 0) {
00533 float levels[9] = {level1, level2, level3, level4, level5, level6, level7, level8, level9};
00534
00535 if((level1 < 0.0) || (level1 > 1.0)) {
00536 audio_error("No valid levels specified in MilesAudioSample::set_speaker_levels().");
00537 } else if((level2 < 0.0) || (level2 > 1.0)) {
00538 AIL_set_sample_channel_levels(_sample, levels, 1);
00539 } else if((level3 < 0.0) || (level3 > 1.0)) {
00540 AIL_set_sample_channel_levels(_sample, levels, 2);
00541 } else if((level4 < 0.0) || (level4 > 1.0)) {
00542 AIL_set_sample_channel_levels(_sample, levels, 3);
00543 } else if((level5 < 0.0) || (level5 > 1.0)) {
00544 AIL_set_sample_channel_levels(_sample, levels, 4);
00545 } else if((level6 < 0.0) || (level6 > 1.0)) {
00546 AIL_set_sample_channel_levels(_sample, levels, 5);
00547 } else if((level7 < 0.0) || (level7 > 1.0)) {
00548 AIL_set_sample_channel_levels(_sample, levels, 6);
00549 } else if((level8 < 0.0) || (level8 > 1.0)) {
00550 AIL_set_sample_channel_levels(_sample, levels, 7);
00551 } else if((level9 < 0.0) || (level9 > 1.0)) {
00552 AIL_set_sample_channel_levels(_sample, levels, 8);
00553 } else {
00554 AIL_set_sample_channel_levels(_sample, levels, 9);
00555 }
00556 } else {
00557 audio_warning("Warning: MilesAudioSample::set_speaker_levels only works for sounds that are currently playing");
00558 }
00559 }
00560
00561
00562
00563
00564
00565
00566
00567
00568 void MilesAudioSample::
00569 internal_stop() {
00570 _sample = 0;
00571 _sample_index = 0;
00572 }
00573
00574
00575
00576
00577
00578
00579
00580 void AILCALLBACK MilesAudioSample::
00581 finish_callback(HSAMPLE sample) {
00582 MilesAudioSample *self = (MilesAudioSample *)AIL_sample_user_data(sample, 0);
00583 if (milesAudio_cat.is_debug()) {
00584 milesAudio_cat.debug()
00585 << "finished " << *self << "\n";
00586 }
00587 if (self->_manager == (MilesAudioManager *)NULL) {
00588 return;
00589 }
00590 self->_manager->_sounds_finished = true;
00591 }
00592
00593
00594
00595
00596
00597
00598 void MilesAudioSample::
00599 do_set_time(PN_stdfloat time) {
00600 miles_audio_debug("do_set_time(time="<<time<<")");
00601 nassertv(_sample != 0);
00602
00603
00604 PN_stdfloat max_time = length();
00605 if (time > max_time) {
00606 milesAudio_cat.warning()
00607 << "set_time(" << time << ") requested for sound of length "
00608 << max_time << "\n";
00609 time = max_time;
00610 }
00611
00612 S32 time_ms = (S32)(1000.0f * time);
00613 AIL_set_sample_ms_position(_sample, time_ms);
00614 }
00615
00616 #endif //]