comparison src/libmlk-core/core/sys.c @ 379:67c1c46af2c8

core: replace SDL2_mixer with OpenAL, closes #2528 @3h
author David Demelier <markand@malikania.fr>
date Wed, 05 Jan 2022 12:45:17 +0100
parents 460c78706989
children 31e2f6d35c34
comparison
equal deleted inserted replaced
378:460c78706989 379:67c1c46af2c8
18 18
19 #include "config.h" 19 #include "config.h"
20 20
21 #include <sys/stat.h> 21 #include <sys/stat.h>
22 #include <assert.h> 22 #include <assert.h>
23 #include <errno.h>
23 #include <stdio.h> 24 #include <stdio.h>
24 #include <stdlib.h> 25 #include <stdlib.h>
26 #include <string.h>
25 #include <limits.h> 27 #include <limits.h>
26 28
27 #if defined(_WIN32) 29 #if defined(_WIN32)
28 # include <shlwapi.h> 30 # include <shlwapi.h>
29 # include <windows.h> 31 # include <windows.h>
32 # include <string.h> 34 # include <string.h>
33 #endif 35 #endif
34 36
35 #include <SDL.h> 37 #include <SDL.h>
36 #include <SDL_image.h> 38 #include <SDL_image.h>
37 #include <SDL_mixer.h>
38 #include <SDL_ttf.h> 39 #include <SDL_ttf.h>
39 40
41 #include <sndfile.h>
42
40 #include <port/port.h> 43 #include <port/port.h>
41 44
45 #include "alloc.h"
42 #include "error.h" 46 #include "error.h"
47 #include "panic.h"
43 #include "sound.h" 48 #include "sound.h"
44 #include "sys.h" 49 #include "sys.h"
50 #include "sys_p.h"
51
52 ALCdevice *audio_dev = NULL;
53 ALCcontext *audio_ctx = NULL;
45 54
46 static struct { 55 static struct {
47 char organization[128]; 56 char organization[128];
48 char name[128]; 57 char name[128];
49 } info = { 58 } info = {
190 port_strlcpy(paths.localedir, system_directory(MLK_LOCALEDIR), sizeof (paths.localedir)); 199 port_strlcpy(paths.localedir, system_directory(MLK_LOCALEDIR), sizeof (paths.localedir));
191 200
192 port_strlcpy(info.organization, organization, sizeof (info.organization)); 201 port_strlcpy(info.organization, organization, sizeof (info.organization));
193 port_strlcpy(info.name, name, sizeof (info.name)); 202 port_strlcpy(info.name, name, sizeof (info.name));
194 203
204 /* SDL2. */
195 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) 205 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
196 return errorf("%s", SDL_GetError()); 206 return errorf("%s", SDL_GetError());
197 if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) 207 if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG)
198 return errorf("%s", SDL_GetError()); 208 return errorf("%s", SDL_GetError());
199 if (TTF_Init() < 0) 209 if (TTF_Init() < 0)
200 return errorf("%s", SDL_GetError()); 210 return errorf("%s", SDL_GetError());
201 if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) 211
202 return errorf("%s", SDL_GetError()); 212 /* OpenAL. */
203 if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) < 0) 213 if (!(audio_dev = alcOpenDevice(NULL)))
204 return errorf("%s", SDL_GetError()); 214 return errorf("unable to create audio device");
205 215 if (!(audio_ctx = alcCreateContext(audio_dev, NULL)))
206 Mix_AllocateChannels(SOUND_CHANNELS_MAX); 216 return errorf("unable to create audio context");
217
218 alcMakeContextCurrent(audio_ctx);
207 219
208 return 0; 220 return 0;
209 } 221 }
210 222
211 const char * 223 const char *
257 } 269 }
258 270
259 void 271 void
260 sys_finish(void) 272 sys_finish(void)
261 { 273 {
262 Mix_Quit();
263 TTF_Quit(); 274 TTF_Quit();
264 IMG_Quit(); 275 IMG_Quit();
265 SDL_Quit(); 276 SDL_Quit();
266 } 277
278 alcMakeContextCurrent(NULL);
279
280 if (audio_ctx) {
281 alcDestroyContext(audio_ctx);
282 audio_ctx = NULL;
283 }
284 if (audio_dev) {
285 alcCloseDevice(audio_dev);
286 audio_dev = NULL;
287 }
288 }
289
290 struct audiostream *
291 audiostream_create(SNDFILE *file, const SF_INFO *info)
292 {
293 struct audiostream *stream;
294
295 stream = alloc_new(sizeof (*stream));
296 stream->samplerate = info->samplerate;
297 stream->samplesz = info->frames * info->channels;
298 stream->samples = alloc_array(stream->samplesz, sizeof (*stream->samples));
299 stream->format = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
300
301 if (sf_read_short(file, stream->samples, stream->samplesz) != stream->samplesz) {
302 free(stream->samples);
303 free(stream);
304 stream = NULL;
305 }
306
307 alGenBuffers(1, &stream->buffer);
308 alBufferData(stream->buffer, stream->format, stream->samples,
309 stream->samplesz * sizeof (ALushort), stream->samplerate);
310 alGenSources(1, &stream->source);
311 alSourcei(stream->source, AL_BUFFER, stream->buffer);
312
313 sf_close(file);
314
315 return stream;
316 }
317
318 struct audiostream *
319 audiostream_open(const char *path)
320 {
321 assert(path);
322
323 SF_INFO info;
324 SNDFILE *file;
325
326 if (!(file = sf_open(path, SFM_READ, &info)))
327 return NULL;
328
329 return audiostream_create(file, &info);
330 }
331
332 struct viodata {
333 const unsigned char *data;
334 const size_t datasz;
335 sf_count_t offset;
336 };
337
338 static sf_count_t
339 vio_get_filelen(void *data)
340 {
341 const struct viodata *vio = data;
342
343 return (sf_count_t)vio->datasz;
344 }
345
346 static sf_count_t
347 vio_seek(sf_count_t offset, int whence, void *data)
348 {
349 struct viodata *vio = data;
350
351 switch (whence) {
352 case SEEK_SET:
353 vio->offset = offset;
354 break;
355 case SEEK_CUR:
356 vio->offset += offset;
357 break;
358 case SEEK_END:
359 vio->offset = vio->datasz - offset;
360 break;
361 default:
362 break;
363 }
364
365 return vio->offset;
366 }
367
368 static sf_count_t
369 vio_read(void *ptr, sf_count_t count, void *data)
370 {
371 struct viodata *vio = data;
372
373 memcpy(ptr, vio->data + vio->offset, count);
374 vio->offset += count;
375
376 return count;
377 }
378
379 static sf_count_t
380 vio_tell(void *data)
381 {
382 const struct viodata *vio = data;
383
384 return vio->offset;
385 }
386
387 struct audiostream *
388 audiostream_openmem(const void *data, size_t datasz)
389 {
390 assert(data);
391
392 SF_VIRTUAL_IO io = {
393 .get_filelen = vio_get_filelen,
394 .seek = vio_seek,
395 .read = vio_read,
396 .tell = vio_tell
397 };
398 SF_INFO info;
399 SNDFILE *file;
400 struct viodata viodata = {
401 .data = data,
402 .datasz = datasz,
403 };
404
405 if (!(file = sf_open_virtual(&io, SFM_READ, &info, &viodata)))
406 return NULL;
407
408 return audiostream_create(file, &info);
409 }
410
411 void
412 audiostream_finish(struct audiostream *s)
413 {
414 assert(s);
415
416 alDeleteBuffers(1, &s->buffer);
417 alSourcei(s->source, AL_BUFFER, 0);
418 alDeleteSources(1, &s->source);
419 }