diff src/system_sdl.c @ 24:4c9dbfa30a66

Implemented audio
author Michael Pavone <pavone@retrodev.com>
date Thu, 31 Mar 2016 00:07:37 -0700
parents 41ec033ef8c3
children c677507682e3
line wrap: on
line diff
--- a/src/system_sdl.c	Wed Mar 30 20:31:04 2016 -0700
+++ b/src/system_sdl.c	Thu Mar 31 00:07:37 2016 -0700
@@ -3,13 +3,75 @@
 #include <stdlib.h>
 
 
-SDL_Window   *window;
-SDL_Renderer *renderer;
-SDL_Texture  *texture;
+static SDL_Window   *window;
+static SDL_Renderer *renderer;
+static SDL_Texture  *texture;
+static int sample_rate;
+static int buffer_size;
+static uint8_t quitting;
+
+static SDL_mutex * audio_mutex;
+static SDL_cond * source_ready;
+static SDL_cond * output_ready;
+static int16_t *source_buffer;
 
-int system_init(int width, int height)
+static void audio_callback(void * userdata, uint8_t *stream, int len)
+{
+	uint8_t local_quit;
+	int16_t *local_source;
+	SDL_LockMutex(audio_mutex);
+		local_source = NULL;
+		do {
+			if (!local_source) {
+				local_source = source_buffer;
+				source_buffer = NULL;
+				SDL_CondSignal(output_ready);
+			}
+			if (!quitting && !local_source) {
+				SDL_CondWait(source_ready, audio_mutex);
+			}
+		} while (!quitting && !local_source);
+		local_quit = quitting;
+	SDL_UnlockMutex(audio_mutex);
+	if (!local_quit) {
+		fflush(stdout);
+		memcpy(stream, local_source, len);
+	}
+}
+
+static void close_audio()
 {
-	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+	SDL_LockMutex(audio_mutex);
+		quitting = 1;
+		SDL_CondSignal(source_ready);
+	SDL_UnlockMutex(audio_mutex);
+	SDL_CloseAudio();
+}
+
+void system_present_audio(int16_t *buffer)
+{
+	SDL_LockMutex(audio_mutex);
+		while (source_buffer) {
+			SDL_CondWait(output_ready, audio_mutex);
+		}
+		source_buffer = buffer;
+		SDL_CondSignal(source_ready);
+	SDL_UnlockMutex(audio_mutex);
+}
+
+int system_sample_rate()
+{
+	return sample_rate;
+}
+
+int system_buffer_size()
+{
+	return buffer_size;
+}
+
+int system_init(int width, int height, int desired_sample_rate)
+{
+	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
 		fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError());
 		return 0;
 	}
@@ -23,20 +85,46 @@
 	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
 	if (!renderer) {
 		fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError());
-		return 0;
+		goto renderer_error;
 	}
 	
 	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB444, SDL_TEXTUREACCESS_STREAMING, 320, 240);
 	if (!texture) {
 		fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError());
-		SDL_DestroyRenderer(renderer);
-		SDL_DestroyWindow(window);
-		return 0;
+		goto error;
 	}
+	
+	audio_mutex = SDL_CreateMutex();
+	source_ready = SDL_CreateCond();
+	output_ready = SDL_CreateCond();
+	
+	SDL_AudioSpec desired, actual;
+	desired.freq = desired_sample_rate;
+	desired.format = AUDIO_S16SYS;
+	desired.channels = 1;
+	desired.callback = audio_callback;
+	desired.userdata = NULL;
+	desired.samples = 512;
+	
+	if (SDL_OpenAudio(&desired, &actual) < 0) {
+		fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError());
+		goto error;
+	}
+	printf("Initialized audio at frequency %d with a %d sample buffer and %d channels\n", actual.freq, actual.samples, actual.channels);
+	sample_rate = actual.freq;
+	buffer_size = actual.samples;
+	atexit(close_audio);
+	SDL_PauseAudio(0);
+	
 	return 1;
+	
+error:
+	SDL_DestroyRenderer(renderer);
+renderer_error:
+	SDL_DestroyWindow(window);
+	return 0;
 }
 
-//Should be called once per frame to get a pointer to the output buffer at the start of rendering
 uint16_t *system_get_framebuffer(int *pitch)
 {
 	void *pixels;
@@ -47,8 +135,6 @@
 	return pixels;
 }
 
-//Should be called once per frame at the competion of rendering
-//The pointer returned by system_get_framebuffer should be discarded after calling this function
 void system_framebuffer_updated()
 {
 	SDL_UnlockTexture(texture);