Panda3D

milesAudioSample.cxx

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 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, &current_ms);
00168   PN_stdfloat time = PN_stdfloat(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(PN_stdfloat 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(PN_stdfloat 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(PN_stdfloat 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 * (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 //     Function: MilesAudioSample::length
00242 //       Access: Public, Virtual
00243 //  Description: 
00244 ////////////////////////////////////////////////////////////////////
00245 PN_stdfloat 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(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 //     Function: MilesAudioSample::get_3d_attributes
00327 //       Access: public
00328 //  Description: Get position and velocity of this sound.
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 //     Function: MilesAudioSample::set_3d_min_distance
00350 //       Access: public
00351 //  Description: Set the distance that this sound begins to fall
00352 //               off.  With Miles's default falloff behavior, when
00353 //               the distance between the sound and the listener is
00354 //               doubled, the volume is halved, and vice versa.
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     // Implementation is awkward, since Miles gets and sets min and max distances
00361     // in a single operation.
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 //     Function: MilesAudioSample::get_3d_min_distance
00374 //       Access: public
00375 //  Description: Get the distance that this sound begins to fall off.
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 //     Function: MilesAudioSample::set_3d_max_distance
00392 //       Access: public
00393 //  Description: Set the distance at which this sound is clipped to
00394 //               silence.  Note that this value does not affect
00395 //               the rate at which the sound falls off, but only
00396 //               the distance at which it gets clipped.
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     // Implementation is awkward, since Miles gets and sets min and max distances
00403     // in a single operation.
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 //     Function: MilesAudioSample::get_3d_max_distance
00416 //       Access: public
00417 //  Description: Get the distance at which this sound is clipped to
00418 //               silence.
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 //     Function: MilesAudioSample::get_speaker_level
00435 //       Access: Published
00436 //  Description: Get the level of a particular logical channel (speaker).
00437 //               "index" specifies which speaker in an array of all the
00438 //               logical channels currently in use to retrieve the level
00439 //               of.
00440 //
00441 //               For instance, in a standard 4.0 channel setup, speakers
00442 //               are setup as [frontLeft, frontRight, backLeft, backRight].
00443 //               Thus, get_speaker_level(2) will retrieve the level of the
00444 //               backLeft speaker.
00445 //
00446 //               The order in which speakers appear in the array for
00447 //               standard speaker setups is defined to be:
00448 //
00449 //                  FRONT_LEFT 
00450 //                  FRONT_RIGHT 
00451 //                  FRONT_CENTER 
00452 //                  LOW_FREQUENCY (sub woofer)
00453 //                  BACK_LEFT 
00454 //                  BACK_RIGHT 
00455 //                  FRONT_LEFT_OF_CENTER 
00456 //                  FRONT_RIGHT_OF_CENTER 
00457 //                  BACK_CENTER 
00458 //                  SIDE_LEFT 
00459 //                  SIDE_RIGHT 
00460 //                  TOP_CENTER 
00461 //                  TOP_FRONT_LEFT 
00462 //                  TOP_FRONT_CENTER 
00463 //                  TOP_FRONT_RIGHT 
00464 //                  TOP_BACK_LEFT 
00465 //                  TOP_BACK_CENTER 
00466 //                  TOP_BACK_RIGHT 
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 //     Function: MilesAudioSample::set_speaker_levels
00491 //       Access: Published
00492 //  Description: Set the output levels on the logical channels (speakers)
00493 //               for this sound.  Values should be in the range 0.0 to 1.0.
00494 //               Levels for up to nine channels may be specified. As soon
00495 //               as a level is reached that falls outside the range 0.0 to
00496 //               1.0, the levels specified up to that point will be sent
00497 //               and all other levels will be ignored.
00498 //
00499 //               The user must know what the current speaker setup is in order
00500 //               to know which level corresponds to which speaker.
00501 //
00502 //               This method will have no effect if 3D attributes have been
00503 //               set for this sound.
00504 //
00505 //               The order in which speakers appear in the array for
00506 //               standard speaker setups is defined to be:
00507 //
00508 //                  FRONT_LEFT 
00509 //                  FRONT_RIGHT 
00510 //                  FRONT_CENTER 
00511 //                  LOW_FREQUENCY (sub woofer)
00512 //                  BACK_LEFT 
00513 //                  BACK_RIGHT 
00514 //                  FRONT_LEFT_OF_CENTER 
00515 //                  FRONT_RIGHT_OF_CENTER 
00516 //                  BACK_CENTER 
00517 //                  SIDE_LEFT 
00518 //                  SIDE_RIGHT 
00519 //                  TOP_CENTER 
00520 //                  TOP_FRONT_LEFT 
00521 //                  TOP_FRONT_CENTER 
00522 //                  TOP_FRONT_RIGHT 
00523 //                  TOP_BACK_LEFT 
00524 //                  TOP_BACK_CENTER 
00525 //                  TOP_BACK_RIGHT 
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 //     Function: MilesAudioSample::internal_stop
00563 //       Access: Private
00564 //  Description: Called by the GlobalMilesManager when it is detected
00565 //               that this particular sound has already stopped, and
00566 //               its sample handle will be recycled.
00567 ////////////////////////////////////////////////////////////////////
00568 void MilesAudioSample::
00569 internal_stop() {
00570   _sample = 0;
00571   _sample_index = 0;
00572 }
00573 
00574 ////////////////////////////////////////////////////////////////////
00575 //     Function: MilesAudioSample::finish_callback
00576 //       Access: Private, Static
00577 //  Description: This callback is made by Miles (possibly in a
00578 //               sub-thread) when the sample finishes.
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 //     Function: MilesAudioSample::do_set_time
00595 //       Access: Private
00596 //  Description: Sets the start time of an already allocated sample.
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   // Ensure we don't inadvertently run off the end of the sound.
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 //]
 All Classes Functions Variables Enumerations