Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Rubberduckycooly
GitHub Repository: Rubberduckycooly/RSDKv5-Decompilation
Path: blob/master/RSDKv5/RSDK/Audio/XAudio/XAudioDevice.cpp
1168 views
1
2
3
// allows generic string literal stuff
4
#include <tchar.h>
5
6
uint8 AudioDevice::contextInitialized;
7
8
IXAudio2 *AudioDevice::audioContext;
9
IXAudio2MasteringVoice *AudioDevice::masteringVoice;
10
IXAudio2SourceVoice *AudioDevice::sourceVoice;
11
AudioDeviceCallback AudioDevice::voiceCallback;
12
AudioEngineCallback AudioDevice::engineCallback;
13
14
RTL_CRITICAL_SECTION AudioDevice::criticalSection;
15
16
int32 AudioDevice::mixBufferID = 0;
17
float AudioDevice::mixBuffer[3][MIX_BUFFER_SIZE];
18
19
bool32 AudioDevice::Init()
20
{
21
if (!contextInitialized) {
22
contextInitialized = true;
23
InitAudioChannels();
24
25
CoInitializeEx(NULL, 0);
26
}
27
28
audioState = false;
29
if (!audioContext) {
30
if (SUCCEEDED(InitContext())) {
31
if (SUCCEEDED(audioContext->CreateMasteringVoice(&masteringVoice, 0, 0, 0, NULL, NULL))) {
32
WAVEFORMATEX format;
33
format.cbSize = 0;
34
format.wBitsPerSample = sizeof(SAMPLE_FORMAT) * 8;
35
format.nChannels = AUDIO_CHANNELS;
36
format.nBlockAlign = (format.nChannels * format.wBitsPerSample) / 8;
37
format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
38
format.nSamplesPerSec = AUDIO_FREQUENCY;
39
format.nAvgBytesPerSec = AUDIO_FREQUENCY * AUDIO_CHANNELS * sizeof(SAMPLE_FORMAT);
40
41
if (SUCCEEDED(audioContext->CreateSourceVoice(&sourceVoice, &format, 0, 2.0, &voiceCallback, NULL, NULL))) {
42
sourceVoice->Start(0, XAUDIO2_COMMIT_NOW);
43
InitMixBuffer();
44
audioState = true;
45
}
46
else {
47
#if RETRO_RENDERDEVICE_DIRECTX9 || RETRO_RENDERDEVICE_DIRECTX11
48
if (videoSettings.windowed) {
49
MessageBox(RenderDevice::windowHandle, _T("Unable to create source voice. Sound will not be available during this session."),
50
_T("AudioDevice::Init"), MB_OK);
51
}
52
#endif
53
}
54
}
55
else {
56
#if RETRO_RENDERDEVICE_DIRECTX9 || RETRO_RENDERDEVICE_DIRECTX11
57
if (videoSettings.windowed) {
58
MessageBox(RenderDevice::windowHandle, _T("Unable to create mastering voice. Sound will not be available during this session."),
59
_T("AudioDevice::Init"), MB_OK);
60
}
61
#endif
62
63
if (audioContext) {
64
audioContext->Release();
65
audioContext = NULL;
66
}
67
}
68
}
69
else {
70
#if RETRO_RENDERDEVICE_DIRECTX9 || RETRO_RENDERDEVICE_DIRECTX11
71
if (videoSettings.windowed) {
72
MessageBox(RenderDevice::windowHandle,
73
_T("Error Initializing XAudio2.\n"
74
"You may need to install the Jun 2010 DirectX update to have the XAudio Drivers.\n"
75
"Sound will not be available during this session."),
76
_T("AudioDevice::Init"), MB_OK);
77
}
78
#endif
79
}
80
}
81
82
return true;
83
}
84
85
void AudioDevice::Release()
86
{
87
if (sourceVoice)
88
sourceVoice->DestroyVoice();
89
if (masteringVoice)
90
masteringVoice->DestroyVoice();
91
if (audioContext)
92
audioContext->Release();
93
94
AudioDeviceBase::Release();
95
96
CoUninitialize();
97
DeleteCriticalSection(&AudioDevice::criticalSection);
98
}
99
100
void AudioDevice::FrameInit()
101
{
102
if (audioState > 2 && --audioState == 2) {
103
if (sourceVoice) {
104
sourceVoice->DestroyVoice();
105
sourceVoice = NULL;
106
}
107
108
if (masteringVoice) {
109
masteringVoice->DestroyVoice();
110
masteringVoice = NULL;
111
}
112
113
audioContext->StopEngine();
114
115
Sleep(1000);
116
117
if (audioContext)
118
audioContext->Release();
119
audioContext = NULL;
120
121
Init();
122
}
123
}
124
125
void AudioDevice::HandleStreamLoad(ChannelInfo *channel, bool32 async)
126
{
127
if (async) {
128
DWORD threadId;
129
HANDLE thread = CreateThread(NULL, 0, LoadStreamASync, channel, 0, &threadId);
130
CloseHandle(thread);
131
}
132
else {
133
LoadStream(channel);
134
}
135
}
136
137
HRESULT AudioDevice::InitContext()
138
{
139
IXAudio2 *context = nullptr;
140
141
HRESULT res = XAudio2Create(&context, 0, XAUDIO2_DEFAULT_PROCESSOR);
142
if (SUCCEEDED(res)) {
143
res = context->StartEngine();
144
if (FAILED(res))
145
context->Release();
146
else
147
audioContext = context;
148
}
149
150
return res;
151
}
152
153
void AudioDevice::InitAudioChannels()
154
{
155
InitializeCriticalSection(&AudioDevice::criticalSection);
156
157
AudioDeviceBase::InitAudioChannels();
158
}
159
160
void AudioDevice::InitMixBuffer()
161
{
162
void *mixBuffer = AudioDevice::mixBuffer[AudioDevice::mixBufferID];
163
164
XAUDIO2_BUFFER buffer;
165
memset(&buffer, 0, sizeof(buffer));
166
buffer.pAudioData = (BYTE *)mixBuffer;
167
buffer.pContext = 0;
168
buffer.AudioBytes = MIX_BUFFER_SIZE * sizeof(SAMPLE_FORMAT);
169
170
AudioDevice::mixBufferID = ((AudioDevice::mixBufferID) + 1) % 3;
171
172
AudioDevice::sourceVoice->SubmitSourceBuffer(&buffer, NULL);
173
AudioDevice::audioContext->RegisterForCallbacks(&engineCallback);
174
}
175
176
void AudioEngineCallback::OnCriticalError(HRESULT Error) { AudioDevice::audioState = 30; }
177
178
void AudioDeviceCallback::OnBufferEnd(void *pBufferContext)
179
{
180
XAUDIO2_VOICE_STATE state;
181
AudioDevice::sourceVoice->GetState(&state);
182
183
if (state.BuffersQueued < 2) {
184
void *mixBuffer = AudioDevice::mixBuffer[AudioDevice::mixBufferID];
185
186
LockAudioDevice();
187
AudioDevice::ProcessAudioMixing(mixBuffer, MIX_BUFFER_SIZE);
188
UnlockAudioDevice();
189
190
XAUDIO2_BUFFER buffer;
191
memset(&buffer, 0, sizeof(buffer));
192
buffer.pAudioData = (BYTE *)mixBuffer;
193
buffer.pContext = 0;
194
buffer.AudioBytes = MIX_BUFFER_SIZE * sizeof(SAMPLE_FORMAT);
195
196
AudioDevice::mixBufferID = ((AudioDevice::mixBufferID) + 1) % 3;
197
198
AudioDevice::sourceVoice->SubmitSourceBuffer(&buffer, NULL);
199
}
200
}
201