44 audio_debug(
"FmodAudioSound::FmodAudioSound() Creating new sound, filename: "
47 _active = manager->get_active();
64 _max_dist = 1000000000.0;
71 for (
int i=0; i<AudioManager::SPK_COUNT; i++) {
77 DCAST_INTO_V(fmanager, manager);
85 result = _manager->_system->getSpeakerMode( &_speakermode );
86 fmod_audio_errcheck(
"_system->getSpeakerMode()", result);
89 bool preload = (fmod_audio_preload_threshold < 0) || (file->
get_file_size() < fmod_audio_preload_threshold);
90 int flags = FMOD_SOFTWARE;
91 flags |= positional ? FMOD_3D : FMOD_2D;
93 FMOD_CREATESOUNDEXINFO sound_info;
94 memset(&sound_info, 0,
sizeof(sound_info));
95 sound_info.cbsize =
sizeof(sound_info);
100 memcpy(&sound_info, &_manager->_midi_info,
sizeof(sound_info));
101 if (sound_info.dlsname !=
nullptr) {
102 audio_debug(
"Using DLS file " << sound_info.dlsname);
106 const char *name_or_data = _file_name.c_str();
109 vector_uchar mem_buffer;
116 sound_info.length = mem_buffer.size();
117 if (mem_buffer.size() != 0) {
118 name_or_data = (
const char *)&mem_buffer[0];
120 flags |= FMOD_OPENMEMORY;
121 if (fmodAudio_cat.is_debug()) {
122 fmodAudio_cat.debug()
123 <<
"Reading " << _file_name <<
" into memory (" << sound_info.length
127 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
130 result = FMOD_ERR_FILE_BAD;
137 os_filename = info.get_filename().to_os_specific();
138 name_or_data = os_filename.c_str();
139 sound_info.fileoffset = (
unsigned int)info.get_start();
140 sound_info.length = (
unsigned int)info.get_size();
141 flags |= FMOD_CREATESTREAM;
142 if (fmodAudio_cat.is_debug()) {
143 fmodAudio_cat.debug()
144 <<
"Streaming " << _file_name <<
" from disk (" << name_or_data
145 <<
", " << sound_info.fileoffset <<
", " << sound_info.length <<
")\n";
149 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
154 if (result == FMOD_ERR_FILE_BAD) {
155 #if defined(HAVE_THREADS) && !defined(SIMPLE_THREADS)
158 name_or_data = (
const char *)file;
159 sound_info.fileoffset = 0;
160 sound_info.length = (
unsigned int)info.get_size();
161 sound_info.useropen = open_callback;
162 sound_info.userclose = close_callback;
163 sound_info.userread = read_callback;
164 sound_info.userseek = seek_callback;
165 flags |= FMOD_CREATESTREAM;
166 if (fmodAudio_cat.is_debug()) {
167 fmodAudio_cat.debug()
168 <<
"Streaming " << _file_name <<
" from disk using callbacks\n";
171 _manager->_system->createSound(name_or_data, flags, &sound_info, &_sound);
173 #else // HAVE_THREADS && !SIMPLE_THREADS
177 fmodAudio_cat.warning()
178 <<
"Cannot stream " << _file_name <<
"; file is not literally on disk.\n";
184 if (result != FMOD_OK) {
185 audio_error(
"createSound(" << _file_name <<
"): " << FMOD_ErrorString(result));
188 FMOD_CREATESOUNDEXINFO sound_info;
189 memset(&sound_info, 0,
sizeof(sound_info));
190 char blank_data[100];
191 memset(blank_data, 0,
sizeof(blank_data));
192 sound_info.cbsize =
sizeof(sound_info);
193 sound_info.length =
sizeof(blank_data);
194 sound_info.numchannels = 1;
195 sound_info.defaultfrequency = 8000;
196 sound_info.format = FMOD_SOUND_FORMAT_PCM16;
197 int flags = FMOD_SOFTWARE | FMOD_OPENMEMORY | FMOD_OPENRAW;
199 result = _manager->_system->createSound( blank_data, flags, &sound_info, &_sound);
200 fmod_audio_errcheck(
"createSound (blank)", result);
205 _sound->setLoopCount(1);
206 _sound->setMode(FMOD_LOOP_OFF);
213 result = _sound->getDefaults( &_sampleFrequency, &_volume , &_balance, &_priority);
214 fmod_audio_errcheck(
"_sound->getDefaults()", result);
227 _manager->_all_sounds.erase(
this);
230 result = _sound->release();
231 fmod_audio_errcheck(
"_sound->release()", result);
252 result =_channel->stop();
253 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
255 }
else if (result == FMOD_OK) {
258 fmod_audio_errcheck(
"_channel->stop()", result);
297 audio_debug(
"FmodAudioSound::set_loop_count() Setting the sound's loop count to: " << loop_count);
302 if (loop_count == 0) {
303 result = _sound->setLoopCount( -1 );
304 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
305 result =_sound->setMode(FMOD_LOOP_NORMAL);
306 fmod_audio_errcheck(
"_sound->setMode()", result);
307 }
else if (loop_count == 1) {
308 result = _sound->setLoopCount( 1 );
309 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
310 result =_sound->setMode(FMOD_LOOP_OFF);
311 fmod_audio_errcheck(
"_sound->setMode()", result);
313 result = _sound->setLoopCount( loop_count );
314 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
315 result =_sound->setMode(FMOD_LOOP_NORMAL);
316 fmod_audio_errcheck(
"_sound->setMode()", result);
319 audio_debug(
"FmodAudioSound::set_loop_count() Sound's loop count should be set to: " << loop_count);
331 result = _sound->getLoopCount( &loop_count );
332 fmod_audio_errcheck(
"_sound->getLoopCount()", result);
334 if (loop_count <= 0) {
337 return (
unsigned long)loop_count;
348 _start_time = start_time;
350 if (
status() == PLAYING) {
363 unsigned int current_time;
369 result = _channel->getPosition( ¤t_time , FMOD_TIMEUNIT_MS );
370 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
373 fmod_audio_errcheck(
"_channel->getPosition()", result);
375 return ((
double)current_time) / 1000.0;
385 set_volume_on_channel();
399 void FmodAudioSound::
409 int startTime = (int)(_start_time * 1000);
413 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
414 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
418 fmod_audio_errcheck(
"_channel->setPosition()", result);
421 result = _channel->isPlaying(&playing);
422 fmod_audio_errcheck(
"_channel->isPlaying()", result);
423 if (result != FMOD_OK || !playing) {
430 result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound,
true, &_channel);
431 fmod_audio_errcheck(
"_system->playSound()", result);
432 result = _channel->setChannelGroup(_manager->_channelgroup);
433 fmod_audio_errcheck(
"_channel->setChannelGroup()", result);
434 result = _channel->setUserData(
this);
435 fmod_audio_errcheck(
"_channel->setUserData()", result);
436 result = _channel->setCallback(sound_end_callback);
437 fmod_audio_errcheck(
"_channel->setCallback()", result);
438 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
439 fmod_audio_errcheck(
"_channel->setPosition()", result);
441 set_volume_on_channel();
442 set_play_rate_on_channel();
443 set_speaker_mix_or_balance_on_channel();
445 set_3d_attributes_on_channel();
447 result = _channel->setPaused(
false);
448 fmod_audio_errcheck(
"_channel->setPaused()", result);
457 void FmodAudioSound::
458 set_volume_on_channel() {
463 result = _channel->setVolume( _volume );
464 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
467 fmod_audio_errcheck(
"_channel->setVolume()", result);
479 set_speaker_mix_or_balance_on_channel();
502 set_play_rate_on_channel();
508 PN_stdfloat FmodAudioSound::
509 get_play_rate()
const {
516 void FmodAudioSound::
517 set_play_rate_on_channel() {
520 PN_stdfloat frequency = _sampleFrequency * _playrate;
523 result = _channel->setFrequency( frequency );
524 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
527 fmod_audio_errcheck(
"_channel->setFrequency()", result);
549 result = _sound->getLength( &
length, FMOD_TIMEUNIT_MS );
550 fmod_audio_errcheck(
"_sound->getLength()", result);
552 return ((
double)
length) / 1000.0;
567 set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
577 set_3d_attributes_on_channel();
583 void FmodAudioSound::
584 set_3d_attributes_on_channel() {
589 result = _sound->getMode(&soundMode);
590 fmod_audio_errcheck(
"_sound->getMode()", result);
592 if ((_channel != 0) && (soundMode & FMOD_3D)) {
593 result = _channel->set3DAttributes( &_location, &_velocity );
594 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
597 fmod_audio_errcheck(
"_channel->set3DAttributes()", result);
607 get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
608 audio_error(
"get3dAttributes: Currently unimplemented. Get the attributes of the attached object.");
622 result = _sound->set3DMinMaxDistance( dist, _max_dist );
623 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
644 result = _sound->set3DMinMaxDistance( _min_dist, dist );
645 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
682 result = _channel->getSpeakerMix( &frontleft, &frontright, ¢er, &sub, &backleft, &backright, &sideleft, &sideright );
683 fmod_audio_errcheck(
"_channel->getSpeakerMix()", result);
686 case AudioManager::SPK_frontleft:
return frontleft;
687 case AudioManager::SPK_frontright:
return frontright;
688 case AudioManager::SPK_center:
return center;
689 case AudioManager::SPK_sub:
return sub;
690 case AudioManager::SPK_backleft:
return backleft;
691 case AudioManager::SPK_backright:
return backright;
692 case AudioManager::SPK_sideleft:
return sideleft;
693 case AudioManager::SPK_sideright:
return sideright;
707 set_speaker_mix(PN_stdfloat frontleft, PN_stdfloat frontright, PN_stdfloat center, PN_stdfloat sub, PN_stdfloat backleft, PN_stdfloat backright, PN_stdfloat sideleft, PN_stdfloat sideright) {
709 _mix[AudioManager::SPK_frontleft] = frontleft;
710 _mix[AudioManager::SPK_frontright] = frontright;
711 _mix[AudioManager::SPK_center] = center;
712 _mix[AudioManager::SPK_sub] = sub;
713 _mix[AudioManager::SPK_backleft] = backleft;
714 _mix[AudioManager::SPK_backright] = backright;
715 _mix[AudioManager::SPK_sideleft] = sideleft;
716 _mix[AudioManager::SPK_sideright] = sideright;
718 set_speaker_mix_or_balance_on_channel();
729 void FmodAudioSound::
730 set_speaker_mix_or_balance_on_channel() {
735 result = _sound->getMode(&soundMode);
736 fmod_audio_errcheck(
"_sound->getMode()", result);
738 if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) {
739 if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) {
740 result = _channel->setPan( _balance );
742 result = _channel->setSpeakerMix( _mix[AudioManager::SPK_frontleft],
743 _mix[AudioManager::SPK_frontright],
744 _mix[AudioManager::SPK_center],
745 _mix[AudioManager::SPK_sub],
746 _mix[AudioManager::SPK_backleft],
747 _mix[AudioManager::SPK_backright],
748 _mix[AudioManager::SPK_sideleft],
749 _mix[AudioManager::SPK_sideright]
752 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
755 fmod_audio_errcheck(
"_channel->setSpeakerMix()/setPan()", result);
766 audio_debug(
"FmodAudioSound::get_priority()");
774 void FmodAudioSound::
775 set_priority(
int priority) {
778 audio_debug(
"FmodAudioSound::set_priority()");
782 _priority = priority;
784 result = _sound->setDefaults( _sampleFrequency, _volume , _balance, _priority);
785 fmod_audio_errcheck(
"_sound->setDefaults()", result);
797 if ( _channel == 0 ) {
801 result = _channel->isPlaying( &playingState );
802 if ((result == FMOD_OK) && (playingState ==
true)) {
817 if (_active != active) {
829 if (
status() == PLAYING) {
855 audio_error(
"finished: not implemented under FMOD-EX");
865 audio_error(
"set_finished_event: not implemented under FMOD-EX");
876 audio_error(
"get_finished_event: not implemented under FMOD-EX");
877 return _finished_event;
884 FMOD_RESULT F_CALLBACK FmodAudioSound::
885 sound_end_callback(FMOD_CHANNEL * channel,
886 FMOD_CHANNEL_CALLBACKTYPE type,
888 void *commanddata2) {
892 if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
893 FMOD::Channel *fc = (FMOD::Channel *)channel;
894 void *userdata =
nullptr;
895 FMOD_RESULT result = fc->getUserData(&userdata);
896 fmod_audio_errcheck(
"channel->getUserData()", result);
898 fsound->_self_ref = fsound;
906 FMOD_RESULT F_CALLBACK FmodAudioSound::
907 open_callback(
const char *name,
int,
unsigned int *file_size,
908 void **handle,
void **user_data) {
911 if (file ==
nullptr) {
912 return FMOD_ERR_FILE_NOTFOUND;
914 if (fmodAudio_cat.is_spam()) {
916 <<
"open_callback(" << *file <<
")\n";
922 (*handle) = (
void *)str;
923 (*user_data) = (
void *)file;
935 FMOD_RESULT F_CALLBACK FmodAudioSound::
936 close_callback(
void *handle,
void *user_data) {
938 if (fmodAudio_cat.is_spam()) {
940 <<
"close_callback(" << *file <<
")\n";
945 istream *str = (istream *)handle;
957 FMOD_RESULT F_CALLBACK FmodAudioSound::
958 read_callback(
void *handle,
void *buffer,
unsigned int size_bytes,
959 unsigned int *bytes_read,
void *user_data) {
961 if (fmodAudio_cat.is_spam()) {
963 <<
"read_callback(" << *file <<
", " << size_bytes <<
")\n";
966 istream *str = (istream *)handle;
967 str->read((
char *)buffer, size_bytes);
968 (*bytes_read) = str->gcount();
976 if ((*bytes_read) == 0) {
977 return FMOD_ERR_FILE_EOF;
983 return FMOD_ERR_FILE_BAD;
992 FMOD_RESULT F_CALLBACK FmodAudioSound::
993 seek_callback(
void *handle,
unsigned int pos,
void *user_data) {
995 if (fmodAudio_cat.is_spam()) {
997 <<
"seek_callback(" << *file <<
", " << pos <<
")\n";
1000 istream *str = (istream *)handle;
1004 if (str->fail() && !str->eof()) {
1005 return FMOD_ERR_FILE_COULDNOTSEEK;