15 #include "milesAudioSample.h" 17 #ifdef HAVE_RAD_MSS //[ 19 #include "milesAudioManager.h" 24 #undef miles_audio_debug 27 #define miles_audio_debug(x) \ 28 audio_debug("MilesAudioSample \""<<get_name()<<"\" "<< x ) 30 #define miles_audio_debug(x) ((void)0) 40 MilesAudioSample(MilesAudioManager *manager, MilesAudioManager::SoundData *sd,
41 const string &file_name) :
42 MilesAudioSound(manager, file_name),
46 audio_debug(
"MilesAudioSample(manager=0x"<<(
void*)&manager
47 <<
", sd=0x"<<(
void*)sd<<
", file_name="<<file_name<<
")");
51 _original_playback_rate = 1.0f;
61 miles_audio_debug(
"~MilesAudioSample()");
63 miles_audio_debug(
"~MilesAudioSample() done");
71 void MilesAudioSample::
73 miles_audio_debug(
"play()");
75 if (_sd->_raw_data.empty()) {
76 milesAudio_cat.warning()
77 <<
"Could not play " << _file_name <<
": no data\n";
80 _manager->starting_sound(
this);
82 nassertv(_sample == 0);
84 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
85 if (!mgr->get_sample(_sample, _sample_index,
this)){
86 milesAudio_cat.warning()
87 <<
"Could not play " << _file_name <<
": too many open samples\n";
90 AIL_set_named_sample_file(_sample, _sd->_basename.c_str(),
91 &_sd->_raw_data[0], _sd->_raw_data.size(),
93 _original_playback_rate = AIL_sample_playback_rate(_sample);
94 AIL_set_sample_user_data(_sample, 0, (SINTa)
this);
95 AIL_register_EOS_callback(_sample, finish_callback);
99 AIL_set_sample_loop_count(_sample, _loop_count);
101 if (_got_start_time) {
102 do_set_time(_start_time);
103 AIL_resume_sample(_sample);
105 AIL_start_sample(_sample);
109 _got_start_time =
false;
113 audio_debug(
" paused "<<_file_name );
123 void MilesAudioSample::
125 if (_manager == (MilesAudioManager *)NULL) {
129 miles_audio_debug(
"stop()");
130 _manager->stopping_sound(
this);
142 AIL_end_sample(_sample);
144 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
145 mgr->release_sample(_sample_index,
this);
157 PN_stdfloat MilesAudioSample::
160 if (_got_start_time) {
167 AIL_sample_ms_position(_sample, NULL, ¤t_ms);
168 PN_stdfloat time = PN_stdfloat(current_ms * 0.001f);
178 void MilesAudioSample::
179 set_volume(PN_stdfloat volume) {
180 miles_audio_debug(
"set_volume(volume="<<volume<<
")");
190 volume *= _manager->get_volume();
193 F32 milesVolume = volume;
194 milesVolume = min(milesVolume, 1.0f);
195 milesVolume = max(milesVolume, 0.0f);
198 F32 milesBalance = (F32)((_balance + 1.0f) * 0.5f);
200 AIL_set_sample_volume_pan(_sample, milesVolume, milesBalance);
209 void MilesAudioSample::
210 set_balance(PN_stdfloat balance_right) {
211 miles_audio_debug(
"set_balance(balance_right="<<balance_right<<
")");
212 _balance = balance_right;
223 void MilesAudioSample::
224 set_play_rate(PN_stdfloat play_rate) {
225 miles_audio_debug(
"set_play_rate(play_rate="<<play_rate<<
")");
228 _play_rate = play_rate;
231 play_rate *= _manager->get_play_rate();
234 S32 speed = (S32)(play_rate * (PN_stdfloat)_original_playback_rate);
235 AIL_set_sample_playback_rate(_sample, speed);
236 audio_debug(
" play_rate for this wav or mp3 is now " << speed);
245 PN_stdfloat MilesAudioSample::
247 return _sd->get_length();
255 AudioSound::SoundStatus MilesAudioSample::
258 return AudioSound::READY;
260 switch (AIL_sample_status(_sample)) {
264 return AudioSound::READY;
267 case SMP_PLAYINGBUTRELEASED:
268 return AudioSound::PLAYING;
271 return AudioSound::BAD;
282 void MilesAudioSample::
286 nassertv(_sample == 0);
288 if (_manager != (MilesAudioManager *)NULL) {
289 _manager->release_sound(
this);
299 void MilesAudioSample::
300 output(ostream &out)
const {
302 if (!_sd.is_null()) {
303 out <<
" " << (_sd->_raw_data.size() + 1023) / 1024 <<
"K";
314 void MilesAudioSample::set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
315 audio_debug(
"MilesAudioSample::set_3d_attributes() Setting a sound's 3D Coordinates.");
318 AIL_set_sample_3D_position(_sample, px, pz, py);
319 AIL_set_sample_3D_velocity_vector(_sample, vx, vz, vy);
321 audio_warning(
"_sample == 0 in MilesAudioSample::set_3d_attributes().");
330 void MilesAudioSample::get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
331 audio_debug(
"MilesAudioSample::get_3d_attributes().");
334 float lpx, lpy, lpz, lvx, lvy, lvz;
335 AIL_sample_3D_position(_sample, &lpx, &lpz, &lpy);
336 AIL_sample_3D_velocity(_sample, &lvx, &lvz, &lvy);
344 audio_warning(
"_sample == 0 in MilesAudioSample::get_3d_attributes().");
356 void MilesAudioSample::set_3d_min_distance(PN_stdfloat dist) {
357 audio_debug(
"MilesAudioSample::set_3d_min_distance() Setting the sound's 3D min distance ( min= " << dist <<
" ) ");
363 int auto_3D_wet_atten;
364 AIL_sample_3D_distances(_sample, &max_dist, NULL, &auto_3D_wet_atten);
366 AIL_set_sample_3D_distances(_sample, max_dist, dist, auto_3D_wet_atten);
368 audio_warning(
"_sample == 0 in MilesAudioSample::set_3d_min_distance().");
377 PN_stdfloat MilesAudioSample::get_3d_min_distance()
const {
378 audio_debug(
"MilesAudioSample::get_3d_min_distance() ");
382 AIL_sample_3D_distances(_sample, NULL, &min_dist, NULL);
383 return (PN_stdfloat)min_dist;
385 audio_warning(
"_sample == 0 in MilesAudioSample::get_3d_min_distance().");
398 void MilesAudioSample::set_3d_max_distance(PN_stdfloat dist) {
399 audio_debug(
"MilesAudioSample::set_3d_max_distance() Setting the sound's 3D max distance ( max= " << dist <<
" ) ");
405 int auto_3D_wet_atten;
406 AIL_sample_3D_distances(_sample, NULL, &min_dist, &auto_3D_wet_atten);
408 AIL_set_sample_3D_distances(_sample, dist, min_dist, auto_3D_wet_atten);
410 audio_warning(
"_sample == 0 in MilesAudioSample::set_3d_max_distance().");
420 PN_stdfloat MilesAudioSample::get_3d_max_distance()
const {
421 audio_debug(
"MilesAudioSample::get_3d_max_distance() ");
425 AIL_sample_3D_distances(_sample, &max_dist, NULL, NULL);
426 return (PN_stdfloat)max_dist;
428 audio_warning(
"_sample == 0 in MilesAudioSample::get_3d_max_distance().");
469 PN_stdfloat MilesAudioSample::
470 get_speaker_level(
int index) {
471 audio_debug(
"MilesAudioSample::get_speaker_level(" << index <<
")");
475 float *levels = AIL_sample_channel_levels(_sample, &numLevels);
477 if(index < numLevels) {
478 return (PN_stdfloat)levels[index];
480 audio_error(
"index out of range in MilesAudioSample::get_speaker_level. numLevels: " << numLevels);
484 audio_warning(
"Warning: MilesAudioSample::get_speaker_level only works for sounds that are currently playing");
528 void MilesAudioSample::
529 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) {
530 audio_debug(
"MilesAudioSample::set_speaker_levels()");
533 float levels[9] = {level1, level2, level3, level4, level5, level6, level7, level8, level9};
535 if((level1 < 0.0) || (level1 > 1.0)) {
536 audio_error(
"No valid levels specified in MilesAudioSample::set_speaker_levels().");
537 }
else if((level2 < 0.0) || (level2 > 1.0)) {
538 AIL_set_sample_channel_levels(_sample, levels, 1);
539 }
else if((level3 < 0.0) || (level3 > 1.0)) {
540 AIL_set_sample_channel_levels(_sample, levels, 2);
541 }
else if((level4 < 0.0) || (level4 > 1.0)) {
542 AIL_set_sample_channel_levels(_sample, levels, 3);
543 }
else if((level5 < 0.0) || (level5 > 1.0)) {
544 AIL_set_sample_channel_levels(_sample, levels, 4);
545 }
else if((level6 < 0.0) || (level6 > 1.0)) {
546 AIL_set_sample_channel_levels(_sample, levels, 5);
547 }
else if((level7 < 0.0) || (level7 > 1.0)) {
548 AIL_set_sample_channel_levels(_sample, levels, 6);
549 }
else if((level8 < 0.0) || (level8 > 1.0)) {
550 AIL_set_sample_channel_levels(_sample, levels, 7);
551 }
else if((level9 < 0.0) || (level9 > 1.0)) {
552 AIL_set_sample_channel_levels(_sample, levels, 8);
554 AIL_set_sample_channel_levels(_sample, levels, 9);
557 audio_warning(
"Warning: MilesAudioSample::set_speaker_levels only works for sounds that are currently playing");
568 void MilesAudioSample::
580 void AILCALLBACK MilesAudioSample::
581 finish_callback(HSAMPLE sample) {
582 MilesAudioSample *
self = (MilesAudioSample *)AIL_sample_user_data(sample, 0);
583 if (milesAudio_cat.is_debug()) {
584 milesAudio_cat.debug()
585 <<
"finished " << *
self <<
"\n";
587 if (self->_manager == (MilesAudioManager *)NULL) {
590 self->_manager->_sounds_finished =
true;
598 void MilesAudioSample::
599 do_set_time(PN_stdfloat time) {
600 miles_audio_debug(
"do_set_time(time="<<time<<
")");
601 nassertv(_sample != 0);
604 PN_stdfloat max_time =
length();
605 if (time > max_time) {
606 milesAudio_cat.warning()
607 <<
"set_time(" << time <<
") requested for sound of length " 612 S32 time_ms = (S32)(1000.0f * time);
613 AIL_set_sample_ms_position(_sample, time_ms);
AudioSound::SoundStatus status() const
Get status of the sound.
void set_volume(PN_stdfloat volume=1.0)
0.0 to 1.0 scale of volume converted to Fmod's internal 0.0 to 255.0 scale.
PN_stdfloat length() const
Get length FMOD returns the time in MS so we have to convert to seconds.
const string & get_name() const
Get name of sound file.
void set_play_rate(PN_stdfloat play_rate=1.0f)
Sets the speed at which a sound plays back.
void set_active(bool active=true)
Sets whether the sound is marked "active".
TypeHandle is the identifier used to differentiate C++ class types.