Mercurial > repos > simple16
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);