Elevate Engine 1
Loading...
Searching...
No Matches
WwiseSoundEngine.cpp
Go to the documentation of this file.
1#ifdef EE_USES_WWISE
2
3#include <filesystem>
4
5#include "WwiseSoundEngine.h"
6
9
10#include <glm/vec3.hpp>
11
12// Sound Engine
13#include <AK/SoundEngine/Common/AkSoundEngine.h>
14#include <AK/SoundEngine/Common/AkMemoryMgr.h>
15#include <AK/SoundEngine/Common/IAkStreamMgr.h>
16#include <AK/SoundEngine/Common/AkMemoryMgrModule.h>
17
18// Spatial audio
19#include <AK/SpatialAudio/Common/AkSpatialAudio.h>
20#include <AK/Tools/Common/AkPlatformFuncs.h>
21
22// Wwise Communication
23#ifndef AK_OPTIMIZED // Keep the following header out in release mode
24#include <AK/Comm/AkCommunication.h>
25#endif // AK_OPTIMIZED
26
27// Decoders
28#if EE_AUDIO_VORBIS
29#include <AK/Plugin/AkVorbisDecoderFactory.h> // This is necessary to be able to play vorbis files
30#endif // EE_AUDIO_VORBIS
31#if EE_AUDIO_OPUS
32#include <AK/Plugin/AkOpusDecoderFactory.h> // This is necessary to be able to play opus files
33#endif // EE_AUDIO_OPUS
34
35// TODO REMOVE
36// For Wwise integration testing
37#define BANKNAME_INIT L"Init.bnk"
38
39namespace Elevate
40{
41 WwiseSoundEngine* WwiseSoundEngine::Get()
42 {
43 return static_cast<WwiseSoundEngine*>(SoundEngine::GetImpl());
44 }
45
46 bool WwiseSoundEngine::LoadBank(const wchar_t* bankName)
47 {
48 AkBankID bankID; // Not used
49 AKRESULT res = AK::SoundEngine::LoadBank(bankName, bankID);
50 bool success = res == AK_Success;
51
52 if (!success)
53 {
54 std::string nameAsStr = std::filesystem::path(bankName).string();
55 EE_CORE_CERROR(true, "ERROR: Failed to load SoundBank : {}", nameAsStr);
56 }
57 return success;
58 }
59 bool WwiseSoundEngine::LoadBank(const std::wstring& bankName)
60 {
61 return LoadBank(bankName.c_str());
62 }
63 bool WwiseSoundEngine::LoadBank(const char* bankName)
64 {
65 AkBankID bankID; // Not used
66 AKRESULT res = AK::SoundEngine::LoadBank(bankName, bankID);
67 bool success = res == AK_Success;
68 EE_CORE_CERROR(!success, "ERROR: Failed to load SoundBank : {}", bankName);
69 return success;
70 }
71 bool WwiseSoundEngine::LoadBank(std::string& bankName)
72 {
73 return LoadBank(bankName.c_str());
74 }
75
76 bool WwiseSoundEngine::InitImpl()
77 {
78 EE_CORE_INFO("Initializing Wwise Sound Engine...");
79
80 // Creating the memory manager
81 AkMemSettings memorySettings;
82 AK::MemoryMgr::GetDefaultSettings(memorySettings);
83 if (AK::MemoryMgr::Init(&memorySettings) != AK_Success)
84 {
85 EE_CORE_ASSERT(false, "ERROR: Failed to initialize the Wwise memory manager.");
86 return false;
87 }
88 else
89 {
90 EE_CORE_TRACE("Wwise memory manager initialized!");
91 }
92
93 // Creating the stream manager
94 AkStreamMgrSettings streamSettings;
95 AK::StreamMgr::GetDefaultSettings(streamSettings);
96 if (!AK::StreamMgr::Create(streamSettings))
97 {
98 EE_CORE_ASSERT(false, "ERROR: Failed to create the Wwise stream manager.");
99 return false;
100 }
101 else
102 {
103 EE_CORE_TRACE("Wwise stream manager initialized!");
104 }
105
106 // Creating a streaming device
107 AkDeviceSettings deviceSettings;
108 AK::StreamMgr::GetDefaultDeviceSettings(deviceSettings);
109
110 m_lowLevelIO = std::make_unique<CAkFilePackageLowLevelIODeferred>();
111 if (m_lowLevelIO->Init(deviceSettings) != AK_Success)
112 {
113 EE_CORE_ASSERT(false, "ERROR: Failed to create the Wwise streaming device and low-level I/O system.");
114 return false;
115 }
116 else
117 {
118 EE_CORE_TRACE("Wwise streaming device and low-level I/O initialized!");
119 }
120
121 // Initializing the sound engine itself
122 AkInitSettings initSettings;
123 AK::SoundEngine::GetDefaultInitSettings(initSettings);
124
125 AkPlatformInitSettings platformInitSettings;
126 AK::SoundEngine::GetDefaultPlatformInitSettings(platformInitSettings);
127
128 if (AK::SoundEngine::Init(&initSettings, &platformInitSettings) != AK_Success)
129 {
130 EE_CORE_ASSERT(false, "ERROR: Failded to initialize the Sound Engine.");
131 return false;
132 }
133 else
134 {
135 EE_CORE_TRACE("Wwise SoundEngine initialized!");
136 }
137
138 // Initializing the interactive music engine
139 AkSpatialAudioInitSettings spatialAudioSettings;
140 if (AK::SpatialAudio::Init(spatialAudioSettings) != AK_Success)
141 {
142 EE_CORE_ASSERT(false, "ERROR: Failded to initialize Spatial Audio.");
143 return false;
144 }
145 else
146 {
147 EE_CORE_TRACE("Wwise Spatial Audio initialized!");
148 }
149
150#ifndef AK_OPTIMIZED
151 AkCommSettings communicationSettings;
152 AK::Comm::GetDefaultInitSettings(communicationSettings);
153 if (AK::Comm::Init(communicationSettings) != AK_Success)
154 {
155 EE_CORE_ASSERT(false, "ERROR: Failded to initialize Wwise communication.");
156 return false;
157 }
158 else
159 {
160 EE_CORE_TRACE("Wwise communication initialized!");
161 }
162#endif // AK_OPTIMIZED
163
164 EE_CORE_INFO("Wwise Initialized!");
165
166 PrepareAudio();
167
168#ifdef EE_EDITOR_BUILD
169 // todo move to a setting somewhere
170 // this is our test impl to check and discover wwise elemetns from the file browser
171 std::string wwiseProjectPath = "./WwiseProject"; // todo get from the user
172 std::string rootOutputPath = wwiseProjectPath + "/GeneratedSoundBanks";
173 std::string currentPlatform = "Windows"; // todo set via macros
174
175 m_mergedDataSource.reset(new WwiseMergedDataSource(wwiseProjectPath, rootOutputPath, currentPlatform));
176 m_mergedDataSource->InitializeSource();
177
178 // todo add a check to check if we use waapi
179 WAAPIClient::Get(); // Simply force the creation of the instance.
180#endif
181
182 return true;
183 }
184
185 void WwiseSoundEngine::PrepareAudio()
186 {
187 m_lowLevelIO->SetBasePath(AKTEXT("./WwiseProject/GeneratedSoundBanks/Windows/"));
188 AK::StreamMgr::SetCurrentLanguage(AKTEXT("English(US)"));
189
190 LoadBank(BANKNAME_INIT);
191 LoadBank(L"Sandbox.bnk");
192 }
193
194 void WwiseSoundEngine::RenderAudioImpl()
195 {
196 AK::SoundEngine::RenderAudio();
197 }
198
199 void WwiseSoundEngine::TerminateImpl()
200 {
201#ifndef AK_OPTIMIZED
202 AK::Comm::Term();
203#endif // AK_OPTIMIZED
204
205 AK::SoundEngine::Term();
206
207 m_lowLevelIO->Term();
208
209 if (AK::IAkStreamMgr::Get())
210 {
211 AK::IAkStreamMgr::Get()->Destroy();
212 }
213
214 AK::MemoryMgr::Term();
215 }
216
217 void WwiseSoundEngine::WakeUpImpl()
218 {
219 // todo add the delay in ms option
220 AK::SoundEngine::WakeupFromSuspend();
221 AK::SoundEngine::RenderAudio();
222 }
223
224 void WwiseSoundEngine::SuspendImpl(bool renderAnyway, bool fadeOut)
225 {
226 AK::SoundEngine::Suspend(renderAnyway, fadeOut);
227 }
228
229 void WwiseSoundEngine::SetDefaultListenerImpl(GameObject* obj)
230 {
231 if (obj)
232 {
233 m_currentListenerID = obj->GetObjectId();
234 AK::SoundEngine::SetDefaultListeners(&m_currentListenerID, 1);
235 }
236 }
237
238 void WwiseSoundEngine::SetDistanceProbeImpl(GameObject* obj)
239 {
240 if (obj)
241 {
242 AK::SoundEngine::SetDistanceProbe(m_currentListenerID, obj->GetObjectId());
243 }
244 }
245
246 void WwiseSoundEngine::UnsetDistanceProbeImpl()
247 {
248 AK::SoundEngine::SetDistanceProbe(m_currentListenerID, m_currentListenerID);
249 }
250
251 void WwiseSoundEngine::RegisterGameObjectImpl(GameObject* obj)
252 {
253 if (obj)
254 {
255 AkGameObjectID id = obj->GetObjectId();
256 if (AK::SoundEngine::RegisterGameObj(id, obj->GetName().c_str()) != AK_Success)
257 {
258 EE_CORE_ERROR("SoundEngine Error : Unable to register gO => (name : {}), (id : {})", obj->GetObjectId(), obj->GetName().c_str());
259 }
260 else
261 {
262 EE_CORE_TRACE("SoundEngine registed gO => (name : {}), (id : {})", obj->GetObjectId(), obj->GetName().c_str());
263 }
264 }
265 }
266
267 void WwiseSoundEngine::UnregisterGameObjectImpl(GameObject* obj)
268 {
269 if (obj)
270 {
271 AkGameObjectID id = obj->GetObjectId();
272 AK::SoundEngine::UnregisterGameObj(id);
273 }
274 }
275
276 void WwiseSoundEngine::UpdateObjectPositionImpl(GameObject* obj)
277 {
278 if (obj)
279 {
280 const glm::vec3 objectPosition = obj->GetPosition();
281 AkGameObjectID id = obj->GetObjectId();
282
283 const Transform& transform = obj->GetTransform();
284 glm::vec3 top = glm::normalize(transform.GetUp());
285 glm::vec3 front = glm::normalize(transform.GetForward());
286
287 AkSoundPosition soundPosition;
288 soundPosition.SetPosition(objectPosition.x, objectPosition.y, objectPosition.z);
289 soundPosition.SetOrientation(front.x, front.y, front.z, top.x, top.y, top.z);
290
291 if (AK::SoundEngine::SetPosition(id, soundPosition) == AK_InvalidParameter)
292 {
293 EE_CORE_ERROR("SoundEngine Error : could not set the transform values for {} with values [{}, {}, {}]", obj->GetName(), objectPosition.x, objectPosition.y, objectPosition.z);
294 }
295 }
296 }
297
298 void WwiseSoundEngine::PostEventImpl(const char* eventName, GameObject* obj)
299 {
300 if (obj)
301 {
302 AkGameObjectID id = obj->GetObjectId();
303 AK::SoundEngine::PostEvent(eventName, id);
304 }
305 else
306 {
307 EE_CORE_ERROR("Error (WwiseSoundEngine::PostEventImpl) : Cannot play an event on a null GameObject.");
308 }
309 }
310
311 void WwiseSoundEngine::PostEventImpl(uint32_t eventId, GameObject* obj)
312 {
313 if (obj)
314 {
315 AkGameObjectID id = obj->GetObjectId();
316 AK::SoundEngine::PostEvent(eventId, id);
317 }
318 else
319 {
320 EE_CORE_ERROR("Error (WwiseSoundEngine::PostEventImpl) : Cannot play an event on a null GameObject.");
321 }
322 }
323
324 void WwiseSoundEngine::PostEventImpl(const char* eventName)
325 {
326 AK::SoundEngine::PostEvent(eventName, m_currentListenerID);
327 }
328
329 void WwiseSoundEngine::PostEventImpl(uint32_t eventId)
330 {
331 AK::SoundEngine::PostEvent(eventId, m_currentListenerID);
332 }
333
334#ifdef EE_EDITOR_BUILD
335 std::shared_ptr<WwiseDataSource> WwiseSoundEngine::GetDataSource()
336 {
337 return m_mergedDataSource;
338 }
339#endif
340}
341
342#endif // #ifdef EE_USES_WWISE
static SoundEngine * GetImpl()
static WAAPIClient & Get()
Definition WAAPIClient.h:21