• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Razakhel / RaZ / 18064138724

27 Sep 2025 04:20PM UTC coverage: 74.093% (+0.04%) from 74.05%
18064138724

push

github

Razakhel
[Utils/Logger] Added formatted logging overloads

- Formatted calls to logging functions and made use of std::format() in several other places

100 of 170 new or added lines in 36 files covered. (58.82%)

4 existing lines in 2 files now uncovered.

8334 of 11248 relevant lines covered (74.09%)

1757.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.68
/src/RaZ/Audio/AudioSystem.cpp
1
#include "RaZ/Audio/AudioSystem.hpp"
2
#include "RaZ/Audio/Listener.hpp"
3
#include "RaZ/Audio/Sound.hpp"
4
#include "RaZ/Math/Matrix.hpp"
5
#include "RaZ/Math/Transform.hpp"
6
#include "RaZ/Physics/RigidBody.hpp"
7
#include "RaZ/Utils/Logger.hpp"
8

9
#include "tracy/Tracy.hpp"
10

11
#include <AL/al.h>
12
#include <AL/alc.h>
13

14
#include <string>
15

16
namespace Raz {
17

18
namespace {
19

20
constexpr const char* recoverAlcErrorStr(int errorCode) {
×
21
  switch (errorCode) {
×
22
    case ALC_INVALID_DEVICE:  return "Invalid device";
×
23
    case ALC_INVALID_CONTEXT: return "Invalid context";
×
24
    case ALC_INVALID_ENUM:    return "Invalid enum";
×
25
    case ALC_INVALID_VALUE:   return "Invalid value";
×
26
    case ALC_OUT_OF_MEMORY:   return "Out of memory";
×
27
    case ALC_NO_ERROR:        return "No error";
×
28
    default:                  return "Unknown error";
×
29
  }
30
}
31

32
inline void checkError(void* device, const std::string& errorMsg) {
36✔
33
  const int errorCode = alcGetError(static_cast<ALCdevice*>(device));
36✔
34

35
  if (errorCode != ALC_NO_ERROR)
36✔
NEW
36
    Logger::error("[OpenAL] {} ({})", errorMsg, recoverAlcErrorStr(errorCode));
×
37
}
36✔
38

39
} // namespace
40

41
AudioSystem::AudioSystem(const std::string& deviceName) {
18✔
42
  ZoneScopedN("AudioSystem::AudioSystem");
43

44
  registerComponents<Sound, Listener>();
18✔
45
  openDevice(deviceName);
18✔
46

47
  if (m_device == nullptr || m_context == nullptr)
18✔
48
    return;
1✔
49

50
  const std::string_view alRenderer = alGetString(AL_RENDERER);
17✔
51

52
  Logger::debug("[AudioSystem] OpenAL renderer: {}", alRenderer);
17✔
53

54
#if !defined(RAZ_PLATFORM_EMSCRIPTEN) // Emscripten has its own implementation with some OpenAL Soft extensions
55
  if (alRenderer != "OpenAL Soft")
17✔
56
    Logger::warn("[OpenAL] Standard OpenAL detected; make sure to use OpenAL Soft to get all possible features");
×
57
#endif
58
}
×
59

60
std::vector<std::string> AudioSystem::recoverDevices() {
2✔
61
  if (!alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT")) // If the needed extension is unsupported, return an empty vector
2✔
62
    return {};
×
63

64
  std::vector<std::string> devices;
2✔
65

66
  // This recovers all devices' names in a single string, each name separated by a null character ('\0'), and ending with two of those
67
  // For example: "First device\0Second device\0Third device\0\0"
68
  const char* devicesNames = alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);
2✔
69

70
  while (devicesNames[0] != '\0') {
4✔
71
    devices.emplace_back(devicesNames); // This automatically fills the string until the first \0
2✔
72
    devicesNames += devices.back().size() + 1;
2✔
73
  }
74

75
  return devices;
2✔
76
}
2✔
77

78
void AudioSystem::openDevice(const std::string& deviceName) {
20✔
79
  ZoneScopedN("AudioSystem::openDevice");
80

81
  Logger::debug("[AudioSystem] Opening {}...", (!deviceName.empty() ? std::format("device '{}'", deviceName) : "default device"));
38✔
82

83
  destroy();
20✔
84

85
  m_device = alcOpenDevice((!deviceName.empty() ? deviceName.c_str() : nullptr));
20✔
86
  if (!m_device) {
20✔
87
    Logger::error("[OpenAL] Failed to open an audio device");
2✔
88
    return;
2✔
89
  }
90

91
  m_context = alcCreateContext(static_cast<ALCdevice*>(m_device), nullptr);
18✔
92
  checkError(m_device, "Failed to create context");
18✔
93

94
  if (!alcMakeContextCurrent(static_cast<ALCcontext*>(m_context))) {
18✔
95
    Logger::error("[OpenAL] Failed to make the audio context current");
×
96
    alcGetError(static_cast<ALCdevice*>(m_device)); // Flushing errors, since alcMakeContextCurrent() produces one on failure, which we already handled
×
97
  }
98

99
  Logger::debug("[AudioSystem] Opened device '{}'", recoverCurrentDevice());
18✔
100
}
101

102
std::string AudioSystem::recoverCurrentDevice() const {
23✔
103
  if (m_device == nullptr) // The system has failed to initialize; returning an empty device name
23✔
104
    return {};
2✔
105

106
  if (!alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT")) // If the needed extension is unsupported, return an empty string
21✔
107
    return {};
×
108

109
  return alcGetString(static_cast<ALCdevice*>(m_device), ALC_ALL_DEVICES_SPECIFIER);
42✔
110
}
111

112
bool AudioSystem::update(const FrameTimeInfo&) {
4✔
113
  ZoneScopedN("AudioSystem::update");
114

115
#if defined(RAZ_CONFIG_DEBUG)
116
  // Checking that only one Listener exists
117
  bool hasOneListener = false;
4✔
118
#endif
119

120
  for (Entity* entity : m_entities) {
12✔
121
    if (entity->hasComponent<Sound>()) {
8✔
122
      const Sound& sound = entity->getComponent<Sound>();
5✔
123

124
      if (entity->hasComponent<Transform>()) {
5✔
125
        auto& soundTrans = entity->getComponent<Transform>();
4✔
126

127
        // TODO: Transform's update status may be reinitialized in the RenderSystem (and should theoretically be reset in every system, including here)
128
        //  A viable solution must be implemented to check for and reset this status in all systems
129
        //if (soundTrans.hasUpdated()) {
130
          sound.setPosition(soundTrans.getPosition());
4✔
131
          //soundTrans.setUpdated(false);
132
        //}
133
      }
134

135
      // TODO: velocity should be set only if it has been updated since last time
136
      if (entity->hasComponent<RigidBody>())
5✔
137
        sound.setVelocity(entity->getComponent<RigidBody>().getVelocity());
4✔
138
    }
139

140
    if (entity->hasComponent<Listener>()) {
8✔
141
#if defined(RAZ_CONFIG_DEBUG)
142
      assert("Error: Only one Listener component must exist in an AudioSystem." && !hasOneListener);
3✔
143
      hasOneListener = true;
3✔
144
#endif
145

146
      assert("Error: A Listener entity must have a Transform component." && entity->hasComponent<Transform>());
3✔
147

148
      auto& listener      = entity->getComponent<Listener>();
3✔
149
      auto& listenerTrans = entity->getComponent<Transform>();
3✔
150

151
      //if (listenerTrans.hasUpdated()) {
152
        listener.setPosition(listenerTrans.getPosition());
3✔
153
        listener.setOrientation(Mat3f(listenerTrans.getRotation().computeMatrix()));
3✔
154

155
        //listenerTrans.setUpdated(false);
156
      //}
157

158
      if (entity->hasComponent<RigidBody>())
3✔
159
        listener.setVelocity(entity->getComponent<RigidBody>().getVelocity());
2✔
160
    }
161
  }
162

163
  return true;
4✔
164
}
165

166
void AudioSystem::destroy() {
39✔
167
  ZoneScopedN("AudioSystem::destroy");
168

169
  if (m_context == nullptr && m_device == nullptr)
39✔
170
    return;
21✔
171

172
  Logger::debug("[AudioSystem] Destroying...");
18✔
173

174
  alcMakeContextCurrent(nullptr);
18✔
175

176
  if (m_context != nullptr) {
18✔
177
    alcDestroyContext(static_cast<ALCcontext*>(m_context));
18✔
178
    checkError(m_device, "Failed to destroy context");
18✔
179
    m_context = nullptr;
18✔
180
  }
181

182
  if (m_device != nullptr) {
18✔
183
    if (!alcCloseDevice(static_cast<ALCdevice*>(m_device)))
18✔
184
      Logger::error("[OpenAL] Failed to close the audio device");
×
185

186
    m_device = nullptr;
18✔
187
  }
188

189
  Logger::debug("[AudioSystem] Destroyed");
36✔
190
}
191

192
} // namespace Raz
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc