Skip to content

Commit a8dee59

Browse files
committed
WAV sounds are finally playing, YAY!
1 parent 3335f40 commit a8dee59

10 files changed

Lines changed: 126 additions & 94 deletions

File tree

3DRadSpace/3DRadSpace_CPPSample/MyGame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void MyGame::Load()
4343
{
4444
Game::Load();
4545

46-
_sound = this->Content->Load<Sound>("Data\\Sounds\\explosion.ogg");
46+
_sound = this->Content->Load<Sound>("Data\\Sounds\\myfile.wav");
4747
_soundInstance = std::make_unique<SoundInstance>(_sound);
4848
_soundInstance->SetLooping(false);
4949

3DRadSpace/CMakeSettings.json

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1 @@
1-
{
2-
"configurations": [
3-
{
4-
"name": "x64-Debug",
5-
"generator": "Ninja",
6-
"configurationType": "Debug",
7-
"inheritEnvironments": [ "msvc_x64_x64" ],
8-
"buildRoot": "${projectDir}\\out\\build\\${name}",
9-
"installRoot": "${projectDir}\\out\\install\\${name}",
10-
"cmakeCommandArgs": "",
11-
"ctestCommandArgs": "",
12-
"variables": [
13-
{
14-
"name": "CMAKE_BUILD_TYPE",
15-
"value": "Debug",
16-
"type": "STRING"
17-
}
18-
]
19-
},
20-
{
21-
"name": "x64-Release",
22-
"generator": "Ninja",
23-
"configurationType": "RelWithDebInfo",
24-
"buildRoot": "${projectDir}\\out\\build\\${name}",
25-
"installRoot": "${projectDir}\\out\\install\\${name}",
26-
"cmakeCommandArgs": "",
27-
"buildCommandArgs": "",
28-
"ctestCommandArgs": "",
29-
"inheritEnvironments": [ "msvc_x64_x64" ],
30-
"variables": [
31-
{
32-
"name": "CMAKE_BUILD_TYPE",
33-
"value": "RelWithDebInfo",
34-
"type": "STRING"
35-
}
36-
]
37-
}
38-
]
39-
}
1+


3DRadSpace/Engine3DRadSpace/Audio/AudioBuffer.cpp

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#include "AudioBuffer.hpp"
2-
#include "AudioBuffer.hpp"
32
#include <al.h>
43
#include <vorbis\codec.h>
54
#include <vorbis\vorbisenc.h>
@@ -17,7 +16,7 @@ AudioBuffer::AudioBuffer(char* buffer, int channel, int sampleRate, int bps, int
1716
{
1817
}
1918

20-
std::optional<AudioBuffer> AudioBuffer::FromWAV(const std::filesystem::path& path)
19+
std::expected<AudioBuffer, AudioBuffer::WAVLoadError> AudioBuffer::FromWAV(const std::filesystem::path& path)
2120
{
2221
//https://stackoverflow.com/questions/36949957/loading-a-wav-file-for-openal
2322
auto convertToInt = [](char* buffer, int len) -> int
@@ -38,45 +37,51 @@ std::optional<AudioBuffer> AudioBuffer::FromWAV(const std::filesystem::path& pat
3837
int size;
3938
char buffer[4];
4039

41-
std::ifstream in(path);
40+
std::ifstream in(path, std::ios::binary);
41+
42+
if (in.bad() || in.fail())
43+
{
44+
return std::unexpected(AudioBuffer::WAVLoadError::CannotOpen);
45+
}
46+
4247
in.read(buffer, 4);
4348

4449
if(strncmp(buffer, "RIFF", 4) != 0)
4550
{
46-
//"Error here, not a valid WAV file, RIFF not found in header\n This was found instead: "
47-
return std::nullopt;
51+
//RIFF not found in header
52+
return std::unexpected(AudioBuffer::WAVLoadError::RIFFNotFound);
4853
}
4954

5055
in.read(buffer, 4);//size of file. Not used. Read it to skip over it.
5156
in.read(buffer, 4);//Format, should be WAVE
5257
if(strncmp(buffer, "WAVE", 4) != 0)
5358
{
5459
//not a valid WAV file, RIFF not found in header
55-
return std::nullopt;
60+
return std::unexpected(AudioBuffer::WAVLoadError::RIFFNotFound);
5661
}
5762

5863
in.read(buffer, 4);//Format Space Marker. should equal fmt (space)
5964

6065
if(strncmp(buffer, "fmt ", 4) != 0)
6166
{
6267
//not a valid WAV file, Format Marker not found in header
63-
return std::nullopt;
68+
return std::unexpected(AudioBuffer::WAVLoadError::NoFormatMarker);
6469
}
6570

6671
in.read(buffer, 4);//Length of format data. Should be 16 for PCM, meaning uncompressed.
6772

6873
if(convertToInt(buffer, 4) != 16)
6974
{
7075
// not a valid WAV file, format length wrong in header
71-
return std::nullopt;
76+
return std::unexpected(AudioBuffer::WAVLoadError::WrongFormatLength);
7277
}
7378

7479
in.read(buffer, 2);//Type of format, 1 = PCM
7580

7681
if(convertToInt(buffer, 2) != 1)
7782
{
7883
// not a valid WAV file, file not in PCM format
79-
return std::nullopt;
84+
return std::unexpected(AudioBuffer::WAVLoadError::NotPCM);
8085
}
8186

8287
in.read(buffer, 2);//Get number of channels.
@@ -97,7 +102,7 @@ std::optional<AudioBuffer> AudioBuffer::FromWAV(const std::filesystem::path& pat
97102
bps = convertToInt(buffer, 2);
98103

99104
//Skip character data, which marks the start of the data that we care about.
100-
in.read(buffer, 4);//"data" chunk.
105+
in.read(buffer, 4); //"data" chunk.
101106

102107
in.read(buffer, 4); //Get size of the data
103108

@@ -106,10 +111,14 @@ std::optional<AudioBuffer> AudioBuffer::FromWAV(const std::filesystem::path& pat
106111
if(size < 0)
107112
{
108113
//not a valid WAV file, size of file reports 0
109-
return std::nullopt;
114+
return std::unexpected(AudioBuffer::WAVLoadError::NullSize);
110115
}
111116

112117
char* data = new char[size];
118+
if (data == nullptr)
119+
{
120+
return std::unexpected(AudioBuffer::WAVLoadError::OutOfMemory);
121+
}
113122

114123
in.read(data, size);//Read audio data into buffer, return.
115124

@@ -118,29 +127,17 @@ std::optional<AudioBuffer> AudioBuffer::FromWAV(const std::filesystem::path& pat
118127
int format;
119128
if (channels == 1)
120129
{
121-
if (bps == 8)
122-
{
123-
format = AL_FORMAT_MONO8;
124-
}
125-
else {
126-
format = AL_FORMAT_MONO16;
127-
}
130+
format = bps == 8 ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16;
128131
}
129132
else
130133
{
131-
if (bps == 8)
132-
{
133-
format = AL_FORMAT_STEREO8;
134-
}
135-
else {
136-
format = AL_FORMAT_STEREO16;
137-
}
134+
format = bps == 8 ? AL_FORMAT_STEREO8 : AL_FORMAT_STEREO16;
138135
}
139136

140137
return AudioBuffer(data, channels, sampleRate, bps, format, size);
141138
}
142139

143-
std::optional<AudioBuffer> AudioBuffer::FromOGG(const std::filesystem::path& path)
140+
std::expected<AudioBuffer, AudioBuffer::OGGLoadError> AudioBuffer::FromOGG(const std::filesystem::path& path)
144141
{
145142
//https://gist.github.com/tilkinsc/f91d2a74cff62cc3760a7c9291290b29
146143

@@ -150,21 +147,21 @@ std::optional<AudioBuffer> AudioBuffer::FromOGG(const std::filesystem::path& pat
150147
if(file == nullptr)
151148
{
152149
//Failed to open OGG file.
153-
return std::nullopt;
150+
return std::unexpected(AudioBuffer::OGGLoadError::CannotOpen);
154151
}
155152

156153
if(ov_open_callbacks(file, &vf, nullptr, 0, OV_CALLBACKS_NOCLOSE) < 0)
157154
{
158155
//Not a valid OGG file.
159-
return std::nullopt;
156+
return std::unexpected(AudioBuffer::OGGLoadError::Invalid);
160157
}
161158

162159
vorbis_info* info = ov_info(&vf, -1);
163160
if(info == nullptr)
164161
{
165162
//Failed to get OGG info
166163
ov_clear(&vf);
167-
return std::nullopt;
164+
return std::unexpected(AudioBuffer::OGGLoadError::InfoFail);
168165
}
169166
int channels = info->channels;
170167
int sampleRate = info->rate;
@@ -177,7 +174,7 @@ std::optional<AudioBuffer> AudioBuffer::FromOGG(const std::filesystem::path& pat
177174
{
178175
//Failed to allocate memory for OGG buffer
179176
ov_clear(&vf);
180-
return std::nullopt;
177+
return std::unexpected(AudioBuffer::OGGLoadError::OutOfMemory);
181178
}
182179

183180
for(size_t bytesRead = 0, offset = 0, sel=0; ; offset += bytesRead)
@@ -198,7 +195,7 @@ std::optional<AudioBuffer> AudioBuffer::FromOGG(const std::filesystem::path& pat
198195
//Faulty OGG file.
199196
delete[] buffer;
200197
ov_clear(&vf);
201-
return std::nullopt;
198+
return std::unexpected(AudioBuffer::OGGLoadError::Invalid);
202199
}
203200
}
204201
ov_clear(&vf);

3DRadSpace/Engine3DRadSpace/Audio/AudioBuffer.hpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,30 @@ namespace Engine3DRadSpace::Audio
2323
AudioBuffer& operator=(const AudioBuffer&) = delete;
2424
AudioBuffer& operator=(AudioBuffer&&) = default;
2525

26-
static std::optional<AudioBuffer> FromWAV(const std::filesystem::path& path);
27-
static std::optional<AudioBuffer> FromOGG(const std::filesystem::path& path);
26+
enum class WAVLoadError
27+
{
28+
None,
29+
CannotOpen,
30+
RIFFNotFound,
31+
NoFormatMarker,
32+
WrongFormatLength,
33+
NotPCM,
34+
NullSize,
35+
OutOfMemory
36+
};
37+
38+
static std::expected<AudioBuffer, WAVLoadError> FromWAV(const std::filesystem::path& path);
39+
40+
enum class OGGLoadError
41+
{
42+
None,
43+
CannotOpen,
44+
Invalid,
45+
InfoFail,
46+
OutOfMemory,
47+
};
48+
49+
static std::expected<AudioBuffer, OGGLoadError> FromOGG(const std::filesystem::path& path);
2850

2951
~AudioBuffer() = default;
3052

3DRadSpace/Engine3DRadSpace/Audio/AudioEngine.cpp

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ void AudioEngine::_initializeContext()
1313
_audioContext = alcCreateContext(static_cast<ALCdevice*>(_audioDevice), nullptr);
1414
if(!_audioContext)
1515
{
16-
throw Exception("Failed to create audio scene!");
16+
throw Exception("Failed to create audio context!");
1717
}
1818

1919
alcMakeContextCurrent(static_cast<ALCcontext*>(_audioContext));
2020

21-
_hasEAX2support = static_cast<bool>(alIsExtensionPresent("EAX2.0"));
22-
2321
alGetError(); //clear error flag
2422
}
2523

@@ -67,14 +65,17 @@ std::vector<std::string> AudioEngine::ListAudioDevices()
6765
return deviceList;
6866
}
6967

70-
void AudioEngine::SetListener(const Math::Vector3& vector)
68+
void AudioEngine::SwitchAudioDevice(const std::string& deviceName)
7169
{
72-
alListener3f(0, vector.X, vector.Y, vector.Z);
73-
}
70+
this->~AudioEngine();
7471

75-
bool AudioEngine::HasEAX2Support() const noexcept
76-
{
77-
return _hasEAX2support;
72+
_audioDevice = alcOpenDevice(deviceName.c_str());
73+
if (!_audioDevice)
74+
{
75+
throw Exception("Audio device initialization failed! " + deviceName + " was specified.");
76+
}
77+
78+
_initializeContext();
7879
}
7980

8081
AudioEngine::~AudioEngine()
@@ -87,9 +88,39 @@ AudioEngine::~AudioEngine()
8788
alcCloseDevice(device);
8889
}
8990

90-
void AudioEngine::Update()
91+
void AudioEngine::Update() const noexcept
9192
{
92-
//alcProcessContext(static_cast<ALCcontext*>(_audioContext));
93+
if(this->Listener.Enabled)
94+
{
95+
96+
alListenerf(AL_GAIN, this->Listener.Volume);
97+
98+
alListener3f(
99+
AL_POSITION,
100+
this->Listener.Position.X,
101+
this->Listener.Position.Y,
102+
this->Listener.Position.Z
103+
);
104+
105+
alListener3f(
106+
AL_VELOCITY,
107+
this->Listener.Velocity.X,
108+
this->Listener.Velocity.Y,
109+
this->Listener.Velocity.Z
110+
);
111+
112+
float orientation[6] =
113+
{
114+
this->Listener.Direction.X,
115+
this->Listener.Direction.Y,
116+
this->Listener.Direction.Z,
117+
this->Listener.Normal.X,
118+
this->Listener.Normal.Y,
119+
this->Listener.Normal.Z,
120+
};
121+
122+
alListenerfv(AL_ORIENTATION, orientation);
123+
}
93124
}
94125

95126
std::optional<AudioError> AudioEngine::CheckErrors()

3DRadSpace/Engine3DRadSpace/Audio/AudioEngine.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22
#include "AudioError.hpp"
33
#include "../Core/Libs.hpp"
4-
#include "../Math/Vector3.hpp"
4+
#include "Listener.hpp"
55

66
namespace Engine3DRadSpace::Audio
77
{
@@ -29,16 +29,17 @@ namespace Engine3DRadSpace::Audio
2929
AudioEngine& operator=(const AudioEngine&) = delete;
3030
AudioEngine& operator=(AudioEngine&&) = delete;
3131

32+
class Listener Listener;
33+
3234
static std::vector<std::string> ListAudioDevices();
3335

34-
void SetListener(const Math::Vector3& vector);
36+
void SwitchAudioDevice(const std::string& deviceName);
3537

3638
bool HasEAX2Support() const noexcept;
3739

3840
~AudioEngine();
3941

40-
// Inherited via IUpdateable
41-
void Update();
42+
void Update() const noexcept;
4243

4344
std::optional<AudioError> CheckErrors();
4445
};
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
#include "../Math/Vector3.hpp"
3+
4+
namespace Engine3DRadSpace::Audio
5+
{
6+
struct Listener
7+
{
8+
float Volume = 1.0f;
9+
Math::Vector3 Position = Math::Vector3::Zero();
10+
Math::Vector3 Velocity = Math::Vector3::Zero();
11+
12+
Math::Vector3 Direction = Math::Vector3::UnitZ();
13+
Math::Vector3 Normal = Math::Vector3::UnitY();
14+
15+
bool Enabled = true;
16+
};
17+
}

3DRadSpace/Engine3DRadSpace/Audio/Sound.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Sound::Sound(AudioEngine *audio, const std::filesystem::path& path) :
3131
_sound(std::move(_attemptLoading(path)))
3232
{
3333
//Generate OpenAL sound buffer
34-
alGenBuffers(1, &_bufferID); //Create one buffer
34+
alGenBuffers(1, &_bufferID); //Create one buffer
3535
alBufferData(_bufferID, _sound._format, _sound._buffer.get(), _sound._size, _sound._sampleRate); //Set buffer.
3636
if(audio->CheckErrors().has_value()) throw Exception("Failed to copy OpenAL buffer!");
3737
}

0 commit comments

Comments
 (0)