32 #include <OgreResourceGroupManager.h>
34 #define LOGSTREAM Ogre::LogManager::getSingleton().stream() << "[RoR|Audio] "
38 int err = alGetError();
39 if (err != AL_NO_ERROR)
42 snprintf(buf, 1000,
"OpenAL Error: %s (0x%x), @ %s:%d", alGetString(err), err, filename, linenum);
49 #define hasALErrors() _checkALErrors(__FILE__, __LINE__)
62 LOGSTREAM <<
"No audio device configured, opening default.";
63 audio_device = alcOpenDevice(
nullptr);
72 audio_device = alcOpenDevice(
nullptr);
78 LOGSTREAM <<
"Failed to open default audio device. Sound disabled.";
83 sound_context = alcCreateContext(audio_device, NULL);
87 alcCloseDevice(audio_device);
93 alcMakeContextCurrent(sound_context);
95 if (alGetString(AL_VENDOR)) LOG(
"SoundManager: OpenAL vendor is: " + String(alGetString(AL_VENDOR)));
96 if (alGetString(AL_VERSION)) LOG(
"SoundManager: OpenAL version is: " + String(alGetString(AL_VERSION)));
97 if (alGetString(AL_RENDERER)) LOG(
"SoundManager: OpenAL renderer is: " + String(alGetString(AL_RENDERER)));
98 if (alGetString(AL_EXTENSIONS)) LOG(
"SoundManager: OpenAL extensions are: " + String(alGetString(AL_EXTENSIONS)));
99 if (alcGetString(audio_device, ALC_DEVICE_SPECIFIER)) LOG(
"SoundManager: OpenAL device is: " + String(alcGetString(audio_device, ALC_DEVICE_SPECIFIER)));
100 if (alcGetString(audio_device, ALC_EXTENSIONS)) LOG(
"SoundManager: OpenAL ALC extensions are: " + String(alcGetString(audio_device, ALC_EXTENSIONS)));
103 m_efx_is_available = alcIsExtensionPresent(audio_device,
"ALC_EXT_EFX");
104 if (m_efx_is_available)
106 LOG(
"SoundManager: Found OpenAL EFX extension");
109 alGenEffects = (LPALGENEFFECTS)alGetProcAddress(
"alGenEffects");
110 alDeleteEffects = (LPALDELETEEFFECTS)alGetProcAddress(
"alDeleteEffects");
111 alIsEffect = (LPALISEFFECT)alGetProcAddress(
"alIsEffect");
112 alEffecti = (LPALEFFECTI)alGetProcAddress(
"alEffecti");
113 alEffectf = (LPALEFFECTF)alGetProcAddress(
"alEffectf");
114 alEffectfv = (LPALEFFECTFV)alGetProcAddress(
"alEffectfv");
115 alGenFilters = (LPALGENFILTERS)alGetProcAddress(
"alGenFilters");
116 alDeleteFilters = (LPALDELETEFILTERS)alGetProcAddress(
"alDeleteFilters");
117 alIsFilter = (LPALISFILTER)alGetProcAddress(
"alIsFilter");
118 alFilteri = (LPALFILTERI)alGetProcAddress(
"alFilteri");
119 alFilterf = (LPALFILTERF)alGetProcAddress(
"alFilterf");
120 alGenAuxiliaryEffectSlots = (LPALGENAUXILIARYEFFECTSLOTS)alGetProcAddress(
"alGenAuxiliaryEffectSlots");
121 alDeleteAuxiliaryEffectSlots = (LPALDELETEAUXILIARYEFFECTSLOTS)alGetProcAddress(
"alDeleteAuxiliaryEffectSlots");
122 alIsAuxiliaryEffectSlot = (LPALISAUXILIARYEFFECTSLOT)alGetProcAddress(
"alIsAuxiliaryEffectSlot");
123 alAuxiliaryEffectSloti = (LPALAUXILIARYEFFECTSLOTI)alGetProcAddress(
"alAuxiliaryEffectSloti");
124 alAuxiliaryEffectSlotf = (LPALAUXILIARYEFFECTSLOTF)alGetProcAddress(
"alAuxiliaryEffectSlotf");
125 alAuxiliaryEffectSlotfv = (LPALAUXILIARYEFFECTSLOTFV)alGetProcAddress(
"alAuxiliaryEffectSlotfv");
136 LOG(
"SoundManager: Reverb engine disabled");
141 if (alGetEnumValue(
"AL_EFFECT_EAXREVERB") != 0)
143 LOG(
"SoundManager: OpenAL driver supports AL_EFFECT_EAXREVERB, using it");
147 LOG(
"SoundManager: AL_EFFECT_EAXREVERB requested but OpenAL driver does not support it, falling back to standard reverb. Advanced features, such as reflection panning, will not be available");
153 LOG(
"SoundManager: Using OpenAL standard reverb");
157 if (!this->alIsAuxiliaryEffectSlot(m_listener_slot))
161 this->alGenAuxiliaryEffectSlots(1, &m_listener_slot);
162 ALuint error = alGetError();
164 if (error != AL_NO_ERROR)
166 LOG(
"SoundManager: alGenAuxiliaryEffectSlots for listener_slot failed: " +
TOSTRING(alGetString(error)));
167 m_listener_slot = AL_EFFECTSLOT_NULL;
171 this->PrepopulateEfxPropertiesMap();
181 this->alGenFilters(1, &m_efx_outdoor_obstruction_lowpass_filter_id);
182 ALuint e = alGetError();
184 if (e != AL_NO_ERROR)
186 m_efx_outdoor_obstruction_lowpass_filter_id = AL_FILTER_NULL;
190 this->alFilteri(m_efx_outdoor_obstruction_lowpass_filter_id, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
191 this->alFilterf(m_efx_outdoor_obstruction_lowpass_filter_id, AL_LOWPASS_GAIN, 0.33f);
192 this->alFilterf(m_efx_outdoor_obstruction_lowpass_filter_id, AL_LOWPASS_GAINHF, 0.25f);
203 this->alGenFilters(1, &m_efx_occlusion_wet_path_lowpass_filter_id);
206 if (e != AL_NO_ERROR)
208 m_efx_occlusion_wet_path_lowpass_filter_id = AL_FILTER_NULL;
212 this->alFilteri(m_efx_occlusion_wet_path_lowpass_filter_id, AL_FILTER_TYPE, AL_FILTER_LOWPASS);
213 this->alFilterf(m_efx_occlusion_wet_path_lowpass_filter_id, AL_LOWPASS_GAIN, 0.33f);
214 this->alFilterf(m_efx_occlusion_wet_path_lowpass_filter_id, AL_LOWPASS_GAINHF, 0.25f);
220 LOG(
"SoundManager: OpenAL EFX extension not found, disabling EFX");
225 for (hardware_sources_num = 0; hardware_sources_num < MAX_HARDWARE_SOURCES; hardware_sources_num++)
228 alGenSources(1, &hardware_sources[hardware_sources_num]);
229 if (alGetError() != AL_NO_ERROR)
231 alSourcef(hardware_sources[hardware_sources_num], AL_REFERENCE_DISTANCE, REFERENCE_DISTANCE);
232 alSourcef(hardware_sources[hardware_sources_num], AL_ROLLOFF_FACTOR, ROLLOFF_FACTOR);
233 alSourcef(hardware_sources[hardware_sources_num], AL_MAX_DISTANCE, MAX_DISTANCE);
238 alSource3i(hardware_sources[hardware_sources_num], AL_AUXILIARY_SEND_FILTER, m_listener_slot, 0, AL_FILTER_NULL);
243 alSpeedOfSound(343.3f);
245 for (
int i = 0; i < MAX_HARDWARE_SOURCES; i++)
247 hardware_sources_map[i] = -1;
256 alDeleteSources(MAX_HARDWARE_SOURCES, hardware_sources);
257 alDeleteBuffers(MAX_AUDIO_BUFFERS, audio_buffers);
259 if (m_efx_is_available)
261 if (this->alIsFilter(m_efx_outdoor_obstruction_lowpass_filter_id))
263 this->alDeleteFilters(1, &m_efx_outdoor_obstruction_lowpass_filter_id);
266 if (this->alIsFilter(m_efx_occlusion_wet_path_lowpass_filter_id))
268 this->alDeleteFilters(1, &m_efx_occlusion_wet_path_lowpass_filter_id);
271 if (this->alIsAuxiliaryEffectSlot(m_listener_slot))
273 this->alAuxiliaryEffectSloti(m_listener_slot, AL_EFFECTSLOT_EFFECT, AL_EFFECTSLOT_NULL);
274 this->alDeleteAuxiliaryEffectSlots(1, &m_listener_slot);
282 sound_context = alcGetCurrentContext();
283 audio_device = alcGetContextsDevice(sound_context);
284 alcMakeContextCurrent(NULL);
285 alcDestroyContext(sound_context);
288 alcCloseDevice(audio_device);
290 LOG(
"SoundManager destroyed.");
295 if (m_efx_is_available)
297 m_listener_efx_reverb_properties =
nullptr;
298 if (this->alIsAuxiliaryEffectSlot(m_listener_slot))
300 this->alAuxiliaryEffectSloti(m_listener_slot, AL_EFFECTSLOT_EFFECT, AL_EFFECTSLOT_NULL);
303 for (
auto it = m_efx_effect_id_map.begin(); it != m_efx_effect_id_map.end();)
305 this->DeleteAlEffect(it->second);
306 it = m_efx_effect_id_map.erase(it);
315 const auto it = m_efx_properties_map.find(efx_preset_name);
317 if (it != m_efx_properties_map.end())
329 m_efx_properties_map[
"EFX_REVERB_PRESET_GENERIC"] = EFX_REVERB_PRESET_GENERIC;
330 m_efx_properties_map[
"EFX_REVERB_PRESET_ROOM"] = EFX_REVERB_PRESET_ROOM;
331 m_efx_properties_map[
"EFX_REVERB_PRESET_CAVE"] = EFX_REVERB_PRESET_CAVE;
332 m_efx_properties_map[
"EFX_REVERB_PRESET_ARENA"] = EFX_REVERB_PRESET_ARENA;
333 m_efx_properties_map[
"EFX_REVERB_PRESET_HANGAR"] = EFX_REVERB_PRESET_HANGAR;
334 m_efx_properties_map[
"EFX_REVERB_PRESET_ALLEY"] = EFX_REVERB_PRESET_ALLEY;
335 m_efx_properties_map[
"EFX_REVERB_PRESET_HALLWAY"] = EFX_REVERB_PRESET_HALLWAY;
336 m_efx_properties_map[
"EFX_REVERB_PRESET_FOREST"] = EFX_REVERB_PRESET_FOREST;
337 m_efx_properties_map[
"EFX_REVERB_PRESET_CITY"] = EFX_REVERB_PRESET_CITY;
338 m_efx_properties_map[
"EFX_REVERB_PRESET_MOUNTAINS"] = EFX_REVERB_PRESET_MOUNTAINS;
339 m_efx_properties_map[
"EFX_REVERB_PRESET_QUARRY"] = EFX_REVERB_PRESET_QUARRY;
340 m_efx_properties_map[
"EFX_REVERB_PRESET_PLAIN"] = EFX_REVERB_PRESET_PLAIN;
341 m_efx_properties_map[
"EFX_REVERB_PRESET_PARKINGLOT"] = EFX_REVERB_PRESET_PARKINGLOT;
342 m_efx_properties_map[
"EFX_REVERB_PRESET_UNDERWATER"] = EFX_REVERB_PRESET_UNDERWATER;
343 m_efx_properties_map[
"EFX_REVERB_PRESET_DRUGGED"] = EFX_REVERB_PRESET_DRUGGED;
344 m_efx_properties_map[
"EFX_REVERB_PRESET_DIZZY"] = EFX_REVERB_PRESET_DIZZY;
345 m_efx_properties_map[
"EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE"] = EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE;
346 m_efx_properties_map[
"EFX_REVERB_PRESET_CASTLE_LARGEROOM"] = EFX_REVERB_PRESET_CASTLE_LARGEROOM;
347 m_efx_properties_map[
"EFX_REVERB_PRESET_CASTLE_LONGPASSAGE"] = EFX_REVERB_PRESET_CASTLE_LONGPASSAGE;
348 m_efx_properties_map[
"EFX_REVERB_PRESET_CASTLE_HALL"] = EFX_REVERB_PRESET_CASTLE_HALL;
349 m_efx_properties_map[
"EFX_REVERB_PRESET_CASTLE_COURTYARD"] = EFX_REVERB_PRESET_CASTLE_COURTYARD;
350 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_SMALLROOM"] = EFX_REVERB_PRESET_FACTORY_SMALLROOM;
351 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE"] = EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE;
352 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_MEDIUMROOM"] = EFX_REVERB_PRESET_FACTORY_MEDIUMROOM;
353 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_LARGEROOM"] = EFX_REVERB_PRESET_FACTORY_LARGEROOM;
354 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_LONGPASSAGE"] = EFX_REVERB_PRESET_FACTORY_LONGPASSAGE;
355 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_HALL"] = EFX_REVERB_PRESET_FACTORY_HALL;
356 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_COURTYARD"] = EFX_REVERB_PRESET_FACTORY_COURTYARD;
357 m_efx_properties_map[
"EFX_REVERB_PRESET_FACTORY_ALCOVE"] = EFX_REVERB_PRESET_FACTORY_ALCOVE;
358 m_efx_properties_map[
"EFX_REVERB_PRESET_SPACESTATION_SMALLROOM"] = EFX_REVERB_PRESET_SPACESTATION_SMALLROOM;
359 m_efx_properties_map[
"EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE"] = EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE;
360 m_efx_properties_map[
"EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM"] = EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM;
361 m_efx_properties_map[
"EFX_REVERB_PRESET_SPACESTATION_LARGEROOM"] = EFX_REVERB_PRESET_SPACESTATION_LARGEROOM;
362 m_efx_properties_map[
"EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE"] = EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE;
363 m_efx_properties_map[
"EFX_REVERB_PRESET_SPACESTATION_HALL"] = EFX_REVERB_PRESET_SPACESTATION_HALL;
364 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_SMALLROOM"] = EFX_REVERB_PRESET_WOODEN_SMALLROOM;
365 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE"] = EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE;
366 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_MEDIUMROOM"] = EFX_REVERB_PRESET_WOODEN_MEDIUMROOM;
367 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_LARGEROOM"] = EFX_REVERB_PRESET_WOODEN_LARGEROOM;
368 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_LONGPASSAGE"] = EFX_REVERB_PRESET_WOODEN_LONGPASSAGE;
369 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_HALL"] = EFX_REVERB_PRESET_WOODEN_HALL;
370 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_COURTYARD"] = EFX_REVERB_PRESET_WOODEN_COURTYARD;
371 m_efx_properties_map[
"EFX_REVERB_PRESET_WOODEN_ALCOVE"] = EFX_REVERB_PRESET_WOODEN_ALCOVE;
372 m_efx_properties_map[
"EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM"] = EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM;
373 m_efx_properties_map[
"EFX_REVERB_PRESET_SPORT_FULLSTADIUM"] = EFX_REVERB_PRESET_SPORT_FULLSTADIUM;
374 m_efx_properties_map[
"EFX_REVERB_PRESET_SPORT_STADIUMTANNOY"] = EFX_REVERB_PRESET_SPORT_STADIUMTANNOY;
375 m_efx_properties_map[
"EFX_REVERB_PRESET_PREFAB_WORKSHOP"] = EFX_REVERB_PRESET_PREFAB_WORKSHOP;
376 m_efx_properties_map[
"EFX_REVERB_PRESET_PREFAB_OUTHOUSE"] = EFX_REVERB_PRESET_PREFAB_OUTHOUSE;
377 m_efx_properties_map[
"EFX_REVERB_PRESET_PREFAB_CARAVAN"] = EFX_REVERB_PRESET_PREFAB_CARAVAN;
378 m_efx_properties_map[
"EFX_REVERB_PRESET_PIPE_LARGE"] = EFX_REVERB_PRESET_PIPE_LARGE;
379 m_efx_properties_map[
"EFX_REVERB_PRESET_PIPE_LONGTHIN"] = EFX_REVERB_PRESET_PIPE_LONGTHIN;
380 m_efx_properties_map[
"EFX_REVERB_PRESET_PIPE_RESONANT"] = EFX_REVERB_PRESET_PIPE_RESONANT;
381 m_efx_properties_map[
"EFX_REVERB_PRESET_OUTDOORS_BACKYARD"] = EFX_REVERB_PRESET_OUTDOORS_BACKYARD;
382 m_efx_properties_map[
"EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS"] = EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS;
383 m_efx_properties_map[
"EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON"] = EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON;
384 m_efx_properties_map[
"EFX_REVERB_PRESET_OUTDOORS_CREEK"] = EFX_REVERB_PRESET_OUTDOORS_CREEK;
385 m_efx_properties_map[
"EFX_REVERB_PRESET_OUTDOORS_VALLEY"] = EFX_REVERB_PRESET_OUTDOORS_VALLEY;
386 m_efx_properties_map[
"EFX_REVERB_PRESET_MOOD_HEAVEN"] = EFX_REVERB_PRESET_MOOD_HEAVEN;
387 m_efx_properties_map[
"EFX_REVERB_PRESET_MOOD_HELL"] = EFX_REVERB_PRESET_MOOD_HELL;
388 m_efx_properties_map[
"EFX_REVERB_PRESET_MOOD_MEMORY"] = EFX_REVERB_PRESET_MOOD_MEMORY;
389 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_COMMENTATOR"] = EFX_REVERB_PRESET_DRIVING_COMMENTATOR;
390 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_PITGARAGE"] = EFX_REVERB_PRESET_DRIVING_PITGARAGE;
391 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_INCAR_RACER"] = EFX_REVERB_PRESET_DRIVING_INCAR_RACER;
392 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS"] = EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS;
393 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY"] = EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY;
394 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND"] = EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND;
395 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND"] = EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND;
396 m_efx_properties_map[
"EFX_REVERB_PRESET_DRIVING_TUNNEL"] = EFX_REVERB_PRESET_DRIVING_TUNNEL;
397 m_efx_properties_map[
"EFX_REVERB_PRESET_CITY_STREETS"] = EFX_REVERB_PRESET_CITY_STREETS;
398 m_efx_properties_map[
"EFX_REVERB_PRESET_CITY_SUBWAY"] = EFX_REVERB_PRESET_CITY_SUBWAY;
399 m_efx_properties_map[
"EFX_REVERB_PRESET_CITY_UNDERPASS"] = EFX_REVERB_PRESET_CITY_UNDERPASS;
400 m_efx_properties_map[
"EFX_REVERB_PRESET_CITY_ABANDONED"] = EFX_REVERB_PRESET_CITY_ABANDONED;
409 m_listener_is_underwater = (water !=
nullptr ? water->IsUnderWater(m_listener_position) :
false);
411 this->UpdateGlobalDopplerFactor();
412 this->recomputeAllSources();
413 this->UpdateAlListener();
414 this->UpdateListenerEnvironment();
415 this->UpdateEfxSpecificProperties(dt);
429 this->SetDopplerFactor(0);
440 for (
int hardware_index = 0; hardware_index < hardware_sources_num; ++hardware_index)
442 this->UpdateSourceSpecificDopplerFactor(hardware_index);
445 alSourcef(hardware_sources[hardware_index], AL_AIR_ABSORPTION_FACTOR, m_air_absorption_factor);
447 this->UpdateSourceFilters(hardware_index);
450 this->UpdateListenerEffectSlot(dt);
454 this->UpdateDirectedSounds();
460 const SoundPtr& corresponding_sound = audio_sources[hardware_sources_map[hardware_index]];
464 for (
const ActorPtr& actor : actors)
466 for (
int soundsource_index = 0; soundsource_index < actor->ar_num_soundsources; ++soundsource_index)
468 const soundsource_t& soundsource = actor->ar_soundsources[soundsource_index];
471 for (
int num_sound = 0; num_sound < num_sounds_of_ss; ++num_sound)
474 if (soundsource.
ssi->
getSound(num_sound) == corresponding_sound)
477 || !actor->ar_physics_paused)
479 this->SetDopplerFactor(hardware_sources[hardware_index], 1.0f);
482 this->SetDopplerFactor(hardware_sources[hardware_index], 0.0f);
494 m_listener_position = position;
495 m_listener_direction = direction;
497 m_listener_velocity = velocity;
507 const EFXEAXREVERBPROPERTIES* listener_reverb_properties =
nullptr;
511 if (this->ListenerIsUnderwater())
513 this->SetSpeedOfSound(1522.0f);
519 this->SetAirAbsorptionFactor(0.00668f);
523 this->SetSpeedOfSound(343.3f);
524 this->SetAirAbsorptionFactor(1.0f);
529 m_listener_efx_reverb_properties = this->GetReverbPresetAt(m_listener_position);
536 float orientation[6];
538 orientation[0] = m_listener_direction.x;
539 orientation[1] = m_listener_direction.y;
540 orientation[2] = m_listener_direction.z;
542 orientation[3] = m_listener_up.x;
543 orientation[4] = m_listener_up.y;
544 orientation[5] = m_listener_up.z;
546 alListener3f(AL_POSITION, m_listener_position.x, m_listener_position.y, m_listener_position.z);
547 alListener3f(AL_VELOCITY, m_listener_velocity.x, m_listener_velocity.y, m_listener_velocity.z);
548 alListenerfv(AL_ORIENTATION, orientation);
554 if (position == m_listener_position)
563 bool position_is_underwater = (water !=
nullptr ? water->IsUnderWater(position) :
false);
564 if (position_is_underwater)
566 return this->GetEfxProperties(
"EFX_REVERB_PRESET_UNDERWATER");
572 if (!collision_box.reverb_preset_name.empty())
574 const Ogre::AxisAlignedBox collision_box_aab = Ogre::AxisAlignedBox(collision_box.lo, collision_box.hi);
576 if (collision_box_aab.contains(position))
578 return this->GetEfxProperties(collision_box.reverb_preset_name);
595 if (m_listener_efx_reverb_properties ==
nullptr)
597 this->SmoothlyUpdateAlAuxiliaryEffectSlot(dt, m_listener_slot,
nullptr);
601 EFXEAXREVERBPROPERTIES current_environmental_properties = *m_listener_efx_reverb_properties;
606 std::tuple<Ogre::Vector3, float, float> target_early_reflections_properties = this->ComputeEarlyReflectionsProperties();
609 current_environmental_properties.flReflectionsPan[0] = std::get<0>(target_early_reflections_properties).x;
610 current_environmental_properties.flReflectionsPan[1] = 0;
611 current_environmental_properties.flReflectionsPan[2] = -std::get<0>(target_early_reflections_properties).z;
613 current_environmental_properties.flReflectionsGain = std::get<1>(target_early_reflections_properties);
614 current_environmental_properties.flReflectionsDelay = std::get<2>(target_early_reflections_properties);
617 this->SmoothlyUpdateAlAuxiliaryEffectSlot(dt, m_listener_slot, ¤t_environmental_properties);
622 const float time_to_target = 0.333f;
624 const float step = std::min(dt / time_to_target, 0.5f);
625 static std::map<ALuint, EFXEAXREVERBPROPERTIES> current_efx_properties_of_slot;
627 if (target_efx_properties ==
nullptr)
629 this->alAuxiliaryEffectSloti(slot_id, AL_EFFECTSLOT_EFFECT, AL_EFFECTSLOT_NULL);
633 const auto it = current_efx_properties_of_slot.find(slot_id);
634 if (it == current_efx_properties_of_slot.end())
637 current_efx_properties_of_slot[slot_id] = *target_efx_properties;
640 ALuint efx_effect_id;
642 if (m_efx_effect_id_map.find(slot_id) == m_efx_effect_id_map.end())
644 efx_effect_id = this->CreateAlEffect(target_efx_properties);
645 m_efx_effect_id_map[slot_id] = efx_effect_id;
649 efx_effect_id = m_efx_effect_id_map.find(slot_id)->second;
653 current_efx_properties_of_slot[slot_id] =
655 current_efx_properties_of_slot[slot_id].flDensity + step * (target_efx_properties->flDensity - current_efx_properties_of_slot[slot_id].flDensity),
656 current_efx_properties_of_slot[slot_id].flDiffusion + step * (target_efx_properties->flDiffusion - current_efx_properties_of_slot[slot_id].flDiffusion),
657 current_efx_properties_of_slot[slot_id].flGain + step * (target_efx_properties->flGain - current_efx_properties_of_slot[slot_id].flGain),
658 current_efx_properties_of_slot[slot_id].flGainHF + step * (target_efx_properties->flGainHF - current_efx_properties_of_slot[slot_id].flGainHF),
659 current_efx_properties_of_slot[slot_id].flGainLF + step * (target_efx_properties->flGainLF - current_efx_properties_of_slot[slot_id].flGainLF),
660 current_efx_properties_of_slot[slot_id].flDecayTime + step * (target_efx_properties->flDecayTime - current_efx_properties_of_slot[slot_id].flDecayTime),
661 current_efx_properties_of_slot[slot_id].flDecayHFRatio + step * (target_efx_properties->flDecayHFRatio - current_efx_properties_of_slot[slot_id].flDecayHFRatio),
662 current_efx_properties_of_slot[slot_id].flDecayLFRatio + step * (target_efx_properties->flDecayLFRatio - current_efx_properties_of_slot[slot_id].flDecayLFRatio),
663 current_efx_properties_of_slot[slot_id].flReflectionsGain + step * (target_efx_properties->flReflectionsGain - current_efx_properties_of_slot[slot_id].flReflectionsGain),
664 current_efx_properties_of_slot[slot_id].flReflectionsDelay + step * (target_efx_properties->flReflectionsDelay - current_efx_properties_of_slot[slot_id].flReflectionsDelay),
665 current_efx_properties_of_slot[slot_id].flReflectionsPan[0] + step * (target_efx_properties->flReflectionsPan[0] - current_efx_properties_of_slot[slot_id].flReflectionsPan[0]),
666 current_efx_properties_of_slot[slot_id].flReflectionsPan[1] + step * (target_efx_properties->flReflectionsPan[1] - current_efx_properties_of_slot[slot_id].flReflectionsPan[1]),
667 current_efx_properties_of_slot[slot_id].flReflectionsPan[2] + step * (target_efx_properties->flReflectionsPan[2] - current_efx_properties_of_slot[slot_id].flReflectionsPan[2]),
668 current_efx_properties_of_slot[slot_id].flLateReverbGain + step * (target_efx_properties->flLateReverbGain - current_efx_properties_of_slot[slot_id].flLateReverbGain),
669 current_efx_properties_of_slot[slot_id].flLateReverbDelay + step * (target_efx_properties->flLateReverbDelay - current_efx_properties_of_slot[slot_id].flLateReverbDelay),
670 current_efx_properties_of_slot[slot_id].flLateReverbPan[0] + step * (target_efx_properties->flLateReverbPan[0] - current_efx_properties_of_slot[slot_id].flLateReverbPan[0]),
671 current_efx_properties_of_slot[slot_id].flLateReverbPan[1] + step * (target_efx_properties->flLateReverbPan[1] - current_efx_properties_of_slot[slot_id].flLateReverbPan[1]),
672 current_efx_properties_of_slot[slot_id].flLateReverbPan[2] + step * (target_efx_properties->flLateReverbPan[2] - current_efx_properties_of_slot[slot_id].flLateReverbPan[2]),
673 current_efx_properties_of_slot[slot_id].flEchoTime + step * (target_efx_properties->flEchoTime - current_efx_properties_of_slot[slot_id].flEchoTime),
674 current_efx_properties_of_slot[slot_id].flEchoDepth + step * (target_efx_properties->flEchoDepth - current_efx_properties_of_slot[slot_id].flEchoDepth),
675 current_efx_properties_of_slot[slot_id].flModulationTime + step * (target_efx_properties->flModulationTime - current_efx_properties_of_slot[slot_id].flModulationTime),
676 current_efx_properties_of_slot[slot_id].flModulationDepth + step * (target_efx_properties->flModulationDepth - current_efx_properties_of_slot[slot_id].flModulationDepth),
677 current_efx_properties_of_slot[slot_id].flAirAbsorptionGainHF + step * (target_efx_properties->flAirAbsorptionGainHF - current_efx_properties_of_slot[slot_id].flAirAbsorptionGainHF),
678 current_efx_properties_of_slot[slot_id].flHFReference + step * (target_efx_properties->flHFReference - current_efx_properties_of_slot[slot_id].flHFReference),
679 current_efx_properties_of_slot[slot_id].flLFReference + step * (target_efx_properties->flLFReference - current_efx_properties_of_slot[slot_id].flLFReference),
680 current_efx_properties_of_slot[slot_id].flRoomRolloffFactor + step * (target_efx_properties->flRoomRolloffFactor - current_efx_properties_of_slot[slot_id].flRoomRolloffFactor),
681 static_cast<int>(std::round(current_efx_properties_of_slot[slot_id].iDecayHFLimit + step * (target_efx_properties->iDecayHFLimit - current_efx_properties_of_slot[slot_id].iDecayHFLimit))),
685 switch (m_efx_reverb_engine)
688 this->alEffectf( efx_effect_id, AL_EAXREVERB_DENSITY, current_efx_properties_of_slot[slot_id].flDensity);
689 this->alEffectf( efx_effect_id, AL_EAXREVERB_DIFFUSION, current_efx_properties_of_slot[slot_id].flDiffusion);
690 this->alEffectf( efx_effect_id, AL_EAXREVERB_GAIN, current_efx_properties_of_slot[slot_id].flGain);
691 this->alEffectf( efx_effect_id, AL_EAXREVERB_GAINHF, current_efx_properties_of_slot[slot_id].flGainHF);
692 this->alEffectf( efx_effect_id, AL_EAXREVERB_GAINLF, current_efx_properties_of_slot[slot_id].flGainLF);
693 this->alEffectf( efx_effect_id, AL_EAXREVERB_DECAY_TIME, current_efx_properties_of_slot[slot_id].flDecayTime);
694 this->alEffectf( efx_effect_id, AL_EAXREVERB_DECAY_HFRATIO, current_efx_properties_of_slot[slot_id].flDecayHFRatio);
695 this->alEffectf( efx_effect_id, AL_EAXREVERB_DECAY_LFRATIO, current_efx_properties_of_slot[slot_id].flDecayLFRatio);
696 this->alEffectf( efx_effect_id, AL_EAXREVERB_REFLECTIONS_GAIN, current_efx_properties_of_slot[slot_id].flReflectionsGain);
697 this->alEffectf( efx_effect_id, AL_EAXREVERB_REFLECTIONS_DELAY, current_efx_properties_of_slot[slot_id].flReflectionsDelay);
698 this->alEffectfv(efx_effect_id, AL_EAXREVERB_REFLECTIONS_PAN, current_efx_properties_of_slot[slot_id].flReflectionsPan);
699 this->alEffectf( efx_effect_id, AL_EAXREVERB_LATE_REVERB_GAIN, current_efx_properties_of_slot[slot_id].flLateReverbGain);
700 this->alEffectf( efx_effect_id, AL_EAXREVERB_LATE_REVERB_DELAY, current_efx_properties_of_slot[slot_id].flLateReverbDelay);
701 this->alEffectfv(efx_effect_id, AL_EAXREVERB_LATE_REVERB_PAN, current_efx_properties_of_slot[slot_id].flLateReverbPan);
702 this->alEffectf( efx_effect_id, AL_EAXREVERB_ECHO_TIME, current_efx_properties_of_slot[slot_id].flEchoTime);
703 this->alEffectf( efx_effect_id, AL_EAXREVERB_ECHO_DEPTH, current_efx_properties_of_slot[slot_id].flEchoDepth);
704 this->alEffectf( efx_effect_id, AL_EAXREVERB_MODULATION_TIME, current_efx_properties_of_slot[slot_id].flModulationTime);
705 this->alEffectf( efx_effect_id, AL_EAXREVERB_MODULATION_DEPTH, current_efx_properties_of_slot[slot_id].flModulationDepth);
706 this->alEffectf( efx_effect_id, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, current_efx_properties_of_slot[slot_id].flAirAbsorptionGainHF);
707 this->alEffectf( efx_effect_id, AL_EAXREVERB_HFREFERENCE, current_efx_properties_of_slot[slot_id].flHFReference);
708 this->alEffectf( efx_effect_id, AL_EAXREVERB_LFREFERENCE, current_efx_properties_of_slot[slot_id].flLFReference);
709 this->alEffectf( efx_effect_id, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, current_efx_properties_of_slot[slot_id].flRoomRolloffFactor);
710 this->alEffecti( efx_effect_id, AL_EAXREVERB_DECAY_HFLIMIT, current_efx_properties_of_slot[slot_id].iDecayHFLimit);
714 this->alEffectf( efx_effect_id, AL_REVERB_DENSITY, current_efx_properties_of_slot[slot_id].flDensity);
715 this->alEffectf( efx_effect_id, AL_REVERB_DIFFUSION, current_efx_properties_of_slot[slot_id].flDiffusion);
716 this->alEffectf( efx_effect_id, AL_REVERB_GAIN, current_efx_properties_of_slot[slot_id].flGain);
717 this->alEffectf( efx_effect_id, AL_REVERB_GAINHF, current_efx_properties_of_slot[slot_id].flGainHF);
718 this->alEffectf( efx_effect_id, AL_REVERB_DECAY_TIME, current_efx_properties_of_slot[slot_id].flDecayTime);
719 this->alEffectf( efx_effect_id, AL_REVERB_DECAY_HFRATIO, current_efx_properties_of_slot[slot_id].flDecayHFRatio);
720 this->alEffectf( efx_effect_id, AL_REVERB_REFLECTIONS_GAIN, current_efx_properties_of_slot[slot_id].flReflectionsGain);
721 this->alEffectf( efx_effect_id, AL_REVERB_REFLECTIONS_DELAY, current_efx_properties_of_slot[slot_id].flReflectionsDelay);
722 this->alEffectf( efx_effect_id, AL_REVERB_LATE_REVERB_GAIN, current_efx_properties_of_slot[slot_id].flLateReverbGain);
723 this->alEffectf( efx_effect_id, AL_REVERB_LATE_REVERB_DELAY, current_efx_properties_of_slot[slot_id].flLateReverbDelay);
724 this->alEffectf( efx_effect_id, AL_REVERB_AIR_ABSORPTION_GAINHF, current_efx_properties_of_slot[slot_id].flAirAbsorptionGainHF);
725 this->alEffectf( efx_effect_id, AL_REVERB_ROOM_ROLLOFF_FACTOR, current_efx_properties_of_slot[slot_id].flRoomRolloffFactor);
726 this->alEffectf( efx_effect_id, AL_REVERB_DECAY_HFLIMIT, current_efx_properties_of_slot[slot_id].iDecayHFLimit);
730 this->alAuxiliaryEffectSloti(slot_id, AL_EFFECTSLOT_EFFECT, AL_EFFECTSLOT_NULL);
735 this->alAuxiliaryEffectSloti(slot_id, AL_EFFECTSLOT_EFFECT, efx_effect_id);
740 const float max_distance = 2.0f;
741 const float reflections_gain_boost_max = 2.0f;
742 float early_reflections_gain;
743 float early_reflections_delay;
745 Ogre::Vector3 early_reflections_pan = { 0.0f, 0.0f, 0.0f};
752 bool nearby_surface_detected =
false;
753 const float angle_step_size = 90;
754 float closest_surface_distance = std::numeric_limits<float>::max();
756 for (
float angle = 0; angle < 360; angle += angle_step_size)
758 float closest_surface_distance_in_this_direction = std::numeric_limits<float>::max();
759 Ogre::Vector3 raycast_direction = Quaternion(Ogre::Degree(angle), m_listener_up) * m_listener_direction;
760 raycast_direction.normalise();
764 Ray ray = Ray(m_listener_position, raycast_direction * max_distance *
App::GetGameContext()->GetTerrain()->GetCollisions()->GetCellSize());
767 if (intersection.first)
769 closest_surface_distance_in_this_direction = intersection.second * max_distance;
772 ray.setDirection(ray.getDirection().normalisedCopy());
777 if (!collision_box.enabled || collision_box.virt) {
continue; }
778 intersection = ray.intersects(Ogre::AxisAlignedBox(collision_box.lo, collision_box.hi));
779 if (intersection.first && intersection.second <= max_distance)
781 closest_surface_distance_in_this_direction = std::min(closest_surface_distance_in_this_direction, intersection.second);
787 for (
const ActorPtr& actor : actors)
790 if (actor ==
App::GetGameContext()->GetPlayerCharacter()->GetActorCoupling()) {
continue; }
792 intersection = ray.intersects(actor->ar_bounding_box);
793 if (intersection.first && intersection.second <= max_distance)
795 closest_surface_distance_in_this_direction = std::min(closest_surface_distance_in_this_direction, intersection.second);
799 closest_surface_distance = std::min(closest_surface_distance, closest_surface_distance_in_this_direction);
801 if (closest_surface_distance_in_this_direction <= max_distance)
803 early_reflections_pan += raycast_direction * (max_distance - closest_surface_distance_in_this_direction);
807 nearby_surface_detected = closest_surface_distance <= max_distance;
811 if (!nearby_surface_detected)
814 early_reflections_delay = m_listener_efx_reverb_properties->flReflectionsDelay;
815 early_reflections_gain = m_listener_efx_reverb_properties->flReflectionsGain;
820 magnitude = 1.0f - early_reflections_pan.length() / Ogre::Math::Sqrt(2.0f * Ogre::Math::Pow(max_distance, 2));
823 early_reflections_delay = closest_surface_distance / this->GetSpeedOfSound();
825 early_reflections_gain = std::min(
826 (m_listener_efx_reverb_properties->flReflectionsGain
827 + reflections_gain_boost_max
828 - (reflections_gain_boost_max * (magnitude))),
829 AL_EAXREVERB_MAX_REFLECTIONS_GAIN);
836 Ogre::Quaternion horizontal_rotation;
837 if (m_listener_direction.z > 0.0f)
839 horizontal_rotation = Quaternion(Ogre::Degree(180), m_listener_up) * m_listener_direction.getRotationTo(Ogre::Vector3::UNIT_Z);
843 horizontal_rotation = m_listener_direction.getRotationTo(Ogre::Vector3::NEGATIVE_UNIT_Z);
846 early_reflections_pan = horizontal_rotation * early_reflections_pan;
847 early_reflections_pan.normalise();
849 early_reflections_pan = magnitude * early_reflections_pan;
851 return std::make_tuple(early_reflections_pan, early_reflections_gain, early_reflections_delay);
859 this->alGenEffects(1, &effect);
861 switch (m_efx_reverb_engine)
864 this->alEffecti( effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
866 this->alEffectf( effect, AL_EAXREVERB_DENSITY, efx_properties->flDensity);
867 this->alEffectf( effect, AL_EAXREVERB_DIFFUSION, efx_properties->flDiffusion);
868 this->alEffectf( effect, AL_EAXREVERB_GAIN, efx_properties->flGain);
869 this->alEffectf( effect, AL_EAXREVERB_GAINHF, efx_properties->flGainHF);
870 this->alEffectf( effect, AL_EAXREVERB_GAINLF, efx_properties->flGainLF);
871 this->alEffectf( effect, AL_EAXREVERB_DECAY_TIME, efx_properties->flDecayTime);
872 this->alEffectf( effect, AL_EAXREVERB_DECAY_HFRATIO, efx_properties->flDecayHFRatio);
873 this->alEffectf( effect, AL_EAXREVERB_DECAY_LFRATIO, efx_properties->flDecayLFRatio);
874 this->alEffectf( effect, AL_EAXREVERB_REFLECTIONS_GAIN, efx_properties->flReflectionsGain);
875 this->alEffectf( effect, AL_EAXREVERB_REFLECTIONS_DELAY, efx_properties->flReflectionsDelay);
876 this->alEffectfv(effect, AL_EAXREVERB_REFLECTIONS_PAN, efx_properties->flReflectionsPan);
877 this->alEffectf( effect, AL_EAXREVERB_LATE_REVERB_GAIN, efx_properties->flLateReverbGain);
878 this->alEffectf( effect, AL_EAXREVERB_LATE_REVERB_DELAY, efx_properties->flLateReverbDelay);
879 this->alEffectfv(effect, AL_EAXREVERB_LATE_REVERB_PAN, efx_properties->flLateReverbPan);
880 this->alEffectf( effect, AL_EAXREVERB_ECHO_TIME, efx_properties->flEchoTime);
881 this->alEffectf( effect, AL_EAXREVERB_ECHO_DEPTH, efx_properties->flEchoDepth);
882 this->alEffectf( effect, AL_EAXREVERB_MODULATION_TIME, efx_properties->flModulationTime);
883 this->alEffectf( effect, AL_EAXREVERB_MODULATION_DEPTH, efx_properties->flModulationDepth);
884 this->alEffectf( effect, AL_EAXREVERB_AIR_ABSORPTION_GAINHF, efx_properties->flAirAbsorptionGainHF);
885 this->alEffectf( effect, AL_EAXREVERB_HFREFERENCE, efx_properties->flHFReference);
886 this->alEffectf( effect, AL_EAXREVERB_LFREFERENCE, efx_properties->flLFReference);
887 this->alEffectf( effect, AL_EAXREVERB_ROOM_ROLLOFF_FACTOR, efx_properties->flRoomRolloffFactor);
888 this->alEffecti( effect, AL_EAXREVERB_DECAY_HFLIMIT, efx_properties->iDecayHFLimit);
892 this->alEffecti(effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
894 this->alEffectf(effect, AL_REVERB_DENSITY, efx_properties->flDensity);
895 this->alEffectf(effect, AL_REVERB_DIFFUSION, efx_properties->flDiffusion);
896 this->alEffectf(effect, AL_REVERB_GAIN, efx_properties->flGain);
897 this->alEffectf(effect, AL_REVERB_GAINHF, efx_properties->flGainHF);
898 this->alEffectf(effect, AL_REVERB_DECAY_TIME, efx_properties->flDecayTime);
899 this->alEffectf(effect, AL_REVERB_DECAY_HFRATIO, efx_properties->flDecayHFRatio);
900 this->alEffectf(effect, AL_REVERB_REFLECTIONS_GAIN, efx_properties->flReflectionsGain);
901 this->alEffectf(effect, AL_REVERB_REFLECTIONS_DELAY, efx_properties->flReflectionsDelay);
902 this->alEffectf(effect, AL_REVERB_LATE_REVERB_GAIN, efx_properties->flLateReverbGain);
903 this->alEffectf(effect, AL_REVERB_LATE_REVERB_DELAY, efx_properties->flLateReverbDelay);
904 this->alEffectf(effect, AL_REVERB_AIR_ABSORPTION_GAINHF, efx_properties->flAirAbsorptionGainHF);
905 this->alEffectf(effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, efx_properties->flRoomRolloffFactor);
906 this->alEffecti(effect, AL_REVERB_DECAY_HFLIMIT, efx_properties->iDecayHFLimit);
911 LOG(
"SoundManager: No usable reverb engine set, not creating reverb effect");
914 error = alGetError();
915 if (error != AL_NO_ERROR)
917 LOG(
"SoundManager: Could not create EFX effect:" +
TOSTRING(alGetString(error)));
919 if (this->alIsEffect(effect))
920 this->alDeleteEffects(1, &effect);
932 this->alDeleteEffects(1, &efx_effect_id);
934 error = alGetError();
935 if (error != AL_NO_ERROR)
937 LOG(
"SoundManager: Could not delete EFX effect: " +
TOSTRING(alGetString(error)));
943 return a.second > b.second;
951 if (!audio_device)
return;
953 for (
int i=0; i < m_audio_sources_in_use_count; i++)
955 audio_sources[i]->computeAudibility(m_listener_position);
956 audio_sources_most_audible[i].first = i;
957 audio_sources_most_audible[i].second = audio_sources[i]->audibility;
961 if ((m_audio_sources_in_use_count - 1) > hardware_sources_num)
963 std::nth_element(audio_sources_most_audible, audio_sources_most_audible+hardware_sources_num, audio_sources_most_audible + m_audio_sources_in_use_count - 1,
compareByAudibility);
966 for (
int i=0; i < m_audio_sources_in_use_count; i++)
968 if (audio_sources[audio_sources_most_audible[i].first]->hardware_index != -1 && (i >= hardware_sources_num || audio_sources_most_audible[i].second == 0))
969 retire(audio_sources_most_audible[i].first);
972 for (
int i=0; i < std::min(m_audio_sources_in_use_count, hardware_sources_num); i++)
974 if (audio_sources[audio_sources_most_audible[i].first]->hardware_index == -1 && audio_sources_most_audible[i].second > 0)
976 for (
int j=0; j < hardware_sources_num; j++)
978 if (hardware_sources_map[j] == -1)
980 assign(audio_sources_most_audible[i].first, j);
991 bool source_is_obstructed = this->IsHardwareSourceObstructed(hardware_index);
993 this->UpdateObstructionFilter(hardware_index, source_is_obstructed);
1001 if (source_is_obstructed)
1003 this->UpdateOcclusionFilter(hardware_index, m_listener_slot, m_listener_efx_reverb_properties);
1008 alSource3i(hardware_sources[hardware_index], AL_AUXILIARY_SEND_FILTER, m_listener_slot, m_efx_occlusion_wet_path_send_id, AL_FILTER_NULL);
1014 if ( hardware_sources_map[hardware_index] == -1
1026 &&
App::GetGameContext()->GetPlayerCharacter()->GetActorCoupling()->ar_bounding_box.contains(m_listener_position)
1037 std::pair<bool, Ogre::Real> intersection;
1038 const SoundPtr& corresponding_sound = audio_sources[hardware_sources_map[hardware_index]];
1039 const Ogre::Vector3 direction_to_sound = corresponding_sound->
getPosition() - m_listener_position;
1040 const Ogre::Ray direct_path_to_sound = Ray(m_listener_position, direction_to_sound);
1041 bool obstruction_detected =
false;
1047 obstruction_detected = intersection.first;
1049 if (!obstruction_detected)
1054 if (!collision_box.enabled || collision_box.virt) {
continue; }
1056 Ogre::AxisAlignedBox collision_box_aab = Ogre::AxisAlignedBox(collision_box.lo, collision_box.hi);
1059 if ( collision_box_aab.contains(corresponding_sound->
getPosition())
1060 || collision_box_aab.distance(corresponding_sound->
getPosition()) < 0.1f)
1065 intersection = direct_path_to_sound.intersects(collision_box_aab);
1066 obstruction_detected = intersection.first && intersection.second <= 1.0f;
1067 if (obstruction_detected)
1074 if (!obstruction_detected)
1078 bool soundsource_belongs_to_current_actor =
false;
1079 for (
const ActorPtr& actor : actors)
1083 for (
int soundsource_index = 0; soundsource_index < actor->ar_num_soundsources; ++soundsource_index)
1085 const soundsource_t& soundsource = actor->ar_soundsources[soundsource_index];
1087 for (
int num_sound = 0; num_sound < num_sounds; ++num_sound)
1089 if (soundsource.
ssi->
getSound(num_sound) == corresponding_sound)
1091 soundsource_belongs_to_current_actor =
true;
1094 if (soundsource_belongs_to_current_actor) {
break; }
1097 if (soundsource_belongs_to_current_actor)
1102 intersection = direct_path_to_sound.intersects(actor->ar_bounding_box);
1103 obstruction_detected = intersection.first && intersection.second <= 1.0f;
1104 if (obstruction_detected)
1111 if (!obstruction_detected)
1115 obstruction_detected = intersection.first;
1118 return obstruction_detected;
1126 alSourcei(hardware_sources[hardware_index], AL_DIRECT_FILTER, AL_FILTER_NULL);
1130 alSourcei(hardware_sources[hardware_index], AL_DIRECT_FILTER, m_efx_outdoor_obstruction_lowpass_filter_id);
1136 if (hardware_sources_map[hardware_index] == -1) {
return false; }
1141 alSource3i(hardware_sources[hardware_index], AL_AUXILIARY_SEND_FILTER, effect_slot_id, m_efx_occlusion_wet_path_send_id, AL_FILTER_NULL);
1145 const SoundPtr& corresponding_sound = audio_sources[hardware_sources_map[hardware_index]];
1146 bool occlusion_detected = this->GetReverbPresetAt(corresponding_sound->
getPosition()) != reference_efx_reverb_properties;
1148 if (occlusion_detected)
1150 alSource3i(hardware_sources[hardware_index], AL_AUXILIARY_SEND_FILTER, effect_slot_id, m_efx_occlusion_wet_path_send_id, m_efx_occlusion_wet_path_lowpass_filter_id);
1154 alSource3i(hardware_sources[hardware_index], AL_AUXILIARY_SEND_FILTER, effect_slot_id, m_efx_occlusion_wet_path_send_id, AL_FILTER_NULL);
1157 return occlusion_detected;
1162 for (
int hardware_index = 0; hardware_index < hardware_sources_num; hardware_index++)
1164 if (hardware_sources_map[hardware_index] == -1) {
continue;; }
1166 const SoundPtr& corresponding_sound = audio_sources[hardware_sources_map[hardware_index]];
1169 for (
const ActorPtr& actor : actors)
1174 for (
int soundsource_index = 0; soundsource_index < actor->ar_num_soundsources; ++soundsource_index)
1176 const soundsource_t& soundsource = actor->ar_soundsources[soundsource_index];
1178 for (
int num_sound = 0; num_sound < num_sounds; ++num_sound)
1180 if (soundsource.
ssi->
getSound(num_sound) == corresponding_sound)
1182 sound_node = soundsource.
nodenum;
1195 const std::vector<Exhaust>& exhausts = actor->GetGfxActor()->getExhausts();
1196 for (
const Exhaust& exhaust : exhausts)
1198 if ( sound_node == exhaust.emitterNode
1199 || sound_node == exhaust.directionNode)
1201 const Ogre::Vector3 emitter_node_pos = actor->getNodePosition(exhaust.emitterNode);
1202 const Ogre::Vector3 direction_node_pos = actor->getNodePosition(exhaust.directionNode);
1204 this->UpdateConeProperties(
1205 hardware_sources[hardware_index],
1206 emitter_node_pos - direction_node_pos,
1216 switch(actor->getTruckType())
1220 for (
int engine_num = 0; engine_num < actor->ar_num_aeroengines; ++engine_num)
1222 const auto& aero_engine = actor->ar_aeroengines[engine_num];
1224 switch(aero_engine->getType())
1227 if ( sound_node == aero_engine->getNoderef()
1228 || sound_node == aero_engine->GetBackNode())
1230 const Ogre::Vector3 aero_engine_ref_node = actor->getNodePosition(aero_engine->getNoderef());
1231 const Ogre::Vector3 aero_engine_back_node = actor->getNodePosition(aero_engine->GetBackNode());
1233 this->UpdateConeProperties(
1234 hardware_sources[hardware_index],
1235 aero_engine_ref_node - aero_engine_back_node,
1253 if ( sound_node == aero_engine->getNoderef()
1254 || sound_node == aero_engine->GetFrontNode())
1256 const Ogre::Vector3 aero_engine_ref_node = actor->getNodePosition(aero_engine->getNoderef());
1257 const Ogre::Vector3 aero_engine_front_node = actor->getNodePosition(aero_engine->GetFrontNode());
1259 this->UpdateConeProperties(
1260 hardware_sources[hardware_index],
1261 aero_engine_ref_node - aero_engine_front_node,
1277 for (
int screwprop_num = 0; screwprop_num < actor->ar_num_screwprops; ++screwprop_num)
1279 const auto& screwprop = actor->ar_screwprops[screwprop_num];
1281 if ( sound_node == screwprop->GetRefNode()
1282 || sound_node == screwprop->GetBackNode())
1284 const Ogre::Vector3 screwprop_ref_node = actor->getNodePosition(screwprop->GetRefNode());
1285 const Ogre::Vector3 screwprop_back_node = actor->getNodePosition(screwprop->GetBackNode());
1287 this->UpdateConeProperties(
1288 hardware_sources[hardware_index],
1289 screwprop_ref_node - screwprop_back_node,
1307 const ALuint source,
1308 const Ogre::Vector3& cone_direction,
1309 const float cone_inner_angle,
1310 const float cone_outer_angle,
1311 const float cone_outer_gain,
1312 const float cone_outer_gain_hf
1315 alSource3f(source, AL_DIRECTION, cone_direction.x, cone_direction.y, cone_direction.z);
1317 alSourcef (source, AL_CONE_INNER_ANGLE, cone_inner_angle);
1318 alSourcef (source, AL_CONE_OUTER_ANGLE, cone_outer_angle);
1319 alSourcef (source, AL_CONE_OUTER_GAIN, cone_outer_gain);
1323 alSourcef(source, AL_CONE_OUTER_GAINHF, cone_outer_gain_hf);
1331 audio_sources[source_index]->computeAudibility(m_listener_position);
1333 if (audio_sources[source_index]->audibility == 0.0f)
1335 if (audio_sources[source_index]->hardware_index != -1)
1338 retire(source_index);
1344 if (audio_sources[source_index]->hardware_index != -1)
1346 ALuint hw_source = hardware_sources[audio_sources[source_index]->hardware_index];
1352 this->UpdateSourceFilters(audio_sources[source_index]->hardware_index);
1353 alSourcePlay(hw_source);
1359 case Sound::REASON_LOOP: alSourcei(hw_source, AL_LOOPING, (vfl > 0.5) ? AL_TRUE : AL_FALSE);
1363 case Sound::REASON_POSN: alSource3f(hw_source, AL_POSITION, vvec->x, vvec->y, vvec->z);
1365 case Sound::REASON_VLCT: alSource3f(hw_source, AL_VELOCITY, vvec->x, vvec->y, vvec->z);
1374 if (hardware_sources_in_use_count < hardware_sources_num)
1376 for (
int i = 0; i < hardware_sources_num; i++)
1378 if (hardware_sources_map[i] == -1)
1380 assign(source_index, i);
1390 int al_faintest = 0;
1391 for (
int i = 0; i < hardware_sources_num; i++)
1393 if (hardware_sources_map[i] >= 0 && audio_sources[hardware_sources_map[i]]->audibility < fv)
1395 fv = audio_sources[hardware_sources_map[i]]->audibility;
1400 if (fv < audio_sources[source_index]->audibility)
1403 retire(hardware_sources_map[al_faintest]);
1404 assign(source_index, al_faintest);
1416 audio_sources[source_index]->hardware_index = hardware_index;
1417 hardware_sources_map[hardware_index] = source_index;
1419 ALuint hw_source = hardware_sources[hardware_index];
1420 SoundPtr& audio_source = audio_sources[source_index];
1423 alSourcei(hw_source, AL_BUFFER, audio_source->
buffer);
1425 alSourcei(hw_source, AL_LOOPING, (audio_source->
loop) ? AL_TRUE : AL_FALSE);
1426 alSourcef(hw_source, AL_PITCH, audio_source->
pitch);
1432 this->UpdateSourceFilters(audio_sources[source_index]->hardware_index);
1433 alSourcePlay(hw_source);
1436 hardware_sources_in_use_count++;
1443 if (audio_sources[source_index]->hardware_index == -1)
1445 alSourceStop(hardware_sources[audio_sources[source_index]->hardware_index]);
1446 hardware_sources_map[audio_sources[source_index]->hardware_index] = -1;
1447 audio_sources[source_index]->hardware_index = -1;
1448 hardware_sources_in_use_count--;
1456 alListenerf(AL_GAIN, 0.0f);
1473 alListenerf(AL_GAIN, v);
1481 if (audio_buffers_in_use_count >= MAX_AUDIO_BUFFERS)
1483 LOG(
"SoundManager: Reached MAX_AUDIO_BUFFERS limit (" +
TOSTRING(MAX_AUDIO_BUFFERS) +
")");
1490 for (
int i = 0; i < audio_buffers_in_use_count; i++)
1492 if (filename == audio_buffer_file_name[i])
1494 buffer = audio_buffers[i];
1502 alGenBuffers(1, &audio_buffers[audio_buffers_in_use_count]);
1503 if (loadWAVFile(filename, audio_buffers[audio_buffers_in_use_count], resource_group_name))
1506 alDeleteBuffers(1, &audio_buffers[audio_buffers_in_use_count]);
1507 audio_buffer_file_name[audio_buffers_in_use_count] =
"";
1510 buffer = audio_buffers[audio_buffers_in_use_count];
1511 audio_buffer_file_name[audio_buffers_in_use_count] = filename;
1512 audio_buffers_in_use_count++;
1515 audio_sources[m_audio_sources_in_use_count] =
new Sound(buffer,
this, m_audio_sources_in_use_count);
1517 return audio_sources[m_audio_sources_in_use_count++];
1524 LOG(
"Loading WAV file "+filename);
1527 ResourceGroupManager* rgm = ResourceGroupManager::getSingletonPtr();
1528 if (resource_group_name ==
"")
1530 resource_group_name = rgm->findGroupContainingResource(filename);
1532 DataStreamPtr stream = rgm->openResource(filename, resource_group_name);
1538 unsigned short sbuf;
1541 if (stream->read(magic, 4) != 4)
1543 LOG(
"Could not read file "+filename);
1546 if (String(magic) != String(
"RIFF"))
1548 LOG(
"Invalid WAV file (no RIFF): "+filename);
1554 if (stream->read(magic, 4) != 4)
1556 LOG(
"Could not read file "+filename);
1559 if (String(magic) != String(
"WAVE"))
1561 LOG(
"Invalid WAV file (no WAVE): "+filename);
1565 if (stream->read(magic, 4) != 4)
1567 LOG(
"Could not read file "+filename);
1570 if (String(magic) != String(
"fmt "))
1572 LOG(
"Invalid WAV file (no fmt): "+filename);
1576 if (stream->read(&lbuf, 4) != 4)
1578 LOG(
"Could not read file "+filename);
1581 unsigned long subChunk1Size = lbuf;
1582 if (subChunk1Size < 16)
1584 LOG(
"Invalid WAV file (invalid subChunk1Size): "+filename);
1588 if (stream->read(&sbuf, 2) != 2)
1590 LOG(
"Could not read file "+filename);
1593 unsigned short audioFormat = sbuf;
1594 if (audioFormat != 1)
1596 LOG(
"Invalid WAV file (invalid audioformat "+
TOSTRING(audioFormat)+
"): "+filename);
1600 if (stream->read(&sbuf, 2) != 2)
1602 LOG(
"Could not read file "+filename);
1605 unsigned short channels = sbuf;
1607 if (stream->read(&lbuf, 4) != 4)
1609 LOG(
"Could not read file "+filename);
1612 unsigned long freq = lbuf;
1616 if (stream->read(&sbuf, 2) != 2)
1618 LOG(
"Could not read file "+filename);
1621 unsigned short bps = sbuf;
1623 if (stream->read(magic, 4) != 4)
1625 LOG(
"Could not read file "+filename);
1628 if (String(magic) != String(
"data") && String(magic) != String(
"fact"))
1630 LOG(
"Invalid WAV file (no data/fact): "+filename);
1634 if (String(magic) == String(
"fact"))
1638 if (stream->read(magic, 4) != 4)
1640 LOG(
"Could not read file "+filename);
1643 if (String(magic) != String(
"data"))
1645 LOG(
"Invalid WAV file (no data): "+filename);
1650 if (stream->read(&lbuf, 4) != 4)
1652 LOG(
"Could not read file "+filename);
1656 unsigned long dataSize = lbuf;
1659 if (channels == 1 && bps == 8)
1660 format = AL_FORMAT_MONO8;
1661 else if (channels == 1 && bps == 16)
1662 format = AL_FORMAT_MONO16;
1663 else if (channels == 2 && bps == 8)
1664 format = AL_FORMAT_STEREO16;
1665 else if (channels == 2 && bps == 16)
1666 format = AL_FORMAT_STEREO16;
1669 LOG(
"Invalid WAV file (wrong channels/bps): "+filename);
1673 if (channels != 1) LOG(
"Invalid WAV file: the file needs to be mono, and nothing else. Will try to continue anyways ...");
1676 void* bdata = malloc(dataSize);
1679 LOG(
"Memory error reading file "+filename);
1682 if (stream->read(bdata, dataSize) != dataSize)
1684 LOG(
"Could not read file "+filename);
1692 alBufferData(buffer,
format, bdata, dataSize, freq);
1693 error = alGetError();
1698 if (error != AL_NO_ERROR)
1700 LOG(
"OpenAL error while loading buffer for "+filename+
" : "+
TOSTRING(error));
1707 #endif // USE_OPENAL