16 #include "milesAudioManager.h" 18 #ifdef HAVE_RAD_MSS //[ 20 #include "milesAudioSound.h" 21 #include "milesAudioSample.h" 22 #include "milesAudioStream.h" 23 #include "globalMilesManager.h" 24 #include "config_audio.h" 25 #include "config_util.h" 26 #include "config_express.h" 27 #include "virtualFileSystem.h" 28 #include "nullAudioSound.h" 29 #include "string_utils.h" 30 #include "mutexHolder.h" 31 #include "lightReMutexHolder.h" 39 audio_debug(
"Create_MilesAudioManager()");
40 return new MilesAudioManager();
53 _lock(
"MilesAudioManager::_lock"),
54 _streams_lock(
"MilesAudioManager::_streams_lock"),
55 _streams_cvar(_streams_lock)
57 audio_debug(
"MilesAudioManager::MilesAudioManager(), this = " 59 GlobalMilesManager::get_global_ptr()->add_manager(
this);
60 audio_debug(
" audio_active="<<audio_active);
61 audio_debug(
" audio_volume="<<audio_volume);
62 _cleanup_required =
true;
63 _active = audio_active;
64 _volume = audio_volume;
66 _cache_limit = audio_cache_limit;
67 _concurrent_sound_limit = 0;
69 _hasMidiSounds =
false;
70 _sounds_finished =
false;
94 ~MilesAudioManager() {
95 audio_debug(
"MilesAudioManager::~MilesAudioManager(), this = " 98 GlobalMilesManager::get_global_ptr()->remove_manager(
this);
100 audio_debug(
"MilesAudioManager::~MilesAudioManager() finished");
112 void MilesAudioManager::
114 audio_debug(
"shutdown() started");
115 GlobalMilesManager::get_global_ptr()->cleanup();
116 audio_debug(
"shutdown() finished");
126 bool MilesAudioManager::
129 return do_is_valid();
138 get_sound(
const string &file_name,
bool,
int) {
140 audio_debug(
"MilesAudioManager::get_sound(file_name=\""<<file_name<<
"\")");
142 if (!do_is_valid()) {
143 audio_debug(
"invalid MilesAudioManager returning NullSound");
144 return get_null_sound();
151 audio_debug(
"Reading "<<path);
152 audio_debug(
" resolved file_name is '"<<path<<
"'");
156 SoundMap::const_iterator si=_sounds.find(path);
157 if (si != _sounds.end()) {
160 audio_debug(
" sound found in pool 0x" << (
void*)sd);
165 if (sd != (SoundData *)NULL) {
166 while (_sounds.size() >= (
unsigned int)_cache_limit) {
172 pair<SoundMap::const_iterator, bool> ib
173 = _sounds.insert(SoundMap::value_type(path, sd));
176 audio_debug(
" failed map insert of "<<path);
177 nassertr(do_is_valid(), NULL);
178 return get_null_sound();
188 if (sd != (SoundData *)NULL) {
189 most_recently_used((*si).first);
190 if (sd->_file_type == AILFILETYPE_MIDI ||
191 sd->_file_type == AILFILETYPE_XMIDI ||
192 sd->_file_type == AILFILETYPE_XMIDI_DLS ||
193 sd->_file_type == AILFILETYPE_XMIDI_MLS) {
195 audioSound =
new MilesAudioSequence(
this, sd, file_name);
197 }
else if (!sd->_raw_data.empty()) {
199 audioSound =
new MilesAudioSample(
this, sd, file_name);
203 audioSound =
new MilesAudioStream(
this, file_name, path);
206 audioSound->set_active(_active);
208 bool inserted = _sounds_on_loan.insert((MilesAudioSound *)audioSound.p()).second;
209 nassertr(inserted, audioSound);
211 _hasMidiSounds |= (file_name.find(
".mid")!=string::npos);
217 audio_debug(
" returning 0x" << (
void*)audioSound);
218 nassertr(do_is_valid(), NULL);
229 nassert_raise(
"Miles audio manager does not support MovieAudio sources.");
238 void MilesAudioManager::
239 uncache_sound(
const string &file_name) {
240 audio_debug(
"MilesAudioManager::uncache_sound(file_name=\"" 243 nassertv(do_is_valid());
249 audio_debug(
" path=\""<<path<<
"\"");
250 SoundMap::iterator i = _sounds.find(path);
251 if (i != _sounds.end()) {
252 nassertv(_lru.size() > 0);
253 LRU::iterator lru_i = find(_lru.begin(), _lru.end(), &(i->first));
254 nassertv(lru_i != _lru.end());
258 nassertv(do_is_valid());
266 void MilesAudioManager::
268 audio_debug(
"MilesAudioManager::clear_cache()");
278 void MilesAudioManager::
279 set_cache_limit(
unsigned int count) {
282 audio_debug(
"MilesAudioManager::set_cache_limit(count="<<count<<
")");
283 nassertv(do_is_valid());
284 while (_lru.size() > count) {
288 nassertv(do_is_valid());
296 unsigned int MilesAudioManager::
297 get_cache_limit()
const {
306 void MilesAudioManager::
307 set_volume(PN_stdfloat volume) {
308 audio_debug(
"MilesAudioManager::set_volume(volume="<<volume<<
")");
310 if (_volume != volume) {
313 AudioSet::iterator i = _sounds_on_loan.begin();
314 for (; i!=_sounds_on_loan.end(); ++i) {
315 (*i)->set_volume((*i)->get_volume());
325 PN_stdfloat MilesAudioManager::
335 void MilesAudioManager::
336 set_play_rate(PN_stdfloat play_rate) {
337 audio_debug(
"MilesAudioManager::set_play_rate(play_rate="<<play_rate<<
")");
339 if (_play_rate != play_rate) {
340 _play_rate = play_rate;
342 AudioSet::iterator i = _sounds_on_loan.begin();
343 for (; i != _sounds_on_loan.end(); ++i) {
344 (*i)->set_play_rate((*i)->get_play_rate());
354 PN_stdfloat MilesAudioManager::
355 get_play_rate()
const {
364 void MilesAudioManager::
365 set_active(
bool active) {
366 audio_debug(
"MilesAudioManager::set_active(flag="<<active<<
")");
368 if (_active != active) {
371 AudioSet::iterator i = _sounds_on_loan.begin();
372 for (; i != _sounds_on_loan.end(); ++i) {
373 (*i)->set_active(_active);
376 if ((!_active) && _hasMidiSounds) {
377 GlobalMilesManager::get_global_ptr()->force_midi_reset();
387 bool MilesAudioManager::
397 void MilesAudioManager::
398 set_concurrent_sound_limit(
unsigned int limit) {
400 _concurrent_sound_limit = limit;
401 do_reduce_sounds_playing_to(_concurrent_sound_limit);
409 unsigned int MilesAudioManager::
410 get_concurrent_sound_limit()
const {
411 return _concurrent_sound_limit;
419 void MilesAudioManager::
420 reduce_sounds_playing_to(
unsigned int count) {
422 do_reduce_sounds_playing_to(count);
430 void MilesAudioManager::
432 audio_debug(
"MilesAudioManager::stop_all_sounds()");
433 reduce_sounds_playing_to(0);
443 void MilesAudioManager::audio_3d_set_listener_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz, PN_stdfloat fx, PN_stdfloat fy, PN_stdfloat fz, PN_stdfloat ux, PN_stdfloat uy, PN_stdfloat uz) {
444 audio_debug(
"MilesAudioManager::audio_3d_set_listener_attributes()");
446 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
447 AIL_set_listener_3D_position(mgr->_digital_driver, px, pz, py);
448 AIL_set_listener_3D_velocity_vector(mgr->_digital_driver, vx, vz, vy);
449 AIL_set_listener_3D_orientation(mgr->_digital_driver, fx, fz, fy, ux, uz, uy);
459 void MilesAudioManager::audio_3d_get_listener_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz, PN_stdfloat *fx, PN_stdfloat *fy, PN_stdfloat *fz, PN_stdfloat *ux, PN_stdfloat *uy, PN_stdfloat *uz) {
460 audio_debug(
"MilesAudioManager::audio_3d_get_listener_attributes()");
462 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
463 float lpx, lpy, lpz, lvx, lvy, lvz, lfx, lfy, lfz, lux, luy, luz;
464 AIL_listener_3D_position(mgr->_digital_driver, &lpx, &lpz, &lpy);
465 AIL_listener_3D_velocity(mgr->_digital_driver, &lvx, &lvz, &lvy);
466 AIL_listener_3D_orientation(mgr->_digital_driver, &lfx, &lfz, &lfy, &lux, &luz, &luy);
488 void MilesAudioManager::audio_3d_set_distance_factor(PN_stdfloat factor) {
489 audio_debug(
"MilesAudioManager::audio_3d_set_distance_factor( factor= " << factor <<
")");
491 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
492 AIL_set_3D_distance_factor(mgr->_digital_driver, factor);
500 PN_stdfloat MilesAudioManager::audio_3d_get_distance_factor()
const {
501 audio_debug(
"MilesAudioManager::audio_3d_get_distance_factor()");
503 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
504 return AIL_3D_distance_factor(mgr->_digital_driver);
513 void MilesAudioManager::audio_3d_set_doppler_factor(PN_stdfloat factor) {
514 audio_debug(
"MilesAudioManager::audio_3d_set_doppler_factor(factor="<<factor<<
")");
516 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
517 AIL_set_3D_doppler_factor(mgr->_digital_driver, factor);
525 PN_stdfloat MilesAudioManager::audio_3d_get_doppler_factor()
const {
526 audio_debug(
"MilesAudioManager::audio_3d_get_doppler_factor()");
528 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
529 return AIL_3D_doppler_factor(mgr->_digital_driver);
538 void MilesAudioManager::audio_3d_set_drop_off_factor(PN_stdfloat factor) {
539 audio_debug(
"MilesAudioManager::audio_3d_set_drop_off_factor("<<factor<<
")");
541 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
542 AIL_set_3D_rolloff_factor(mgr->_digital_driver, factor);
551 PN_stdfloat MilesAudioManager::audio_3d_get_drop_off_factor()
const {
552 audio_debug(
"MilesAudioManager::audio_3d_get_drop_off_factor()");
554 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
555 return AIL_3D_rolloff_factor(mgr->_digital_driver);
570 void MilesAudioManager::
572 audio_debug(
"MilesAudioManager::set_speaker_configuration()");
574 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
576 MSSVECTOR3D speakers[9];
578 if(speaker1 != NULL) {
579 speakers[0].x = speaker1->get_x();
580 speakers[0].y = speaker1->get_z();
581 speakers[0].z = speaker1->get_y();
583 if(speaker2 != NULL) {
584 speakers[1].x = speaker2->get_x();
585 speakers[1].y = speaker2->get_z();
586 speakers[1].z = speaker2->get_y();
588 if(speaker3 != NULL) {
589 speakers[2].x = speaker3->get_x();
590 speakers[2].y = speaker3->get_z();
591 speakers[2].z = speaker3->get_y();
593 if(speaker4 != NULL) {
594 speakers[3].x = speaker4->get_x();
595 speakers[3].y = speaker4->get_z();
596 speakers[3].z = speaker4->get_y();
598 if(speaker5 != NULL) {
599 speakers[4].x = speaker5->get_x();
600 speakers[4].y = speaker5->get_z();
601 speakers[4].z = speaker5->get_y();
603 if(speaker6 != NULL) {
604 speakers[5].x = speaker6->get_x();
605 speakers[5].y = speaker6->get_z();
606 speakers[5].z = speaker6->get_y();
608 if(speaker7 != NULL) {
609 speakers[6].x = speaker7->get_x();
610 speakers[6].y = speaker7->get_z();
611 speakers[6].z = speaker7->get_y();
613 if(speaker8 != NULL) {
614 speakers[7].x = speaker8->get_x();
615 speakers[7].y = speaker8->get_z();
616 speakers[7].z = speaker8->get_y();
618 if(speaker9 != NULL) {
619 speakers[8].x = speaker9->get_x();
620 speakers[8].y = speaker9->get_z();
621 speakers[8].z = speaker9->get_y();
624 if(speaker1 == NULL) {
625 audio_error(
"No valid speaker positions specified in MilesAudioManager::set_speaker_configuration().");
626 }
else if(speaker2 == NULL) {
627 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 1, 1.0);
628 }
else if(speaker3 == NULL) {
629 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 2, 1.0);
630 }
else if(speaker4 == NULL) {
631 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 3, 1.0);
632 }
else if(speaker5 == NULL) {
633 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 4, 1.0);
634 }
else if(speaker6 == NULL) {
635 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 5, 1.0);
636 }
else if(speaker7 == NULL) {
637 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 6, 1.0);
638 }
else if(speaker8 == NULL) {
639 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 7, 1.0);
640 }
else if(speaker9 == NULL) {
641 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 8, 1.0);
643 AIL_set_speaker_configuration(mgr->_digital_driver, speakers, 9, 1.0);
654 void MilesAudioManager::
658 if (_stream_thread.is_null() && !_streams.empty()) {
661 do_service_streams();
665 if (_sounds_finished) {
666 _sounds_finished =
false;
674 SoundsPlaying::iterator si = _sounds_playing.begin();
675 while (si != _sounds_playing.end()) {
676 MilesAudioSound *sound = (*si);
679 if (sound->status() == AudioSound::READY) {
691 void MilesAudioManager::
692 release_sound(MilesAudioSound *audioSound) {
693 audio_debug(
"MilesAudioManager::release_sound(audioSound=\"" 694 <<audioSound->get_name()<<
"\"), this = " << (
void *)
this);
696 AudioSet::iterator ai = _sounds_on_loan.find(audioSound);
697 if (ai != _sounds_on_loan.end()) {
698 _sounds_on_loan.erase(ai);
701 audio_debug(
"MilesAudioManager::release_sound() finished");
711 void MilesAudioManager::
713 audio_debug(
"MilesAudioManager::cleanup(), this = " << (
void *)
this 714 <<
", _cleanup_required = " << _cleanup_required);
716 if (!_cleanup_required) {
721 AudioSet orig_sounds;
722 orig_sounds.swap(_sounds_on_loan);
723 AudioSet::iterator ai;
724 for (ai = orig_sounds.begin(); ai != orig_sounds.end(); ++ai) {
731 if (!_stream_thread.is_null()) {
732 milesAudio_cat.info()
733 <<
"Stopping audio streaming thread.\n";
734 PT(StreamThread) old_thread;
737 nassertv(!_stream_thread.is_null());
738 _stream_thread->_keep_running =
false;
739 _streams_cvar.notify();
740 old_thread = _stream_thread;
741 _stream_thread.clear();
746 _cleanup_required =
false;
747 audio_debug(
"MilesAudioManager::cleanup() finished");
755 void MilesAudioManager::
756 output(ostream &out)
const {
758 out << get_type() <<
": " << _sounds_playing.size()
759 <<
" / " << _sounds_on_loan.size() <<
" sounds playing / total";
767 void MilesAudioManager::
768 write(ostream &out)
const {
771 out << (*this) <<
"\n";
772 AudioSet::const_iterator ai;
773 for (ai = _sounds_on_loan.begin(); ai != _sounds_on_loan.end(); ++ai) {
774 MilesAudioSound *sound = (*ai);
775 out <<
" " << *sound <<
"\n";
778 size_t total_preload = 0;
779 size_t num_preloaded = 0;
780 SoundMap::const_iterator si;
781 for (si = _sounds.begin(); si != _sounds.end(); ++si) {
782 if (!(*si).second->_raw_data.empty()) {
784 total_preload += (*si).second->_raw_data.size();
787 out << num_preloaded <<
" of " << _sounds.size() <<
" sounds preloaded, size used is " << (total_preload + 1023) / 1024 <<
"K\n";
791 out << _streams.size() <<
" streams opened.\n";
792 if (!_stream_thread.is_null()) {
793 out <<
"(Audio streaming thread has been started.)\n";
797 GlobalMilesManager *mgr = GlobalMilesManager::get_global_ptr();
799 int num_samples = mgr->get_num_samples();
800 out << num_samples <<
" sample handles allocated globally.\n";
802 int num_sequences = mgr->get_num_sequences();
803 out << num_sequences <<
" sequence handles allocated globally.\n";
813 bool MilesAudioManager::
816 if (_sounds.size() != _lru.size()) {
817 audio_debug(
"-- Error _sounds.size() != _lru.size() --");
821 LRU::const_iterator i = _lru.begin();
822 for (; i != _lru.end(); ++i) {
823 SoundMap::const_iterator smi = _sounds.find(**i);
824 if (smi == _sounds.end()) {
825 audio_debug(
"-- "<<**i<<
" in _lru and not in _sounds --");
831 return _is_valid && check;
839 void MilesAudioManager::
840 do_reduce_sounds_playing_to(
unsigned int count) {
841 int limit = _sounds_playing.size() - count;
842 while (limit-- > 0) {
843 SoundsPlaying::iterator sound = _sounds_playing.begin();
844 assert(sound != _sounds_playing.end());
854 void MilesAudioManager::
856 if (_is_valid) { nassertv(do_is_valid()); }
859 if (_is_valid) { nassertv(do_is_valid()); }
869 void MilesAudioManager::
870 start_service_stream(HSTREAM stream) {
872 nassertv(find(_streams.begin(), _streams.end(), stream) == _streams.end());
873 _streams.push_back(stream);
874 _streams_cvar.notify();
877 milesAudio_cat.info()
878 <<
"Starting audio streaming thread.\n";
879 _stream_thread =
new StreamThread(
this);
880 _stream_thread->start(TP_low,
true);
890 void MilesAudioManager::
891 stop_service_stream(HSTREAM stream) {
893 Streams::iterator si = find(_streams.begin(), _streams.end(), stream);
894 if (si != _streams.end()) {
905 void MilesAudioManager::
906 most_recently_used(
const string &path) {
907 audio_debug(
"MilesAudioManager::most_recently_used(path=\"" 909 LRU::iterator i=find(_lru.begin(), _lru.end(), &path);
910 if (i != _lru.end()) {
914 assert(find(_lru.begin(), _lru.end(), &path) == _lru.end());
915 _lru.push_back(&path);
916 nassertv(do_is_valid());
924 void MilesAudioManager::
926 audio_debug(
"MilesAudioManager::uncache_a_sound()");
927 nassertv(do_is_valid());
929 assert(_lru.size()>0);
930 LRU::reference path=_lru.front();
931 SoundMap::iterator i = _sounds.find(*path);
932 assert(i != _sounds.end());
935 if (i != _sounds.end()) {
936 audio_debug(
" uncaching \""<<i->first<<
"\"");
939 nassertv(do_is_valid());
947 void MilesAudioManager::
948 starting_sound(MilesAudioSound *audio) {
950 if (_concurrent_sound_limit) {
951 do_reduce_sounds_playing_to(_concurrent_sound_limit);
953 _sounds_playing.insert(audio);
963 void MilesAudioManager::
964 stopping_sound(MilesAudioSound *audio) {
966 _sounds_playing.erase(audio);
967 if (_hasMidiSounds && _sounds_playing.size() == 0) {
968 GlobalMilesManager::get_global_ptr()->force_midi_reset();
981 PT(MilesAudioManager::SoundData) MilesAudioManager::
983 PT(SoundData) sd =
new SoundData;
988 milesAudio_cat.warning()
989 <<
"No such file: " << file_name <<
"\n";
993 if (file->get_file_size() == 0) {
994 milesAudio_cat.warning()
995 <<
"File " << file_name <<
" is empty\n";
1001 string extension = sd->_basename.get_extension();
1002 if (extension ==
"pz") {
1003 extension =
Filename(sd->_basename.get_basename_wo_extension()).get_extension();
1006 bool is_midi_file = (downcase(extension) ==
"mid");
1008 if ((miles_audio_preload_threshold == -1 || file->get_file_size() < (streamsize)miles_audio_preload_threshold) ||
1014 if (!file->read_file(sd->_raw_data,
true)) {
1015 milesAudio_cat.warning()
1016 <<
"Unable to read " << file_name <<
"\n";
1021 AIL_file_type(&sd->_raw_data[0], sd->_raw_data.size());
1023 if (sd->_file_type == AILFILETYPE_MIDI) {
1028 if (AIL_MIDI_to_XMI(&sd->_raw_data[0], sd->_raw_data.size(),
1029 &xmi, &xmi_size, 0)) {
1030 audio_debug(
"converted " << sd->_basename <<
" from standard MIDI (" 1031 << sd->_raw_data.size() <<
" bytes) to XMIDI (" 1032 << xmi_size <<
" bytes)");
1036 sd->_raw_data.clear();
1037 sd->_raw_data.insert(sd->_raw_data.end(),
1038 (
unsigned char *)xmi, (
unsigned char *)xmi + xmi_size);
1039 AIL_mem_free_lock(xmi);
1040 sd->_file_type = AILFILETYPE_XMIDI;
1042 milesAudio_cat.warning()
1043 <<
"Could not convert " << sd->_basename <<
" to XMIDI.\n";
1047 bool expand_to_wav =
false;
1049 if (sd->_file_type != AILFILETYPE_MPEG_L3_AUDIO) {
1050 audio_debug(sd->_basename <<
" is not an mp3 file.");
1051 }
else if ((
int)sd->_raw_data.size() >= miles_audio_expand_mp3_threshold) {
1052 audio_debug(sd->_basename <<
" is too large to expand in-memory.");
1054 audio_debug(sd->_basename <<
" will be expanded in-memory.");
1055 expand_to_wav =
true;
1058 if (expand_to_wav) {
1064 if (AIL_decompress_ASI(&sd->_raw_data[0], sd->_raw_data.size(),
1065 sd->_basename.c_str(), &wav_data, &wav_data_size,
1067 audio_debug(
"expanded " << sd->_basename <<
" from " << sd->_raw_data.size()
1068 <<
" bytes to " << wav_data_size <<
" bytes.");
1070 if (wav_data_size != 0) {
1073 sd->_raw_data.clear();
1074 sd->_raw_data.insert(sd->_raw_data.end(),
1075 (
unsigned char *)wav_data, (
unsigned char *)wav_data + wav_data_size);
1076 sd->_file_type = AILFILETYPE_PCM_WAV;
1077 sd->_basename.set_extension(
"wav");
1079 AIL_mem_free_lock(wav_data);
1082 audio_debug(
"unable to expand " << sd->_basename);
1101 void MilesAudioManager::
1102 thread_main(
volatile bool &keep_running) {
1105 while (keep_running) {
1106 if (_streams.empty()) {
1109 _streams_cvar.wait();
1111 do_service_streams();
1115 _streams_lock.release();
1117 _streams_lock.acquire();
1127 void MilesAudioManager::
1128 do_service_streams() {
1130 while (i < _streams.size()) {
1131 HSTREAM stream = _streams[i];
1134 _streams_lock.release();
1135 AIL_service_stream(stream, 0);
1137 _streams_lock.acquire();
1148 MilesAudioManager::StreamThread::
1149 StreamThread(MilesAudioManager *mgr) :
1150 Thread(
"StreamThread",
"StreamThread"),
1153 _keep_running =
true;
1161 void MilesAudioManager::StreamThread::
1163 _mgr->thread_main(_keep_running);
1171 MilesAudioManager::SoundData::
1173 _raw_data(MilesAudioManager::get_class_type()),
1184 MilesAudioManager::SoundData::
1193 PN_stdfloat MilesAudioManager::SoundData::
1198 if (_raw_data.empty()) {
1202 }
else if (_file_type == AILFILETYPE_MPEG_L3_AUDIO) {
1205 audio_debug(
"Computing length of mp3 file " << _basename);
1208 AIL_inspect_MP3(&info, &_raw_data[0], _raw_data.size());
1210 while (AIL_enumerate_MP3_frames(&info)) {
1211 _length += info.data_size * 8.0f / info.bit_rate;
1215 }
else if (_file_type == AILFILETYPE_PCM_WAV ||
1216 _file_type == AILFILETYPE_ADPCM_WAV ||
1217 _file_type == AILFILETYPE_OTHER_ASI_WAV) {
1218 audio_debug(
"Getting length of wav file " << _basename);
1221 if (AIL_WAV_info(&_raw_data[0], &info)) {
1222 _length = (PN_stdfloat)info.samples / (PN_stdfloat)info.rate;
1223 audio_debug(info.samples <<
" samples at " << info.rate
1224 <<
"; length is " << _length <<
" seconds.");
1230 nassertr(_has_length, 0.0f);
1239 void MilesAudioManager::SoundData::
1240 set_length(PN_stdfloat
length) {
string get_basename() const
Returns the basename part of the filename.
This is the base class for all three-component vectors and points.
bool resolve_filename(Filename &filename, const DSearchPath &searchpath, const string &default_extension=string()) const
Searches the given search path for the filename.
A hierarchy of directories and files that appears to be one continuous file system, even though the files may originate from several different sources that may not be related to the actual OS's file system.
PN_stdfloat length() const
Get length FMOD returns the time in MS so we have to convert to seconds.
A lightweight C++ object whose constructor calls acquire() and whose destructor calls release() on a ...
static void consider_yield()
Possibly suspends the current thread for the rest of the current epoch, if it has run for enough this...
The abstract base class for a file or directory within the VirtualFileSystem.
static void force_yield()
Suspends the current thread for the rest of the current epoch.
static bool is_threading_supported()
Returns true if threading support has been compiled in and enabled, or false if no threading is avail...
The name of a file, such as a texture file or an Egg file.
static VirtualFileSystem * get_global_ptr()
Returns the default global VirtualFileSystem.
PointerTo< VirtualFile > get_file(const Filename &filename, bool status_only=false) const
Looks up the file by the indicated name in the file system.
Similar to MutexHolder, but for a light reentrant mutex.
A thread; that is, a lightweight process.
TypeHandle is the identifier used to differentiate C++ class types.
A MovieAudio is actually any source that provides a sequence of audio samples.