Skip to content

Commit 5ada8a3

Browse files
committed
[Audio/AudioData] Added a type dedicated to just audio data
- A Sound can be constructed with and load an AudioData object - The individual members of Sound are replaced with AudioData - Microphone's and WavFormat's functions now return & take AudioData objects instead of Sound ones - Removed Microphone::recoverSound(), now useless - Removed the Internal::SoundAccess type, now unneeded
1 parent 7a32866 commit 5ada8a3

File tree

16 files changed

+223
-232
lines changed

16 files changed

+223
-232
lines changed

examples/audioDemo.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,17 @@ int main() {
5050
// Audio //
5151
///////////
5252

53+
static const Raz::AudioData knockAudio = Raz::WavFormat::load(RAZ_ROOT "assets/sounds/knock.wav");
54+
static const Raz::AudioData waveSeagullsAudio = Raz::WavFormat::load(RAZ_ROOT "assets/sounds/wave_seagulls.wav");
55+
5356
auto& audio = world.addSystem<Raz::AudioSystem>();
5457

5558
// The Listener entity requires a Transform component
5659
auto& listener = world.addEntityWithComponent<Raz::Transform>().addComponent<Raz::Listener>();
5760

5861
Raz::Entity& sound = world.addEntity();
5962
auto& soundTrans = sound.addComponent<Raz::Transform>();
60-
auto& soundComp = sound.addComponent<Raz::Sound>(Raz::WavFormat::load(RAZ_ROOT "assets/sounds/knock.wav"));
63+
auto& soundComp = sound.addComponent<Raz::Sound>(knockAudio);
6164

6265
Raz::Microphone microphone(Raz::AudioFormat::MONO_U8, 16000, 1.f);
6366

@@ -109,7 +112,6 @@ int main() {
109112
listener.setGain(listenerGain);
110113

111114
soundComp.init();
112-
soundComp.load();
113115
soundComp.setRepeat(isRepeating);
114116
soundComp.setGain(soundGain);
115117
soundComp.setPitch(soundPitch);
@@ -162,11 +164,11 @@ int main() {
162164
switch (i) {
163165
case 0:
164166
default:
165-
soundComp = Raz::WavFormat::load(RAZ_ROOT "assets/sounds/knock.wav");
167+
soundComp.load(knockAudio);
166168
break;
167169

168170
case 1:
169-
soundComp = Raz::WavFormat::load(RAZ_ROOT "assets/sounds/wave_seagulls.wav");
171+
soundComp.load(waveSeagullsAudio);
170172
break;
171173
}
172174

@@ -605,7 +607,7 @@ int main() {
605607
// Starting application //
606608
//////////////////////////
607609

608-
std::vector<uint8_t> captureData;
610+
Raz::AudioData captureData;
609611

610612
app.run([&] (const Raz::FrameTimeInfo& timeInfo) {
611613
soundTrans.setPosition((moveSource ? Raz::Vec3f(std::sin(timeInfo.globalTime) * 3.f, 0.f, 1.f) : Raz::Vec3f(0.f)));
@@ -624,23 +626,23 @@ int main() {
624626
constexpr float factorI16 = 1.f / 32767;
625627

626628
if (captureBitDepth == 8) {
627-
for (std::size_t i = 0; i < captureData.size(); ++i) {
629+
for (std::size_t i = 0; i < captureData.buffer.size(); ++i) {
628630
if (isCaptureStereo) { // Stereo 8
629-
leftCapturePlot.push(static_cast<float>(captureData[i]) * factorU8 - 1.f);
630-
rightCapturePlot.push(static_cast<float>(captureData[i + 1]) * factorU8 - 1.f);
631+
leftCapturePlot.push(static_cast<float>(captureData.buffer[i]) * factorU8 - 1.f);
632+
rightCapturePlot.push(static_cast<float>(captureData.buffer[i + 1]) * factorU8 - 1.f);
631633
++i;
632634
} else { // Mono 8
633-
monoCapturePlot.push(static_cast<float>(captureData[i]) * factorU8 - 1.f);
635+
monoCapturePlot.push(static_cast<float>(captureData.buffer[i]) * factorU8 - 1.f);
634636
}
635637
}
636638
} else {
637-
for (std::size_t i = 0; i < captureData.size(); i += 2) {
639+
for (std::size_t i = 0; i < captureData.buffer.size(); i += 2) {
638640
if (isCaptureStereo) { // Stereo 16
639-
leftCapturePlot.push(static_cast<float>(static_cast<int16_t>((captureData[i] << 0u) | (captureData[i + 1] << 8u))) * factorI16);
640-
rightCapturePlot.push(static_cast<float>(static_cast<int16_t>((captureData[i + 2] << 0u) | (captureData[i + 3] << 8u))) * factorI16);
641+
leftCapturePlot.push(static_cast<float>(static_cast<int16_t>(captureData.buffer[i] | (captureData.buffer[i + 1] << 8u))) * factorI16);
642+
rightCapturePlot.push(static_cast<float>(static_cast<int16_t>(captureData.buffer[i + 2] | (captureData.buffer[i + 3] << 8u))) * factorI16);
641643
i += 2;
642644
} else { // Mono 16
643-
monoCapturePlot.push(static_cast<float>(static_cast<int16_t>((captureData[i] << 0u) | (captureData[i + 1] << 8u))) * factorI16);
645+
monoCapturePlot.push(static_cast<float>(static_cast<int16_t>(captureData.buffer[i] | (captureData.buffer[i + 1] << 8u))) * factorI16);
644646
}
645647
}
646648
}

include/RaZ/Audio/AudioData.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#pragma once
2+
3+
#ifndef RAZ_AUDIODATA_HPP
4+
#define RAZ_AUDIODATA_HPP
5+
6+
#include <cstdint>
7+
#include <vector>
8+
9+
namespace Raz {
10+
11+
enum class AudioFormat : int {
12+
MONO_U8 = 4352 /* AL_FORMAT_MONO8 */, ///< Mono format on 8 unsigned bits (0 to 255).
13+
STEREO_U8 = 4354 /* AL_FORMAT_STEREO8 */, ///< Stereo format on 8 unsigned bits (0 to 255).
14+
MONO_I16 = 4353 /* AL_FORMAT_MONO16 */, ///< Mono format on 16 signed bits (-32768 to 32767).
15+
STEREO_I16 = 4355 /* AL_FORMAT_STEREO16 */, ///< Stereo format on 16 signed bits (-32768 to 32767).
16+
MONO_F32 = 65552 /* AL_FORMAT_MONO_FLOAT32 */, ///< Mono format on 32 floating-point bits (float).
17+
STEREO_F32 = 65553 /* AL_FORMAT_STEREO_FLOAT32 */, ///< Stereo format on 32 floating-point bits (float).
18+
MONO_F64 = 65554 /* AL_FORMAT_MONO_DOUBLE_EXT */, ///< Mono format on 64 floating-point bits (double).
19+
STEREO_F64 = 65555 /* AL_FORMAT_STEREO_DOUBLE_EXT */ ///< Stereo format on 64 floating-point bits (double).
20+
};
21+
22+
struct AudioData {
23+
AudioFormat format {};
24+
unsigned int frequency {};
25+
std::vector<uint8_t> buffer {};
26+
};
27+
28+
} // namespace Raz
29+
30+
#endif // RAZ_AUDIODATA_HPP

include/RaZ/Audio/AudioSystem.hpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,6 @@
99

1010
namespace Raz {
1111

12-
enum class AudioFormat : int {
13-
MONO_U8 = 4352 /* AL_FORMAT_MONO8 */, ///< Mono format on 8 unsigned bits (0 to 255).
14-
STEREO_U8 = 4354 /* AL_FORMAT_STEREO8 */, ///< Stereo format on 8 unsigned bits (0 to 255).
15-
MONO_I16 = 4353 /* AL_FORMAT_MONO16 */, ///< Mono format on 16 signed bits (-32768 to 32767).
16-
STEREO_I16 = 4355 /* AL_FORMAT_STEREO16 */, ///< Stereo format on 16 signed bits (-32768 to 32767).
17-
MONO_F32 = 65552 /* AL_FORMAT_MONO_FLOAT32 */, ///< Mono format on 32 floating-point bits (float).
18-
STEREO_F32 = 65553 /* AL_FORMAT_STEREO_FLOAT32 */, ///< Stereo format on 32 floating-point bits (float).
19-
MONO_F64 = 65554 /* AL_FORMAT_MONO_DOUBLE_EXT */, ///< Mono format on 64 floating-point bits (double).
20-
STEREO_F64 = 65555 /* AL_FORMAT_STEREO_DOUBLE_EXT */ ///< Stereo format on 64 floating-point bits (double).
21-
};
22-
2312
class AudioSystem final : public System {
2413
public:
2514
/// Creates a system handling audio.

include/RaZ/Audio/Microphone.hpp

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
#ifndef RAZ_MICROPHONE_HPP
44
#define RAZ_MICROPHONE_HPP
55

6-
#include "RaZ/Audio/AudioSystem.hpp"
6+
#include "RaZ/Audio/AudioData.hpp"
77

8-
namespace Raz {
8+
#include <string>
99

10-
class Sound;
10+
namespace Raz {
1111

1212
class Microphone {
1313
public:
@@ -45,21 +45,16 @@ class Microphone {
4545
/// Recovers the amount of currently captured time.
4646
/// \return Available captured duration, in seconds.
4747
float recoverAvailableDuration() const noexcept;
48-
/// Recovers captured samples.
49-
/// \note This flushes the recovered captured data; if recovering something, the available sample count right after this call will be less than it was before.
50-
/// \param maxDuration Maximum amount of time to recover, in seconds. Giving a negative value will result in recovering all available samples.
51-
/// \return Captured samples.
52-
std::vector<uint8_t> recoverData(float maxDuration = -1.f) const;
53-
/// Recovers captured samples. This overload can be used to avoid reallocating the whole memory range on each call.
54-
/// \note This flushes the recovered captured data; if recovering something, the available sample count right after this call will be less than it was before.
55-
/// \param data Data to be filled with the captured samples.
48+
/// Recovers captured audio data.
49+
/// \note This flushes the captured data; if recovering something, the available sample count right after this call will be less than it was before.
5650
/// \param maxDuration Maximum amount of time to recover, in seconds. Giving a negative value will result in recovering all available samples.
57-
void recoverData(std::vector<uint8_t>& data, float maxDuration = -1.f) const;
58-
/// Recovers captured samples as a Sound object.
59-
/// \note This flushes the recovered captured data; if recovering something, the available sample count right after this call will be less than it was before.
51+
/// \return Captured audio data. The format & frequency are those of the current audio input device.
52+
AudioData recoverData(float maxDuration = -1.f) const;
53+
/// Recovers captured audio data. This overload can be used to avoid reallocating the whole memory range on each call.
54+
/// \note This flushes the captured data; if recovering something, the available sample count right after this call will be less than it was before.
55+
/// \param data Data to be filled with the captured audio.
6056
/// \param maxDuration Maximum amount of time to recover, in seconds. Giving a negative value will result in recovering all available samples.
61-
/// \return Captured sound.
62-
Sound recoverSound(float maxDuration = -1.f) const;
57+
void recoverData(AudioData& data, float maxDuration = -1.f) const;
6358

6459
Microphone& operator=(const Microphone&) = delete;
6560
Microphone& operator=(Microphone&&) = delete;

include/RaZ/Audio/Sound.hpp

Lines changed: 16 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@
44
#define RAZ_SOUND_HPP
55

66
#include "RaZ/Component.hpp"
7-
#include "RaZ/Audio/AudioSystem.hpp"
7+
#include "RaZ/Audio/AudioData.hpp"
88
#include "RaZ/Data/OwnerValue.hpp"
99

10-
#include <cstddef>
1110
#include <limits>
12-
#include <vector>
1311

1412
namespace Raz {
1513

16-
namespace Internal { class SoundAccess; }
17-
1814
class SoundEffectSlot;
1915

2016
template <typename T, std::size_t Size>
@@ -29,24 +25,25 @@ enum class SoundState : int {
2925
};
3026

3127
class Sound final : public Component {
32-
friend Internal::SoundAccess;
33-
friend class Microphone;
34-
3528
public:
3629
Sound() { init(); }
30+
explicit Sound(AudioData data) : Sound() { load(std::move(data)); }
3731
Sound(const Sound&) = delete;
3832
Sound(Sound&&) noexcept = default;
3933

40-
constexpr unsigned int getBufferIndex() const noexcept { return m_buffer; }
41-
constexpr AudioFormat getFormat() const noexcept { return m_format; }
42-
constexpr int getFrequency() const noexcept { return m_frequency; }
34+
constexpr unsigned int getBufferIndex() const noexcept { return m_bufferIndex; }
35+
constexpr const AudioData& getData() const noexcept { return m_data; }
4336

44-
/// Initializes the sound.
37+
/// Initializes the sound. If there is audio data, also loads it into memory.
4538
/// \note A Sound must be initialized again after opening an audio device.
4639
/// \see AudioSystem::open()
4740
void init();
48-
/// Loads the sound's data into memory.
49-
void load();
41+
/// Loads the given audio data into memory.
42+
/// @param data Data to be loaded.
43+
void load(AudioData data) {
44+
m_data = std::move(data);
45+
load();
46+
}
5047
/// Sets the sound's pitch multiplier.
5148
/// \param pitch Sound's pitch multiplier; must be positive. 1 is the default.
5249
void setPitch(float pitch) const noexcept;
@@ -128,30 +125,15 @@ class Sound final : public Component {
128125
~Sound() override { destroy(); }
129126

130127
private:
131-
OwnerValue<unsigned int, std::numeric_limits<unsigned int>::max()> m_buffer {};
132-
OwnerValue<unsigned int, std::numeric_limits<unsigned int>::max()> m_source {};
133-
134-
AudioFormat m_format {};
135-
int m_frequency {};
136-
std::vector<uint8_t> m_data {};
137-
};
138-
139-
namespace Internal {
128+
/// Loads the audio data into memory.
129+
void load();
140130

141-
/// Class giving direct access to a Sound's private members; useful for file importers.
142-
/// \note This class is not meant to be used in user code.
143-
class SoundAccess {
144-
public:
145-
SoundAccess() = delete;
131+
OwnerValue<unsigned int, std::numeric_limits<unsigned int>::max()> m_bufferIndex {};
132+
OwnerValue<unsigned int, std::numeric_limits<unsigned int>::max()> m_sourceIndex {};
146133

147-
static AudioFormat& getFormat(Sound& sound) { return sound.m_format; }
148-
static int& getFrequency(Sound& sound) { return sound.m_frequency; }
149-
static const std::vector<uint8_t>& getData(const Sound& sound) { return sound.m_data; }
150-
static std::vector<uint8_t>& getData(Sound& sound) { return sound.m_data; }
134+
AudioData m_data {};
151135
};
152136

153-
} // namespace Internal
154-
155137
} // namespace Raz
156138

157139
#endif // RAZ_SOUND_HPP

include/RaZ/Data/WavFormat.hpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@
55

66
namespace Raz {
77

8+
struct AudioData;
89
class FilePath;
9-
class Sound;
1010

1111
namespace WavFormat {
1212

13-
/// Loads a [WAV](https://en.wikipedia.org/wiki/WAV) audio from a file.
13+
/// Loads audio data from a [WAV](https://en.wikipedia.org/wiki/WAV) file.
1414
/// \param filePath File from which to load the audio.
15-
/// \return Imported sound.
16-
Sound load(const FilePath& filePath);
15+
/// \return Imported audio data.
16+
AudioData load(const FilePath& filePath);
1717

18-
/// Saves a sound to a WAV file.
18+
/// Saves audio data to a [WAV](https://en.wikipedia.org/wiki/WAV) file.
1919
/// \param filePath File to which to save the sound.
20-
/// \param sound Sound to export data from.
21-
void save(const FilePath& filePath, const Sound& sound);
20+
/// \param data Audio data to export.
21+
void save(const FilePath& filePath, const AudioData& data);
2222

2323
} // namespace WavFormat
2424

include/RaZ/RaZ.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "System.hpp"
1010
#include "World.hpp"
1111
#include "Animation/Skeleton.hpp"
12+
#include "Audio/AudioData.hpp"
1213
#include "Audio/AudioSystem.hpp"
1314
#include "Audio/Listener.hpp"
1415
#include "Audio/Microphone.hpp"

src/RaZ/Audio/Microphone.cpp

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <AL/al.h>
88
#include <AL/alc.h>
99

10+
#include <stdexcept>
1011
#include <string>
1112

1213
namespace Raz {
@@ -52,7 +53,7 @@ constexpr int recoverFrameSize(AudioFormat format) {
5253
break;
5354

5455
default:
55-
throw std::invalid_argument("Error: Unhandled audio format");
56+
throw std::invalid_argument("[Microphone] Unhandled audio format");
5657
}
5758

5859
switch (format) {
@@ -77,7 +78,7 @@ constexpr int recoverFrameSize(AudioFormat format) {
7778
break;
7879

7980
default:
80-
throw std::invalid_argument("Error: Unhandled audio format");
81+
throw std::invalid_argument("[Microphone] Unhandled audio format");
8182
}
8283

8384
return channelCount * bitCount / 8;
@@ -170,17 +171,19 @@ float Microphone::recoverAvailableDuration() const noexcept {
170171
return (static_cast<float>(recoverAvailableSampleCount()) / static_cast<float>(m_frequency));
171172
}
172173

173-
std::vector<uint8_t> Microphone::recoverData(float maxDuration) const {
174-
std::vector<uint8_t> data;
174+
AudioData Microphone::recoverData(float maxDuration) const {
175+
AudioData data {};
175176
recoverData(data, maxDuration);
176177

177178
return data;
178179
}
179180

180-
void Microphone::recoverData(std::vector<uint8_t>& data, float maxDuration) const {
181+
void Microphone::recoverData(AudioData& data, float maxDuration) const {
181182
ZoneScopedN("Microphone::recoverData");
182183

183-
data.clear();
184+
data.format = m_format;
185+
data.frequency = m_frequency;
186+
data.buffer.clear();
184187

185188
if (maxDuration == 0.f)
186189
return;
@@ -193,25 +196,12 @@ void Microphone::recoverData(std::vector<uint8_t>& data, float maxDuration) cons
193196
if (maxDuration > 0.f)
194197
sampleCount = std::min(sampleCount, static_cast<int>(maxDuration * static_cast<float>(m_frequency)));
195198

196-
data.resize(recoverFrameSize(m_format) * sampleCount);
199+
data.buffer.resize(recoverFrameSize(m_format) * sampleCount);
197200

198-
alcCaptureSamples(static_cast<ALCdevice*>(m_device), data.data(), sampleCount);
201+
alcCaptureSamples(static_cast<ALCdevice*>(m_device), data.buffer.data(), sampleCount);
199202
checkError(m_device, "Failed to recover captured data");
200203
}
201204

202-
Sound Microphone::recoverSound(float maxDuration) const {
203-
ZoneScopedN("Microphone::recoverSound");
204-
205-
Sound sound;
206-
207-
sound.m_format = m_format;
208-
sound.m_frequency = static_cast<int>(m_frequency);
209-
sound.m_data = recoverData(maxDuration);
210-
sound.load();
211-
212-
return sound;
213-
}
214-
215205
void Microphone::destroy() {
216206
ZoneScopedN("Microphone::destroy");
217207

0 commit comments

Comments
 (0)