Mercurial > molko
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 } |