OpenClonk
C4SoundModifierList Class Reference

#include <C4SoundModifiers.h>

Public Member Functions

 C4SoundModifierList ()
 
void Init ()
 
void Add (C4SoundModifier *new_modifier)
 
void Remove (C4SoundModifier *prev_modifier)
 
C4SoundModifierGet (class C4PropList *props, bool create_if_not_found)
 
void Clear ()
 
void SetGlobalModifier (C4SoundModifier *new_modifier, int32_t player_index)
 
C4SoundModifierGetGlobalModifier (int32_t player_index) const
 

Detailed Description

Definition at line 112 of file C4SoundModifiers.h.

Constructor & Destructor Documentation

◆ C4SoundModifierList()

C4SoundModifierList::C4SoundModifierList ( )

Definition at line 195 of file C4SoundModifiers.cpp.

196 {
197  for (int32_t i = 0; i <= C4SoundModifier::C4SMT_Max; ++i)
198  is_effect_available[i] = false;
199 }

References C4SoundModifier::C4SMT_Max.

Member Function Documentation

◆ Add()

void C4SoundModifierList::Add ( C4SoundModifier new_modifier)
inline

Definition at line 122 of file C4SoundModifiers.h.

122 { sound_modifiers.push_back(new_modifier); }

Referenced by C4SoundModifier::C4SoundModifier().

Here is the caller graph for this function:

◆ Clear()

void C4SoundModifierList::Clear ( )

Definition at line 282 of file C4SoundModifiers.cpp.

283 {
284  // Release all sounds. ref count should be zero now because sound instances should have been cleared before this call.
285  for (auto iter = sound_modifiers.begin(); iter != sound_modifiers.end(); )
286  {
287  C4SoundModifier *modifier = *iter;
288  ++iter;
289  // release after iterator increase because deletion will modify the list
290  assert(modifier->GetRefCount() == 0);
291  modifier->Release();
292  }
293 }
int32_t GetRefCount() const

References C4SoundModifier::GetRefCount(), and C4SoundModifier::Release().

Referenced by C4Game::Clear(), and C4SoundSystem::Clear().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Get()

C4SoundModifier * C4SoundModifierList::Get ( class C4PropList props,
bool  create_if_not_found 
)

Definition at line 295 of file C4SoundModifiers.cpp.

296 {
297  // find odifier by prop list
298  auto iter = std::find_if(sound_modifiers.begin(), sound_modifiers.end(),
299  [props](const C4SoundModifier *mod) { return mod->GetProps() == props; });
300  if (iter != sound_modifiers.end()) return *iter;
301  // if not found, create if desired
302  if (!create_if_not_found) return nullptr;
303  C4SoundModifier *modifier;
304  int32_t effect_type = props->GetPropertyInt(P_Type);
305  if (!is_effect_available[effect_type]) return nullptr; // Not supported D:
306  switch (effect_type)
307  {
309  modifier = new C4SoundModifierReverb(props);
310  break;
312  modifier = new C4SoundModifierEcho(props);
313  break;
315  modifier = new C4SoundModifierEqualizer(props);
316  break;
317  default:
318  // invalid modifier
319  return nullptr;
320  }
321  // initial parameter settings
322  modifier->Update();
323  return modifier;
324 }
@ P_Type
virtual void Update()

References C4SoundModifier::C4SMT_Echo, C4SoundModifier::C4SMT_Equalizer, C4SoundModifier::C4SMT_Reverb, C4PropList::GetPropertyInt(), P_Type, and C4SoundModifier::Update().

Referenced by C4Game::SetGlobalSoundModifier(), and C4Player::SetSoundModifier().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetGlobalModifier()

C4SoundModifier * C4SoundModifierList::GetGlobalModifier ( int32_t  player_index) const

Definition at line 348 of file C4SoundModifiers.cpp.

349 {
350  // safety
351  int32_t list_index = player_index + 1;
352  if (list_index < 0 || static_cast<size_t>(list_index) >= global_modifiers.size()) return nullptr;
353  // get from player and fall back to global list
354  C4SoundModifier *result = global_modifiers[list_index];
355  if (!result && list_index) result = global_modifiers[0];
356  return result;
357 }

Referenced by C4SoundInstance::SetPlayer().

Here is the caller graph for this function:

◆ Init()

void C4SoundModifierList::Init ( )

Definition at line 201 of file C4SoundModifiers.cpp.

