-
Notifications
You must be signed in to change notification settings - Fork 78
/
Copy pathAudio_SDL.cpp
221 lines (186 loc) · 5.29 KB
/
Audio_SDL.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include "Audio_SDL.hpp"
#include "../Shared/D2HashMap.hpp"
#include "FileSystem.hpp"
#include "Logging.hpp"
namespace Audio_SDL
{
static HashMap<char, AudioChunk, 128, MAX_D2PATH> gpSoundCache;
// Start up the audio subsystem
void Init(OpenD2ConfigStrc* pConfig)
{
// We don't need anything other than WAV support.
// However, if we wanted to support MP3 or OGG, we could use Mix_Init here.
// Init the audio subsystem of SDL if it wasn't already
if (!(SDL_WasInit(0) & SDL_INIT_AUDIO))
{
SDL_InitSubSystem(SDL_INIT_AUDIO);
}
// Determine the proper audio device from commandline arguments (or from what is supported)
Log::Print(OpenD2LogFlags::PRIORITY_SYSTEMINFO, "SDL_Mixer init...\n");
Log::Print(OpenD2LogFlags::PRIORITY_SYSTEMINFO, "Enumerate audio devices:\n");
for (DWORD i = 0; i < SDL_GetNumAudioDevices(false); i++)
{
const char* szDeviceName = SDL_GetAudioDeviceName(i, false);
Log::Print(OpenD2LogFlags::PRIORITY_SYSTEMINFO, "Device %d: %s\n", i, szDeviceName);
}
if (pConfig->dwAudioDevice > SDL_GetNumAudioDevices(false))
{
pConfig->dwAudioDevice = 0;
}
Log_WarnAssertVoidReturn(SDL_GetNumAudioDevices(false) >= pConfig->dwAudioDevice);
Log::Print(OpenD2LogFlags::PRIORITY_MESSAGE, "Output Device: %s\n", SDL_GetAudioDeviceName(pConfig->dwAudioDevice, false));
int result = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024);
//int result = Mix_OpenAudioDevice(44100, MIX_DEFAULT_FORMAT, pConfig->dwAudioChannels, 1024, SDL_GetAudioDeviceName(pConfig->dwAudioDevice, false), SDL_AUDIO_ALLOW_CHANNELS_CHANGE);
if (result == -1)
{
Log::Warning(__FILE__, __LINE__, "Could not open audio device.");
return;
}
}
// Shut down the audio subsystem
void Shutdown()
{
// Free the sound cache
FlushAudioData();
// We don't need anything other than WAV support.
// However, if we wanted to support MP3 or OGG, we could use Mix_Quit here.
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
// Load a WAV into memory
bool LoadWAV(char* szAudioPath, BYTE** ppWavOutput, DWORD& dwSizeBytes)
{
// Find the file and determine how big it should be
fs_handle f;
dwSizeBytes = FS::Open(szAudioPath, &f, FS_READ, true);
if (f == INVALID_HANDLE)
{
return false;
}
if (dwSizeBytes == 0)
{
FS::CloseFile(f);
}
// allocate memory for it
*ppWavOutput = (BYTE*)malloc(dwSizeBytes);
if (!(*ppWavOutput))
{
return false;
}
FS::Read(f, *ppWavOutput, dwSizeBytes);
FS::CloseFile(f);
return true;
}
// Register a sound effect for playing
sfx_handle RegisterSound(char* szAudioPath)
{
bool bAlreadyAvailable = false;
sfx_handle ourHandle = gpSoundCache.NextFree(szAudioPath, bAlreadyAvailable);
if (ourHandle == INVALID_HANDLE)
{
Log::Warning(__FILE__, __LINE__, "Ran out of free sound space.");
return ourHandle;
}
if (bAlreadyAvailable)
{
return ourHandle;
}
BYTE* pWavData = nullptr;
DWORD dwWavSize = 0;
if (!LoadWAV(szAudioPath, &pWavData, dwWavSize))
{
Log::Print(OpenD2LogFlags::PRIORITY_MESSAGE, "Failed to load %s", szAudioPath);
return INVALID_HANDLE;
}
SDL_RWops* sdlFile = SDL_RWFromMem(pWavData, dwWavSize);
Log_WarnAssert(sdlFile);
gpSoundCache[ourHandle].bIsMusic = false;
gpSoundCache[ourHandle].data.pChunk = Mix_LoadWAV_RW(sdlFile, true);
return ourHandle;
}
// Register a music effect for playing
mus_handle RegisterMusic(char* szAudioPath)
{
bool bAlreadyPresent = false;
mus_handle ourHandle = gpSoundCache.NextFree(szAudioPath, bAlreadyPresent);
if (ourHandle == INVALID_HANDLE)
{
Log::Warning(__FILE__, __LINE__, "Ran out of free sound space.");
return ourHandle;
}
if(bAlreadyPresent)
{
// Found what was already existing
return ourHandle;
}
BYTE* pWavData = nullptr;
DWORD dwWavSize = 0;
if (!LoadWAV(szAudioPath, &pWavData, dwWavSize))
{
Log::Print(OpenD2LogFlags::PRIORITY_MESSAGE, "Failed to load %s", szAudioPath);
return INVALID_HANDLE;
}
SDL_RWops* sdlFile = SDL_RWFromMem(pWavData, dwWavSize);
Log_WarnAssert(sdlFile);
gpSoundCache[ourHandle].bIsMusic = true;
gpSoundCache[ourHandle].data.pMusic = Mix_LoadMUS_RW(sdlFile, true);
return ourHandle;
}
// Flush out all the audio data. Should be done when loading a new act.
void FlushAudioData()
{
gpSoundCache = HashMap<char, AudioChunk, 128, MAX_D2PATH>();
}
// Play a sound
void PlaySound(sfx_handle handle, int loops)
{
if (handle == INVALID_HANDLE || handle >= MAX_SDL_SOUNDFILES)
{
return;
}
if (gpSoundCache[handle].bIsMusic)
{
// is actually music
return;
}
Mix_PlayChannel(-1, gpSoundCache[handle].data.pChunk, 0);
}
// Play music
void PlayMusic(mus_handle handle, int loops)
{
if (handle == INVALID_HANDLE || handle >= MAX_SDL_SOUNDFILES)
{
return;
}
if (!gpSoundCache[handle].bIsMusic)
{ // is not actually music
return;
}
Mix_PlayMusic(gpSoundCache[handle].data.pMusic, loops);
}
void PauseAudio()
{
Mix_Pause(-1);
Mix_PauseMusic();
}
void ResumeAudio()
{
Mix_Resume(-1);
Mix_ResumeMusic();
}
// Change the master volume
void SetMasterVolume(float volume)
{
SetMusicVolume(volume);
SetSoundVolume(volume);
}
// Change the music volume
void SetMusicVolume(float volume)
{
Mix_VolumeMusic(volume);
}
// Change the sound volume
void SetSoundVolume(float volume)
{
Mix_Volume(-1, volume);
}
}