Mercurial > molko
diff 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 |
line wrap: on
line diff
--- a/src/libmlk-core/core/sys.c Sun Jan 02 10:22:48 2022 +0100 +++ b/src/libmlk-core/core/sys.c Wed Jan 05 12:45:17 2022 +0100 @@ -20,8 +20,10 @@ #include <sys/stat.h> #include <assert.h> +#include <errno.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <limits.h> #if defined(_WIN32) @@ -34,14 +36,21 @@ #include <SDL.h> #include <SDL_image.h> -#include <SDL_mixer.h> #include <SDL_ttf.h> +#include <sndfile.h> + #include <port/port.h> +#include "alloc.h" #include "error.h" +#include "panic.h" #include "sound.h" #include "sys.h" +#include "sys_p.h" + +ALCdevice *audio_dev = NULL; +ALCcontext *audio_ctx = NULL; static struct { char organization[128]; @@ -192,18 +201,21 @@ port_strlcpy(info.organization, organization, sizeof (info.organization)); port_strlcpy(info.name, name, sizeof (info.name)); + /* SDL2. */ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) return errorf("%s", SDL_GetError()); if (IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG) return errorf("%s", SDL_GetError()); if (TTF_Init() < 0) return errorf("%s", SDL_GetError()); - if (Mix_Init(MIX_INIT_OGG) != MIX_INIT_OGG) - return errorf("%s", SDL_GetError()); - if (Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) < 0) - return errorf("%s", SDL_GetError()); - Mix_AllocateChannels(SOUND_CHANNELS_MAX); + /* OpenAL. */ + if (!(audio_dev = alcOpenDevice(NULL))) + return errorf("unable to create audio device"); + if (!(audio_ctx = alcCreateContext(audio_dev, NULL))) + return errorf("unable to create audio context"); + + alcMakeContextCurrent(audio_ctx); return 0; } @@ -259,8 +271,149 @@ void sys_finish(void) { - Mix_Quit(); TTF_Quit(); IMG_Quit(); SDL_Quit(); + + alcMakeContextCurrent(NULL); + + if (audio_ctx) { + alcDestroyContext(audio_ctx); + audio_ctx = NULL; + } + if (audio_dev) { + alcCloseDevice(audio_dev); + audio_dev = NULL; + } } + +struct audiostream * +audiostream_create(SNDFILE *file, const SF_INFO *info) +{ + struct audiostream *stream; + + stream = alloc_new(sizeof (*stream)); + stream->samplerate = info->samplerate; + stream->samplesz = info->frames * info->channels; + stream->samples = alloc_array(stream->samplesz, sizeof (*stream->samples)); + stream->format = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; + + if (sf_read_short(file, stream->samples, stream->samplesz) != stream->samplesz) { + free(stream->samples); + free(stream); + stream = NULL; + } + + alGenBuffers(1, &stream->buffer); + alBufferData(stream->buffer, stream->format, stream->samples, + stream->samplesz * sizeof (ALushort), stream->samplerate); + alGenSources(1, &stream->source); + alSourcei(stream->source, AL_BUFFER, stream->buffer); + + sf_close(file); + + return stream; +} + +struct audiostream * +audiostream_open(const char *path) +{ + assert(path); + + SF_INFO info; + SNDFILE *file; + + if (!(file = sf_open(path, SFM_READ, &info))) + return NULL; + + return audiostream_create(file, &info); +} + +struct viodata { + const unsigned char *data; + const size_t datasz; + sf_count_t offset; +}; + +static sf_count_t +vio_get_filelen(void *data) +{ + const struct viodata *vio = data; + + return (sf_count_t)vio->datasz; +} + +static sf_count_t +vio_seek(sf_count_t offset, int whence, void *data) +{ + struct viodata *vio = data; + + switch (whence) { + case SEEK_SET: + vio->offset = offset; + break; + case SEEK_CUR: + vio->offset += offset; + break; + case SEEK_END: + vio->offset = vio->datasz - offset; + break; + default: + break; + } + + return vio->offset; +} + +static sf_count_t +vio_read(void *ptr, sf_count_t count, void *data) +{ + struct viodata *vio = data; + + memcpy(ptr, vio->data + vio->offset, count); + vio->offset += count; + + return count; +} + +static sf_count_t +vio_tell(void *data) +{ + const struct viodata *vio = data; + + return vio->offset; +} + +struct audiostream * +audiostream_openmem(const void *data, size_t datasz) +{ + assert(data); + + SF_VIRTUAL_IO io = { + .get_filelen = vio_get_filelen, + .seek = vio_seek, + .read = vio_read, + .tell = vio_tell + }; + SF_INFO info; + SNDFILE *file; + struct viodata viodata = { + .data = data, + .datasz = datasz, + }; + + if (!(file = sf_open_virtual(&io, SFM_READ, &info, &viodata))) + return NULL; + + return audiostream_create(file, &info); +} + +void +audiostream_finish(struct audiostream *s) +{ + assert(s); + + alDeleteBuffers(1, &s->buffer); + alSourcei(s->source, AL_BUFFER, 0); + alDeleteSources(1, &s->source); +}