aboutsummaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/linux.c64
1 files changed, 50 insertions, 14 deletions
diff --git a/platform/linux.c b/platform/linux.c
index 78e74aa..da8d64c 100644
--- a/platform/linux.c
+++ b/platform/linux.c
@@ -26,6 +26,17 @@ static bool running = true;
static Display *display;
static int xi_opcode;
+#define AUDIO_CACHE_INITIAL 10
+
+struct mixer_cache {
+ Mix_Chunk *chunk;
+ unsigned char *buffer;
+};
+static struct mixer_cache *cached_chunks = NULL;
+static unsigned int cached_len = 0;
+/* TODO: Add a limit to the capacity? Do we panic if it's hit? */
+static unsigned int cached_capacity = AUDIO_CACHE_INITIAL;
+
bool sound_init(float volume)
{
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
@@ -33,34 +44,59 @@ bool sound_init(float volume)
return false;
}
- if (Mix_OpenAudio(MIXER_FREQ, MIXER_FORMAT, MIXER_CHANNELS, MIXER_CHUNKSIZE)) {
+ if (Mix_OpenAudio(MIXER_FREQ, MIXER_FORMAT, MIXER_CHANNELS, MIXER_CHUNKSIZE) < 0) {
printf("ERROR: SDL mixer audio device open fail.\n");
return false;
}
+ if ((cached_chunks = malloc(AUDIO_CACHE_INITIAL * sizeof(struct mixer_cache))) == NULL) {
+ printf("ERROR: Could not allocate for audio cache.\n");
+ return false;
+ }
+
Mix_Volume(-1, volume * MIX_MAX_VOLUME); // set for all channels
return true;
}
-// TODO: get rid of this with proper cache thing - only supports 1 sound for now
-static Mix_Chunk *loaded_chunk = NULL;
+/* Find sample in cache, otherwise load into it */
+static Mix_Chunk *sound_cached(unsigned char *buffer, unsigned int buffer_len) {
+ /* Linear scan for now */
+ for (unsigned int i = 0; i < cached_len; ++i) {
+ struct mixer_cache cached = cached_chunks[i];
+ if (cached.buffer == buffer)
+ return cached.chunk;
+ }
+
+ /* Not in cache; grow if required as well */
+ if (cached_len >= cached_capacity) {
+ cached_capacity += 10;
+ if ((cached_chunks = realloc(cached_chunks, cached_capacity * sizeof(struct mixer_cache))) == NULL) {
+ printf("ERROR: Could not allocate for audio cache!\n");
+ return NULL;
+ }
+ }
+
+ SDL_RWops *sample_rw = SDL_RWFromMem(buffer, buffer_len);
+ Mix_Chunk *chunk = Mix_LoadWAV_RW(sample_rw, 1);
+ if (chunk == NULL) {
+ printf("ERROR: Audio sample could not be loaded - %s\n", Mix_GetError());
+ return NULL;
+ }
+
+ cached_chunks[cached_len++] = (struct mixer_cache){ .chunk = chunk, .buffer = buffer };
+ return chunk;
+}
void sound_play(unsigned char *buffer, unsigned int buffer_len)
{
- /* Load sample into SDL memory thing then into the mixer */
- // TODO: Cache these samples as loaded into SDL
- if (loaded_chunk == NULL) {
- SDL_RWops *sample_rw = SDL_RWFromMem(buffer, buffer_len);
- loaded_chunk = Mix_LoadWAV_RW(sample_rw, 1);
- if (loaded_chunk == NULL) {
- printf("ERROR: Sample load fail - %s\n", Mix_GetError());
- running = false;
- return;
- }
+ Mix_Chunk *chunk = sound_cached(buffer, buffer_len);
+ if (chunk == NULL) {
+ running = false;
+ return;
}
/* -1 means not-in-use channel */
- Mix_PlayChannel(-1, loaded_chunk, 0);
+ Mix_PlayChannel(-1, chunk, 0);
}
/*