1515#include < cmath>
1616#include < SDL/SDL.h>
1717
18+ #define MA_FILTER_NONE 0
19+ #define MA_FILTER_LINEAR 1 // recommended
20+ #define MA_FILTER_HIGH_QUALITY 2
21+
22+ #define MA_FILTER MA_FILTER_LINEAR
1823#define MA_FREQ 22050
19- #define MA_SAMPLES 1024
20- #define MA_LINEAR 1 // sample filtering: 0 - none, 1 - linear
24+ #define MA_SAMPLES 256
2125
2226struct ALCdevice
2327{
@@ -51,6 +55,7 @@ struct MA_Source
5155struct MA_Buffer
5256{
5357 std::vector<Sint16> samples;
58+ float pitch = 1 .f;
5459};
5560
5661static ALCdevice alcDevice;
@@ -65,54 +70,63 @@ static void ma_callback(void *userdata, Uint8 *stream, int len)
6570 (void )userdata;
6671 Sint16* stream16 = (Sint16*)stream;
6772 int len16 = len >> 1 ;
73+ if (floatBuff == 0 ) return ;
6874 floatBuff->resize (len16);
6975 std::fill (floatBuff->begin (), floatBuff->end (), 0 .f );
70- for ( auto & p : *sourceMap )
76+ if (sourceMap != 0 )
7177 {
72- MA_Source& src = p.second ;
73- if (src.playing )
78+ for (auto & p : *sourceMap)
7479 {
75- if (src.buffer != 0 )
80+ MA_Source& src = p.second ;
81+ if (src.playing )
7682 {
77- MA_Buffer& buff = (*bufferMap)[src.buffer ];
78- if (!buff.samples .empty ())
83+ if (src.buffer != 0 )
7984 {
80- for (int i = 0 ; i != len16; ++i)
85+ MA_Buffer& buff = (*bufferMap)[src.buffer ];
86+ if (!buff.samples .empty ())
8187 {
82- while (src.pos >= buff.samples .size ())
88+ const float pitch = src.pitch * buff.pitch ;
89+ for (int i = 0 ; i != len16; ++i)
8390 {
84- if (src.looping )
91+ while (src.pos >= buff. samples . size () )
8592 {
86- src.pos -= buff.samples .size ();
93+ if (src.looping )
94+ {
95+ src.pos -= buff.samples .size ();
96+ }
97+ else
98+ {
99+ src.pos = 0 ;
100+ src.playing = false ;
101+ }
87102 }
88- else
103+ if (!src.playing ) break ;
104+ #if MA_FILTER == MA_FILTER_NONE
105+ (*floatBuff)[i] += buff.samples [src.pos ] * src.gain ;
106+ #endif
107+ #if MA_FILTER == MA_FILTER_LINEAR
108+ uint32_t ipos0 = src.pos ;
109+ uint32_t ipos1 = ipos0 + 1 ;
110+ Sint16 smp0 = buff.samples [ipos0];
111+ Sint16 smp1 = 0 ;
112+ if (ipos1 >= buff.samples .size ())
89113 {
90- src.pos = 0 ;
91- src.playing = false ;
114+ if (src.looping )
115+ {
116+ smp1 = buff.samples [0 ];
117+ }
92118 }
93- }
94- if (!src.playing ) break ;
95- #if MA_LINEAR
96- uint32_t ipos0 = src.pos ;
97- uint32_t ipos1 = ipos0 + 1 ;
98- Sint16 smp0 = buff.samples [ipos0];
99- Sint16 smp1 = 0 ;
100- if (ipos1 >= buff.samples .size ())
101- {
102- if (src.looping )
119+ else
103120 {
104- smp1 = buff.samples [0 ];
121+ smp1 = buff.samples [ipos1 ];
105122 }
106- }
107- else
108- {
109- smp1 = buff.samples [ipos1];
110- }
111- (*floatBuff)[i] += (float (smp0) + (float (smp1) - float (smp0)) * (src.pos - ipos0)) * src.gain ;
112- #else
113- (*floatBuff)[i] += buff.samples [src.pos ] * src.gain ;
123+ (*floatBuff)[i] += (float (smp0) + (float (smp1) - float (smp0)) * (src.pos - ipos0)) * src.gain ;
124+ #endif
125+ #if MA_FILTER == MA_FILTER_HIGH_QUALITY
126+ #error "Hight quality audio filter is currently not implemented"
114127#endif
115- src.pos += src.pitch ;
128+ src.pos += pitch;
129+ }
116130 }
117131 }
118132 }
@@ -133,17 +147,29 @@ static void ma_callback(void *userdata, Uint8 *stream, int len)
133147
134148ALCboolean alcIsExtensionPresent (ALCdevice *device, const ALCchar *extname)
135149{
136- (void )device;
137- (void )extname;
138- return 1 ;
150+ if (device == 0 )
151+ {
152+ if (strcmp (extname, " ALC_ENUMERATE_ALL_EXT" ) == 0 )
153+ {
154+ return 1 ;
155+ }
156+ if (strcmp (extname, " ALC_ENUMERATION_EXT" ) == 0 )
157+ {
158+ return 1 ;
159+ }
160+ }
161+ return 0 ;
139162}
140163
141164const ALCchar* alcGetString (ALCdevice *device, ALCenum param)
142165{
143- (void )device;
144- (void )param;
145- static const ALCchar* ret = " \0\0 " ;
146- return ret;
166+ SDL_InitSubSystem (SDL_INIT_AUDIO);
167+ if (device == 0 && (param == ALC_ALL_DEVICES_SPECIFIER || param == ALC_DEVICE_SPECIFIER))
168+ {
169+ static const ALCchar* ret = " \0\0 " ;
170+ return ret;
171+ }
172+ return 0 ;
147173}
148174
149175ALCdevice* alcOpenDevice (const ALCchar *devicename)
@@ -153,7 +179,6 @@ ALCdevice* alcOpenDevice(const ALCchar *devicename)
153179 bufferMap = new std::map<ALuint, MA_Buffer>;
154180 floatBuff = new std::vector<float >;
155181 floatBuff->resize (MA_SAMPLES);
156- SDL_InitSubSystem (SDL_INIT_AUDIO);
157182 SDL_AudioSpec as;
158183 as.freq = MA_FREQ;
159184 as.format = AUDIO_S16;
@@ -190,8 +215,11 @@ ALCboolean alcCloseDevice(ALCdevice *device)
190215 (void )device;
191216 SDL_CloseAudio ();
192217 delete sourceMap;
218+ sourceMap = 0 ;
193219 delete bufferMap;
220+ bufferMap = 0 ;
194221 delete floatBuff;
222+ floatBuff = 0 ;
195223 return 1 ;
196224}
197225
@@ -223,46 +251,50 @@ void alGenBuffers(ALsizei n, ALuint *buffers)
223251 generateStuff (n, buffers, *bufferMap, bufferCounter);
224252}
225253
226- template <class T > void deleteStuff (ALsizei n, const ALuint* stuff, std::map<ALuint, T>& m)
254+ template <class T > void deleteStuff (ALsizei n, const ALuint* stuff, std::map<ALuint, T>* m)
227255{
256+ if (m == 0 )
257+ return ;
228258 SDL_LockAudio ();
229259 for (ALsizei i = 0 ; i != n; ++i)
230260 {
231- m. erase (stuff[i]);
261+ m-> erase (stuff[i]);
232262 }
233263 SDL_UnlockAudio ();
234264}
235265
236266void alDeleteSources (ALsizei n, const ALuint *sources)
237267{
238- deleteStuff (n, sources, * sourceMap);
268+ deleteStuff (n, sources, sourceMap);
239269}
240270
241271void alDeleteBuffers (ALsizei n, const ALuint *buffers)
242272{
243- deleteStuff (n, buffers, * bufferMap);
273+ deleteStuff (n, buffers, bufferMap);
244274}
245275
246276void alListenerfv (ALenum param, const ALfloat *values)
247277{
248278 (void )param;
249279 (void )values;
280+ // listener parameters have no effect
250281 return ;
251282}
252283
253284void alBufferData (ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
254285{
255- if (buffer == 0 || format != AL_FORMAT_MONO16 || freq != MA_FREQ ) return ; // only 22050 Hz, 16-bit mono audio is currently supported
286+ if (buffer == 0 || bufferMap == 0 || format != AL_FORMAT_MONO16 ) return ; // only 16-bit mono audio is currently supported
256287 SDL_LockAudio ();
257288 MA_Buffer& buff = (*bufferMap)[buffer];
289+ buff.pitch = float (freq)/float (MA_FREQ);
258290 buff.samples .resize (size >> 1 );
259291 std::copy ((Sint16*)data, ((Sint16*)data) + buff.samples .size (), buff.samples .begin ());
260292 SDL_UnlockAudio ();
261293}
262294
263295void alSourcef (ALuint source, ALenum param, ALfloat value)
264296{
265- if (source == 0 ) return ;
297+ if (source == 0 || sourceMap == 0 ) return ;
266298 SDL_LockAudio ();
267299 MA_Source& src = (*sourceMap)[source];
268300 switch (param)
@@ -294,7 +326,7 @@ void alSourcefv(ALuint source, ALenum param, const ALfloat *values)
294326
295327void alSourcei (ALuint source, ALenum param, ALint value)
296328{
297- if (source == 0 ) return ;
329+ if (source == 0 || sourceMap == 0 ) return ;
298330 SDL_LockAudio ();
299331 MA_Source& src = (*sourceMap)[source];
300332 switch (param)
@@ -311,7 +343,7 @@ void alSourcei(ALuint source, ALenum param, ALint value)
311343
312344void alSourcePlay (ALuint source)
313345{
314- if (source == 0 ) return ;
346+ if (source == 0 || sourceMap == 0 ) return ;
315347 SDL_LockAudio ();
316348 MA_Source& src = (*sourceMap)[source];
317349 src.playing = true ;
@@ -320,7 +352,7 @@ void alSourcePlay(ALuint source)
320352
321353void alSourceStop (ALuint source)
322354{
323- if (source == 0 ) return ;
355+ if (source == 0 || sourceMap == 0 ) return ;
324356 SDL_LockAudio ();
325357 MA_Source& src = (*sourceMap)[source];
326358 src.playing = false ;
@@ -329,7 +361,7 @@ void alSourceStop(ALuint source)
329361
330362void alSourceRewind (ALuint source)
331363{
332- if (source == 0 ) return ;
364+ if (source == 0 || sourceMap == 0 ) return ;
333365 SDL_LockAudio ();
334366 MA_Source& src = (*sourceMap)[source];
335367 src.pos = 0 ;
0 commit comments