Panda3D
|
00001 // Filename: milesAudioSample.cxx 00002 // Created by: skyler (June 6, 2001) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 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 // Function: MilesAudioSample::Constructor 00035 // Access: Private 00036 // Description: This constructor is called only by the 00037 // MilesAudioManager. 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 // Function: MilesAudioSample::Destructor 00056 // Access: Public, Virtual 00057 // Description: 00058 //////////////////////////////////////////////////////////////////// 00059 MilesAudioSample:: 00060 ~MilesAudioSample() { 00061 miles_audio_debug("~MilesAudioSample()"); 00062 cleanup(); 00063 miles_audio_debug("~MilesAudioSample() done"); 00064 } 00065 00066 //////////////////////////////////////////////////////////////////// 00067 // Function: MilesAudioSample::play 00068 // Access: Public, Virtual 00069 // Description: 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 // In case _loop_count gets set to forever (zero): 00113 audio_debug(" paused "<<_file_name ); 00114 _paused = true; 00115 } 00116 } 00117 00118 //////////////////////////////////////////////////////////////////// 00119 // Function: MilesAudioSample::stop 00120 // Access: Public, Virtual 00121 // Description: 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 // The _paused flag should not be cleared here. _paused is not like 00132 // the Pause button on a cd/dvd player. It is used as a flag to say 00133 // that it was looping when it was set inactive. There is no need to 00134 // make this symmetrical with play(). set_active() is the 'owner' of 00135 // _paused. play() accesses _paused to help in the situation where 00136 // someone calls play on an inactive sound(). 00137 00138 // it fixes audio bug, I don't understand the reasoning of the above comment 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 // Function: MilesAudioSample::get_time 00154 // Access: Public, Virtual 00155 // Description: 00156 //////////////////////////////////////////////////////////////////// 00157 float 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 float time = float(current_ms * 0.001f); 00169 00170 return time; 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: MilesAudioSample::set_volume 00175 // Access: Public, Virtual 00176 // Description: 00177 //////////////////////////////////////////////////////////////////// 00178 void MilesAudioSample:: 00179 set_volume(float volume) { 00180 miles_audio_debug("set_volume(volume="<<volume<<")"); 00181 00182 // Set the volume even if our volume is not changing, because the 00183 // MilesAudioManager will call set_volume() when *its* volume 00184 // changes. 00185 00186 // Set the volume: 00187 _volume = volume; 00188 00189 if (_sample != 0) { 00190 volume *= _manager->get_volume(); 00191 00192 // Change to Miles volume, range 0 to 1.0: 00193 F32 milesVolume = volume; 00194 milesVolume = min(milesVolume, 1.0f); 00195 milesVolume = max(milesVolume, 0.0f); 00196 00197 // Convert balance of -1.0..1.0 to 0-1.0: 00198 F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f); 00199 00200 AIL_set_sample_volume_pan(_sample, milesVolume, milesBalance); 00201 } 00202 } 00203 00204 //////////////////////////////////////////////////////////////////// 00205 // Function: MilesAudioSample::set_balance 00206 // Access: Public, Virtual 00207 // Description: 00208 //////////////////////////////////////////////////////////////////// 00209 void MilesAudioSample:: 00210 set_balance(float balance_right) { 00211 miles_audio_debug("set_balance(balance_right="<<balance_right<<")"); 00212 _balance = balance_right; 00213 00214 // Call set_volume to effect the change: 00215 set_volume(_volume); 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: MilesAudioSample::set_play_rate 00220 // Access: Public, Virtual 00221 // Description: 00222 //////////////////////////////////////////////////////////////////// 00223 void MilesAudioSample:: 00224 set_play_rate(float play_rate) { 00225 miles_audio_debug("set_play_rate(play_rate="<<play_rate<<")"); 00226 00227 // Set the play_rate: 00228 _play_rate = play_rate; 00229 00230 if (_sample != 0) { 00231 play_rate *= _manager->get_play_rate(); 00232 00233 // wave and mp3 use sample rate (e.g. 44100) 00234 S32 speed = (S32)(play_rate * (float)_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 // Function: MilesAudioSample::length 00242 // Access: Public, Virtual 00243 // Description: 00244 //////////////////////////////////////////////////////////////////// 00245 float MilesAudioSample:: 00246 length() const { 00247 return _sd->get_length(); 00248 } 00249 00250 //////////////////////////////////////////////////////////////////// 00251 // Function: MilesAudioSample::status 00252 // Access: Public, Virtual 00253 // Description: 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 // Function: MilesAudioSample::cleanup 00277 // Access: Public, Virtual 00278 // Description: Stops the sound from playing and releases any 00279 // associated resources, in preparation for releasing 00280 // the sound or shutting down the sound system. 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 // Function: MilesAudioSample::output 00296 // Access: Published, Virtual 00297 // Description: 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 // Function: MilesAudioSample::set_3d_attributes 00309 // Access: public 00310 // Description: Set position and velocity of this sound. Note that 00311 // Y and Z are switched to translate from Miles's 00312 // coordinate system. 00313 //////////////////////////////////////////////////////////////////// 00314 void MilesAudioSample::set_3d_attributes(float px, float py, float pz, float vx, float vy, float 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 // Function: MilesAudioSample::get_3d_attributes 00327 // Access: public 00328 // Description: Get position and velocity of this sound. 00329 //////////////////////////////////////////////////////////////////// 00330 void MilesAudioSample::get_3d_attributes(float *px, float *py, float *pz, float *vx, float *vy, float *vz) { 00331 audio_debug("MilesAudioSample::get_3d_attributes()."); 00332 00333 if(_sample != 0) { 00334 AIL_sample_3D_position(_sample, px, pz, py); 00335 AIL_sample_3D_velocity(_sample, vx, vz, vy); 00336 } else { 00337 audio_warning("_sample == 0 in MilesAudioSample::get_3d_attributes()."); 00338 } 00339 } 00340 00341 //////////////////////////////////////////////////////////////////// 00342 // Function: MilesAudioSample::set_3d_min_distance 00343 // Access: public 00344 // Description: Set the distance that this sound begins to fall 00345 // off. With Miles's default falloff behavior, when 00346 // the distance between the sound and the listener is 00347 // doubled, the volume is halved, and vice versa. 00348 //////////////////////////////////////////////////////////////////// 00349 void MilesAudioSample::set_3d_min_distance(float dist) { 00350 audio_debug("MilesAudioSample::set_3d_min_distance() Setting the sound's 3D min distance ( min= " << dist << " ) "); 00351 00352 if(_sample != 0) { 00353 // Implementation is awkward, since Miles gets and sets min and max distances 00354 // in a single operation. 00355 float max_dist; 00356 int auto_3D_wet_atten; 00357 AIL_sample_3D_distances(_sample, &max_dist, NULL, &auto_3D_wet_atten); 00358 00359 AIL_set_sample_3D_distances(_sample, max_dist, dist, auto_3D_wet_atten); 00360 } else { 00361 audio_warning("_sample == 0 in MilesAudioSample::set_3d_min_distance()."); 00362 } 00363 } 00364 00365 //////////////////////////////////////////////////////////////////// 00366 // Function: MilesAudioSample::get_3d_min_distance 00367 // Access: public 00368 // Description: Get the distance that this sound begins to fall off. 00369 //////////////////////////////////////////////////////////////////// 00370 float MilesAudioSample::get_3d_min_distance() const { 00371 audio_debug("MilesAudioSample::get_3d_min_distance() "); 00372 00373 if(_sample != 0) { 00374 float min_dist; 00375 AIL_sample_3D_distances(_sample, NULL, &min_dist, NULL); 00376 return min_dist; 00377 } else { 00378 audio_warning("_sample == 0 in MilesAudioSample::get_3d_min_distance()."); 00379 return -1.0; 00380 } 00381 } 00382 00383 //////////////////////////////////////////////////////////////////// 00384 // Function: MilesAudioSample::set_3d_max_distance 00385 // Access: public 00386 // Description: Set the distance at which this sound is clipped to 00387 // silence. Note that this value does not affect 00388 // the rate at which the sound falls off, but only 00389 // the distance at which it gets clipped. 00390 //////////////////////////////////////////////////////////////////// 00391 void MilesAudioSample::set_3d_max_distance(float dist) { 00392 audio_debug("MilesAudioSample::set_3d_max_distance() Setting the sound's 3D max distance ( max= " << dist << " ) "); 00393 00394 if(_sample != 0) { 00395 // Implementation is awkward, since Miles gets and sets min and max distances 00396 // in a single operation. 00397 float min_dist; 00398 int auto_3D_wet_atten; 00399 AIL_sample_3D_distances(_sample, NULL, &min_dist, &auto_3D_wet_atten); 00400 00401 AIL_set_sample_3D_distances(_sample, dist, min_dist, auto_3D_wet_atten); 00402 } else { 00403 audio_warning("_sample == 0 in MilesAudioSample::set_3d_max_distance()."); 00404 } 00405 } 00406 00407 //////////////////////////////////////////////////////////////////// 00408 // Function: MilesAudioSample::get_3d_max_distance 00409 // Access: public 00410 // Description: Get the distance at which this sound is clipped to 00411 // silence. 00412 //////////////////////////////////////////////////////////////////// 00413 float MilesAudioSample::get_3d_max_distance() const { 00414 audio_debug("MilesAudioSample::get_3d_max_distance() "); 00415 00416 if(_sample != 0) { 00417 float max_dist; 00418 AIL_sample_3D_distances(_sample, &max_dist, NULL, NULL); 00419 return max_dist; 00420 } else { 00421 audio_warning("_sample == 0 in MilesAudioSample::get_3d_max_distance()."); 00422 return -1.0; 00423 } 00424 } 00425 00426 //////////////////////////////////////////////////////////////////// 00427 // Function: MilesAudioSample::get_speaker_level 00428 // Access: Published 00429 // Description: Get the level of a particular logical channel (speaker). 00430 // "index" specifies which speaker in an array of all the 00431 // logical channels currently in use to retrieve the level 00432 // of. 00433 // 00434 // For instance, in a standard 4.0 channel setup, speakers 00435 // are setup as [frontLeft, frontRight, backLeft, backRight]. 00436 // Thus, get_speaker_level(2) will retrieve the level of the 00437 // backLeft speaker. 00438 // 00439 // The order in which speakers appear in the array for 00440 // standard speaker setups is defined to be: 00441 // 00442 // FRONT_LEFT 00443 // FRONT_RIGHT 00444 // FRONT_CENTER 00445 // LOW_FREQUENCY (sub woofer) 00446 // BACK_LEFT 00447 // BACK_RIGHT 00448 // FRONT_LEFT_OF_CENTER 00449 // FRONT_RIGHT_OF_CENTER 00450 // BACK_CENTER 00451 // SIDE_LEFT 00452 // SIDE_RIGHT 00453 // TOP_CENTER 00454 // TOP_FRONT_LEFT 00455 // TOP_FRONT_CENTER 00456 // TOP_FRONT_RIGHT 00457 // TOP_BACK_LEFT 00458 // TOP_BACK_CENTER 00459 // TOP_BACK_RIGHT 00460 // 00461 //////////////////////////////////////////////////////////////////// 00462 float MilesAudioSample:: 00463 get_speaker_level(int index) { 00464 audio_debug("MilesAudioSample::get_speaker_level(" << index << ")"); 00465 00466 if(_sample != 0) { 00467 int numLevels; 00468 float *levels = AIL_sample_channel_levels(_sample, &numLevels); 00469 00470 if(index < numLevels) { 00471 return levels[index]; 00472 } else { 00473 audio_error("index out of range in MilesAudioSample::get_speaker_level. numLevels: " << numLevels); 00474 return -1.0; 00475 } 00476 } else { 00477 audio_warning("Warning: MilesAudioSample::get_speaker_level only works for sounds that are currently playing"); 00478 return -1.0; 00479 } 00480 } 00481 00482 //////////////////////////////////////////////////////////////////// 00483 // Function: MilesAudioSample::set_speaker_levels 00484 // Access: Published 00485 // Description: Set the output levels on the logical channels (speakers) 00486 // for this sound. Values should be in the range 0.0 to 1.0. 00487 // Levels for up to nine channels may be specified. As soon 00488 // as a level is reached that falls outside the range 0.0 to 00489 // 1.0, the levels specified up to that point will be sent 00490 // and all other levels will be ignored. 00491 // 00492 // The user must know what the current speaker setup is in order 00493 // to know which level corresponds to which speaker. 00494 // 00495 // This method will have no effect if 3D attributes have been 00496 // set for this sound. 00497 // 00498 // The order in which speakers appear in the array for 00499 // standard speaker setups is defined to be: 00500 // 00501 // FRONT_LEFT 00502 // FRONT_RIGHT 00503 // FRONT_CENTER 00504 // LOW_FREQUENCY (sub woofer) 00505 // BACK_LEFT 00506 // BACK_RIGHT 00507 // FRONT_LEFT_OF_CENTER 00508 // FRONT_RIGHT_OF_CENTER 00509 // BACK_CENTER 00510 // SIDE_LEFT 00511 // SIDE_RIGHT 00512 // TOP_CENTER 00513 // TOP_FRONT_LEFT 00514 // TOP_FRONT_CENTER 00515 // TOP_FRONT_RIGHT 00516 // TOP_BACK_LEFT 00517 // TOP_BACK_CENTER 00518 // TOP_BACK_RIGHT 00519 // 00520 //////////////////////////////////////////////////////////////////// 00521 void MilesAudioSample:: 00522 set_speaker_levels(float level1, float level2, float level3, float level4, float level5, float level6, float level7, float level8, float level9) { 00523 audio_debug("MilesAudioSample::set_speaker_levels()"); 00524 00525 if(_sample != 0) { 00526 float levels[9] = {level1, level2, level3, level4, level5, level6, level7, level8, level9}; 00527 00528 if((level1 < 0.0) || (level1 > 1.0)) { 00529 audio_error("No valid levels specified in MilesAudioSample::set_speaker_levels()."); 00530 } else if((level2 < 0.0) || (level2 > 1.0)) { 00531 AIL_set_sample_channel_levels(_sample, levels, 1); 00532 } else if((level3 < 0.0) || (level3 > 1.0)) { 00533 AIL_set_sample_channel_levels(_sample, levels, 2); 00534 } else if((level4 < 0.0) || (level4 > 1.0)) { 00535 AIL_set_sample_channel_levels(_sample, levels, 3); 00536 } else if((level5 < 0.0) || (level5 > 1.0)) { 00537 AIL_set_sample_channel_levels(_sample, levels, 4); 00538 } else if((level6 < 0.0) || (level6 > 1.0)) { 00539 AIL_set_sample_channel_levels(_sample, levels, 5); 00540 } else if((level7 < 0.0) || (level7 > 1.0)) { 00541 AIL_set_sample_channel_levels(_sample, levels, 6); 00542 } else if((level8 < 0.0) || (level8 > 1.0)) { 00543 AIL_set_sample_channel_levels(_sample, levels, 7); 00544 } else if((level9 < 0.0) || (level9 > 1.0)) { 00545 AIL_set_sample_channel_levels(_sample, levels, 8); 00546 } else { 00547 AIL_set_sample_channel_levels(_sample, levels, 9); 00548 } 00549 } else { 00550 audio_warning("Warning: MilesAudioSample::set_speaker_levels only works for sounds that are currently playing"); 00551 } 00552 } 00553 00554 //////////////////////////////////////////////////////////////////// 00555 // Function: MilesAudioSample::internal_stop 00556 // Access: Private 00557 // Description: Called by the GlobalMilesManager when it is detected 00558 // that this particular sound has already stopped, and 00559 // its sample handle will be recycled. 00560 //////////////////////////////////////////////////////////////////// 00561 void MilesAudioSample:: 00562 internal_stop() { 00563 _sample = 0; 00564 _sample_index = 0; 00565 } 00566 00567 //////////////////////////////////////////////////////////////////// 00568 // Function: MilesAudioSample::finish_callback 00569 // Access: Private, Static 00570 // Description: This callback is made by Miles (possibly in a 00571 // sub-thread) when the sample finishes. 00572 //////////////////////////////////////////////////////////////////// 00573 void AILCALLBACK MilesAudioSample:: 00574 finish_callback(HSAMPLE sample) { 00575 MilesAudioSample *self = (MilesAudioSample *)AIL_sample_user_data(sample, 0); 00576 if (milesAudio_cat.is_debug()) { 00577 milesAudio_cat.debug() 00578 << "finished " << *self << "\n"; 00579 } 00580 if (self->_manager == (MilesAudioManager *)NULL) { 00581 return; 00582 } 00583 self->_manager->_sounds_finished = true; 00584 } 00585 00586 //////////////////////////////////////////////////////////////////// 00587 // Function: MilesAudioSample::do_set_time 00588 // Access: Private 00589 // Description: Sets the start time of an already allocated sample. 00590 //////////////////////////////////////////////////////////////////// 00591 void MilesAudioSample:: 00592 do_set_time(float time) { 00593 miles_audio_debug("do_set_time(time="<<time<<")"); 00594 nassertv(_sample != 0); 00595 00596 // Ensure we don't inadvertently run off the end of the sound. 00597 float max_time = length(); 00598 if (time > max_time) { 00599 milesAudio_cat.warning() 00600 << "set_time(" << time << ") requested for sound of length " 00601 << max_time << "\n"; 00602 time = max_time; 00603 } 00604 00605 S32 time_ms = (S32)(1000.0f * time); 00606 AIL_set_sample_ms_position(_sample, time_ms); 00607 } 00608 00609 #endif //]