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);
298 audio_debug(
"FmodAudioSound::set_loop_count() Setting the sound's loop count to: " << loop_count);
303 if (loop_count == 0) {
304 result = _sound->setLoopCount( -1 );
305 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
306 result =_sound->setMode(FMOD_LOOP_NORMAL);
307 fmod_audio_errcheck(
"_sound->setMode()", result);
308 }
else if (loop_count == 1) {
309 result = _sound->setLoopCount( 1 );
310 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
311 result =_sound->setMode(FMOD_LOOP_OFF);
312 fmod_audio_errcheck(
"_sound->setMode()", result);
314 result = _sound->setLoopCount( loop_count );
315 fmod_audio_errcheck(
"_sound->setLoopCount()", result);
316 result =_sound->setMode(FMOD_LOOP_NORMAL);
317 fmod_audio_errcheck(
"_sound->setMode()", result);
320 audio_debug(
"FmodAudioSound::set_loop_count() Sound's loop count should be set to: " << loop_count);
332 result = _sound->getLoopCount( &loop_count );
333 fmod_audio_errcheck(
"_sound->getLoopCount()", result);
335 if (loop_count <= 0) {
338 return (
unsigned long)loop_count;
349 _start_time = start_time;
351 if (
status() == PLAYING) {
364 unsigned int current_time;
370 result = _channel->getPosition( ¤t_time , FMOD_TIMEUNIT_MS );
371 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
374 fmod_audio_errcheck(
"_channel->getPosition()", result);
376 return ((
double)current_time) / 1000.0;
386 set_volume_on_channel();
400 void FmodAudioSound::
410 int startTime = (int)(_start_time * 1000);
414 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
415 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
419 fmod_audio_errcheck(
"_channel->setPosition()", result);
422 result = _channel->isPlaying(&playing);
423 fmod_audio_errcheck(
"_channel->isPlaying()", result);
424 if (result != FMOD_OK || !playing) {
431 result = _manager->_system->playSound(FMOD_CHANNEL_FREE, _sound,
true, &_channel);
432 fmod_audio_errcheck(
"_system->playSound()", result);
433 result = _channel->setChannelGroup(_manager->_channelgroup);
434 fmod_audio_errcheck(
"_channel->setChannelGroup()", result);
435 result = _channel->setUserData(
this);
436 fmod_audio_errcheck(
"_channel->setUserData()", result);
437 result = _channel->setCallback(sound_end_callback);
438 fmod_audio_errcheck(
"_channel->setCallback()", result);
439 result = _channel->setPosition( startTime , FMOD_TIMEUNIT_MS );
440 fmod_audio_errcheck(
"_channel->setPosition()", result);
442 set_volume_on_channel();
443 set_play_rate_on_channel();
444 set_speaker_mix_or_balance_on_channel();
446 set_3d_attributes_on_channel();
448 result = _channel->setPaused(
false);
449 fmod_audio_errcheck(
"_channel->setPaused()", result);
458 void FmodAudioSound::
459 set_volume_on_channel() {
464 result = _channel->setVolume( _volume );
465 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
468 fmod_audio_errcheck(
"_channel->setVolume()", result);
480 set_speaker_mix_or_balance_on_channel();
503 set_play_rate_on_channel();
509 PN_stdfloat FmodAudioSound::
510 get_play_rate()
const {
517 void FmodAudioSound::
518 set_play_rate_on_channel() {
521 PN_stdfloat frequency = _sampleFrequency * _playrate;
524 result = _channel->setFrequency( frequency );
525 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
528 fmod_audio_errcheck(
"_channel->setFrequency()", result);
550 result = _sound->getLength( &
length, FMOD_TIMEUNIT_MS );
551 fmod_audio_errcheck(
"_sound->getLength()", result);
553 return ((
double)
length) / 1000.0;
568 set_3d_attributes(PN_stdfloat px, PN_stdfloat py, PN_stdfloat pz, PN_stdfloat vx, PN_stdfloat vy, PN_stdfloat vz) {
578 set_3d_attributes_on_channel();
584 void FmodAudioSound::
585 set_3d_attributes_on_channel() {
590 result = _sound->getMode(&soundMode);
591 fmod_audio_errcheck(
"_sound->getMode()", result);
593 if ((_channel != 0) && (soundMode & FMOD_3D)) {
594 result = _channel->set3DAttributes( &_location, &_velocity );
595 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
598 fmod_audio_errcheck(
"_channel->set3DAttributes()", result);
608 get_3d_attributes(PN_stdfloat *px, PN_stdfloat *py, PN_stdfloat *pz, PN_stdfloat *vx, PN_stdfloat *vy, PN_stdfloat *vz) {
609 audio_error(
"get3dAttributes: Currently unimplemented. Get the attributes of the attached object.");
623 result = _sound->set3DMinMaxDistance( dist, _max_dist );
624 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
645 result = _sound->set3DMinMaxDistance( _min_dist, dist );
646 fmod_audio_errcheck(
"_sound->set3DMinMaxDistance()", result);
683 result = _channel->getSpeakerMix( &frontleft, &frontright, ¢er, &sub, &backleft, &backright, &sideleft, &sideright );
684 fmod_audio_errcheck(
"_channel->getSpeakerMix()", result);
687 case AudioManager::SPK_frontleft:
return frontleft;
688 case AudioManager::SPK_frontright:
return frontright;
689 case AudioManager::SPK_center:
return center;
690 case AudioManager::SPK_sub:
return sub;
691 case AudioManager::SPK_backleft:
return backleft;
692 case AudioManager::SPK_backright:
return backright;
693 case AudioManager::SPK_sideleft:
return sideleft;
694 case AudioManager::SPK_sideright:
return sideright;
708 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) {
710 _mix[AudioManager::SPK_frontleft] = frontleft;
711 _mix[AudioManager::SPK_frontright] = frontright;
712 _mix[AudioManager::SPK_center] = center;
713 _mix[AudioManager::SPK_sub] = sub;
714 _mix[AudioManager::SPK_backleft] = backleft;
715 _mix[AudioManager::SPK_backright] = backright;
716 _mix[AudioManager::SPK_sideleft] = sideleft;
717 _mix[AudioManager::SPK_sideright] = sideright;
719 set_speaker_mix_or_balance_on_channel();
730 void FmodAudioSound::
731 set_speaker_mix_or_balance_on_channel() {
736 result = _sound->getMode(&soundMode);
737 fmod_audio_errcheck(
"_sound->getMode()", result);
739 if ((_channel != 0) && (( soundMode & FMOD_3D ) == 0)) {
740 if ( _speakermode == FMOD_SPEAKERMODE_STEREO ) {
741 result = _channel->setPan( _balance );
743 result = _channel->setSpeakerMix( _mix[AudioManager::SPK_frontleft],
744 _mix[AudioManager::SPK_frontright],
745 _mix[AudioManager::SPK_center],
746 _mix[AudioManager::SPK_sub],
747 _mix[AudioManager::SPK_backleft],
748 _mix[AudioManager::SPK_backright],
749 _mix[AudioManager::SPK_sideleft],
750 _mix[AudioManager::SPK_sideright]
753 if (result == FMOD_ERR_INVALID_HANDLE || result == FMOD_ERR_CHANNEL_STOLEN) {
756 fmod_audio_errcheck(
"_channel->setSpeakerMix()/setPan()", result);
767 audio_debug(
"FmodAudioSound::get_priority()");
775 void FmodAudioSound::
776 set_priority(
int priority) {
779 audio_debug(
"FmodAudioSound::set_priority()");
783 _priority = priority;
785 result = _sound->setDefaults( _sampleFrequency, _volume , _balance, _priority);
786 fmod_audio_errcheck(
"_sound->setDefaults()", result);
798 if ( _channel == 0 ) {
802 result = _channel->isPlaying( &playingState );
803 if ((result == FMOD_OK) && (playingState ==
true)) {
818 if (_active != active) {
830 if (
status() == PLAYING) {
857 audio_error(
"finished: not implemented under FMOD-EX");
867 audio_error(
"set_finished_event: not implemented under FMOD-EX");
878 audio_error(
"get_finished_event: not implemented under FMOD-EX");
879 return _finished_event;
886 FMOD_RESULT F_CALLBACK FmodAudioSound::
887 sound_end_callback(FMOD_CHANNEL * channel,
888 FMOD_CHANNEL_CALLBACKTYPE type,
890 void *commanddata2) {
894 if (type == FMOD_CHANNEL_CALLBACKTYPE_END) {
895 FMOD::Channel *fc = (FMOD::Channel *)channel;
896 void *userdata =
nullptr;
897 FMOD_RESULT result = fc->getUserData(&userdata);
898 fmod_audio_errcheck(
"channel->getUserData()", result);
900 fsound->_self_ref = fsound;
908 FMOD_RESULT F_CALLBACK FmodAudioSound::
909 open_callback(
const char *name,
int,
unsigned int *file_size,
910 void **handle,
void **user_data) {
913 if (file ==
nullptr) {
914 return FMOD_ERR_FILE_NOTFOUND;
916 if (fmodAudio_cat.is_spam()) {
918 <<
"open_callback(" << *file <<
")\n";
924 (*handle) = (
void *)str;
925 (*user_data) = (
void *)file;
937 FMOD_RESULT F_CALLBACK FmodAudioSound::
938 close_callback(
void *handle,
void *user_data) {
940 if (fmodAudio_cat.is_spam()) {
942 <<
"close_callback(" << *file <<
")\n";
947 istream *str = (istream *)handle;
959 FMOD_RESULT F_CALLBACK FmodAudioSound::
960 read_callback(
void *handle,
void *buffer,
unsigned int size_bytes,
961 unsigned int *bytes_read,
void *user_data) {
963 if (fmodAudio_cat.is_spam()) {
965 <<
"read_callback(" << *file <<
", " << size_bytes <<
")\n";
968 istream *str = (istream *)handle;
969 str->read((
char *)buffer, size_bytes);
970 (*bytes_read) = str->gcount();
978 if ((*bytes_read) == 0) {
979 return FMOD_ERR_FILE_EOF;
985 return FMOD_ERR_FILE_BAD;
994 FMOD_RESULT F_CALLBACK FmodAudioSound::
995 seek_callback(
void *handle,
unsigned int pos,
void *user_data) {
997 if (fmodAudio_cat.is_spam()) {
999 <<
"seek_callback(" << *file <<
", " << pos <<
")\n";
1002 istream *str = (istream *)handle;
1006 if (str->fail() && !str->eof()) {
1007 return FMOD_ERR_FILE_COULDNOTSEEK;