202 {
203  is_initialized = false;
204 #if (AUDIO_TK == AUDIO_TK_OPENAL) && defined(HAVE_ALEXT)
205 #define LOAD_ALPROC(x) ((void *&)(x) = alGetProcAddress(#x))
207  if (!alcIsExtensionPresent(Application.MusicSystem.GetDevice(), "ALC_EXT_EFX"))
208  {
209  LogF("ALExt: No efx extensions available. Sound modifications disabled.");
210  return;
211  }
212  LOAD_ALPROC(alGenEffects);
213  LOAD_ALPROC(alDeleteEffects);
214  LOAD_ALPROC(alIsEffect);
215  LOAD_ALPROC(alEffecti);
216  LOAD_ALPROC(alEffectiv);
217  LOAD_ALPROC(alEffectf);
218  LOAD_ALPROC(alEffectfv);
219  LOAD_ALPROC(alGetEffecti);
220  LOAD_ALPROC(alGetEffectiv);
221  LOAD_ALPROC(alGetEffectf);
222  LOAD_ALPROC(alGetEffectfv);
223  LOAD_ALPROC(alGenAuxiliaryEffectSlots);
224  LOAD_ALPROC(alDeleteAuxiliaryEffectSlots);
225  LOAD_ALPROC(alIsAuxiliaryEffectSlot);
226  LOAD_ALPROC(alAuxiliaryEffectSloti);
227  LOAD_ALPROC(alAuxiliaryEffectSlotiv);
228  LOAD_ALPROC(alAuxiliaryEffectSlotf);
229  LOAD_ALPROC(alAuxiliaryEffectSlotfv);
230  LOAD_ALPROC(alGetAuxiliaryEffectSloti);
231  LOAD_ALPROC(alGetAuxiliaryEffectSlotiv);
232  LOAD_ALPROC(alGetAuxiliaryEffectSlotf);
233  LOAD_ALPROC(alGetAuxiliaryEffectSlotfv);
234  if (!alGenEffects)
235  {
236  LogF("ALExt: Error loading efx extensions. Sound modifications disabled.");
237  return; // safety
238  }
239  StdStrBuf sAvailableEffects("");
240  StdStrBuf sUnavailableEffects("");
241  static const struct {
242  ALenum effect;
243  const char *name;
244  } test_effects[] = {
245 #define AL_TEST_EFFECT(effect) { effect, #effect }
246  AL_TEST_EFFECT(AL_EFFECT_REVERB),
247  AL_TEST_EFFECT(AL_EFFECT_ECHO),
248  AL_TEST_EFFECT(AL_EFFECT_EQUALIZER),
249 #undef AL_TEST_EFFECT
250  };
251  ALuint effect = 0u;
252  alGenEffects(1, &effect);
253  ALenum err = alGetError();
254  if (err != AL_NO_ERROR)
255  {
256  LogF("OpenAL alGenEffects Error: %s", alGetString(err));
257  }
258  for (auto test_effect : test_effects)
259  {
260  alEffecti(effect, AL_EFFECT_TYPE, test_effect.effect);
261  err = alGetError();
262  bool is_ok = (err == AL_NO_ERROR);
263  is_effect_available[test_effect.effect] = is_ok;
264  StdStrBuf *target_string;
265  if (!is_ok) target_string = &sUnavailableEffects; else target_string = &sAvailableEffects;
266  if (target_string->getLength()) target_string->Append(", ");
267  target_string->Append(test_effect.name);
268  if (!is_ok) target_string->AppendFormat(" (%s)", alGetString(err));
269  }
270  if (alIsEffect(effect)) alDeleteEffects(1, &effect);
271  if (sAvailableEffects.getLength() == 0) sAvailableEffects = "(none)";
272  if (sUnavailableEffects.getLength() == 0) sUnavailableEffects = "(none)";
273  LogF("OpenAL extensions loaded. Available: %s. Unavailable: %s.", sAvailableEffects.getData(), sUnavailableEffects.getData());
274 #undef LOAD_ALPROC
275 #else
276  // modifiers not supported
277  return;
278 #endif
279  is_initialized = true;
280 }
C4Application Application
Definition: C4Globals.cpp:44
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
C4MusicSystem MusicSystem
Definition: C4Application.h:41
void SelectContext()
ALCdevice * GetDevice() const
Definition: C4MusicSystem.h:90
void AppendFormat(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:190
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:519
size_t getLength() const
Definition: StdBuf.h:445

References StdStrBuf::Append(), StdStrBuf::AppendFormat(), Application, StdStrBuf::getData(), C4MusicSystem::GetDevice(), StdStrBuf::getLength(), LogF(), C4Application::MusicSystem, and C4MusicSystem::SelectContext().

Referenced by C4SoundSystem::Init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Remove()

void C4SoundModifierList::Remove ( C4SoundModifier prev_modifier)
inline

Definition at line 123 of file C4SoundModifiers.h.

123 { sound_modifiers.remove(prev_modifier); }

Referenced by C4SoundModifier::~C4SoundModifier().

Here is the caller graph for this function:

◆ SetGlobalModifier()

void C4SoundModifierList::SetGlobalModifier ( C4SoundModifier new_modifier,
int32_t  player_index 
)

Definition at line 326 of file C4SoundModifiers.cpp.

327 {
328  // -1 based array access for NO_OWNER player number
329  int32_t global_modifier_index = player_number + 1;
330  if (global_modifier_index < 0) return; // safety
331  size_t index = static_cast<size_t>(global_modifier_index);
332  if (index >= global_modifiers.size()) global_modifiers.resize(index+1);
333  if (new_modifier != global_modifiers[index])
334  {
335  // Run new effects with new modifier
336  C4SoundModifier *old_modifier = global_modifiers[index];
337  global_modifiers[index] = new_modifier;
338  // update existing sound effects first
340  if (pInst->GetModifier() == old_modifier) // that check is not 100% correct but should cover all realistic use-cases
341  pInst->SetModifier(new_modifier, true);
342  // Reference counting
343  if (new_modifier) new_modifier->AddRef();
344  if (old_modifier) old_modifier->DelRef();
345  }
346 }
C4SoundSystem SoundSystem
Definition: C4Application.h:42
C4SoundInstance * GetFirstInstance() const
C4SoundInstance * GetNextInstance(C4SoundInstance *prev) const

References C4SoundModifier::AddRef(), Application, C4SoundModifier::DelRef(), C4SoundSystem::GetFirstInstance(), C4SoundSystem::GetNextInstance(), and C4Application::SoundSystem.

Referenced by C4Game::SetGlobalSoundModifier(), and C4Player::SetSoundModifier().

Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: