diff options
| author | Nicholas Tay <nick@windblume.net> | 2022-05-30 21:33:19 +1000 | 
|---|---|---|
| committer | Nicholas Tay <nick@windblume.net> | 2022-05-30 21:33:19 +1000 | 
| commit | 7fe48a5a3f65c759adf7ff4b778bcf8a18334c7b (patch) | |
| tree | 7c22f39227ad2b0948b3661988f88e65d0cf1c1a /platform | |
| parent | 902a639a1ad85fe973190354b6da02ca3586b725 (diff) | |
| download | clak-7fe48a5a3f65c759adf7ff4b778bcf8a18334c7b.tar.gz clak-7fe48a5a3f65c759adf7ff4b778bcf8a18334c7b.tar.bz2 clak-7fe48a5a3f65c759adf7ff4b778bcf8a18334c7b.zip | |
Add a proper cache for Linux+SDL
Diffstat (limited to '')
| -rw-r--r-- | platform/linux.c | 64 | 
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);  }  /* | 
