comparison 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
comparison
equal deleted inserted replaced
23:a085f17b79e9 24:4c9dbfa30a66
1 #include <SDL.h> 1 #include <SDL.h>
2 #include <stdint.h> 2 #include <stdint.h>
3 #include <stdlib.h> 3 #include <stdlib.h>
4 4
5 5
6 SDL_Window *window; 6 static SDL_Window *window;
7 SDL_Renderer *renderer; 7 static SDL_Renderer *renderer;
8 SDL_Texture *texture; 8 static SDL_Texture *texture;
9 static int sample_rate;
10 static int buffer_size;
11 static uint8_t quitting;
9 12
10 int system_init(int width, int height) 13 static SDL_mutex * audio_mutex;
14 static SDL_cond * source_ready;
15 static SDL_cond * output_ready;
16 static int16_t *source_buffer;
17
18 static void audio_callback(void * userdata, uint8_t *stream, int len)
11 { 19 {
12 if (SDL_Init(SDL_INIT_VIDEO) < 0) { 20 uint8_t local_quit;
21 int16_t *local_source;
22 SDL_LockMutex(audio_mutex);
23 local_source = NULL;
24 do {
25 if (!local_source) {
26 local_source = source_buffer;
27 source_buffer = NULL;
28 SDL_CondSignal(output_ready);
29 }
30 if (!quitting && !local_source) {
31 SDL_CondWait(source_ready, audio_mutex);
32 }
33 } while (!quitting && !local_source);
34 local_quit = quitting;
35 SDL_UnlockMutex(audio_mutex);
36 if (!local_quit) {
37 fflush(stdout);
38 memcpy(stream, local_source, len);
39 }
40 }
41
42 static void close_audio()
43 {
44 SDL_LockMutex(audio_mutex);
45 quitting = 1;
46 SDL_CondSignal(source_ready);
47 SDL_UnlockMutex(audio_mutex);
48 SDL_CloseAudio();
49 }
50
51 void system_present_audio(int16_t *buffer)
52 {
53 SDL_LockMutex(audio_mutex);
54 while (source_buffer) {
55 SDL_CondWait(output_ready, audio_mutex);
56 }
57 source_buffer = buffer;
58 SDL_CondSignal(source_ready);
59 SDL_UnlockMutex(audio_mutex);
60 }
61
62 int system_sample_rate()
63 {
64 return sample_rate;
65 }
66
67 int system_buffer_size()
68 {
69 return buffer_size;
70 }
71
72 int system_init(int width, int height, int desired_sample_rate)
73 {
74 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
13 fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError()); 75 fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError());
14 return 0; 76 return 0;
15 } 77 }
16 atexit(SDL_Quit); 78 atexit(SDL_Quit);
17 window = SDL_CreateWindow("simple16", 0, 0, width, height, 0); 79 window = SDL_CreateWindow("simple16", 0, 0, width, height, 0);
21 } 83 }
22 84
23 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); 85 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
24 if (!renderer) { 86 if (!renderer) {
25 fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError()); 87 fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError());
26 return 0; 88 goto renderer_error;
27 } 89 }
28 90
29 texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB444, SDL_TEXTUREACCESS_STREAMING, 320, 240); 91 texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB444, SDL_TEXTUREACCESS_STREAMING, 320, 240);
30 if (!texture) { 92 if (!texture) {
31 fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError()); 93 fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError());
32 SDL_DestroyRenderer(renderer); 94 goto error;
33 SDL_DestroyWindow(window);
34 return 0;
35 } 95 }
96
97 audio_mutex = SDL_CreateMutex();
98 source_ready = SDL_CreateCond();
99 output_ready = SDL_CreateCond();
100
101 SDL_AudioSpec desired, actual;
102 desired.freq = desired_sample_rate;
103 desired.format = AUDIO_S16SYS;
104 desired.channels = 1;
105 desired.callback = audio_callback;
106 desired.userdata = NULL;
107 desired.samples = 512;
108
109 if (SDL_OpenAudio(&desired, &actual) < 0) {
110 fprintf(stderr, "Failed to open audio: %s\n", SDL_GetError());
111 goto error;
112 }
113 printf("Initialized audio at frequency %d with a %d sample buffer and %d channels\n", actual.freq, actual.samples, actual.channels);
114 sample_rate = actual.freq;
115 buffer_size = actual.samples;
116 atexit(close_audio);
117 SDL_PauseAudio(0);
118
36 return 1; 119 return 1;
120
121 error:
122 SDL_DestroyRenderer(renderer);
123 renderer_error:
124 SDL_DestroyWindow(window);
125 return 0;
37 } 126 }
38 127
39 //Should be called once per frame to get a pointer to the output buffer at the start of rendering
40 uint16_t *system_get_framebuffer(int *pitch) 128 uint16_t *system_get_framebuffer(int *pitch)
41 { 129 {
42 void *pixels; 130 void *pixels;
43 if (SDL_LockTexture(texture, NULL, &pixels, pitch) < 0) { 131 if (SDL_LockTexture(texture, NULL, &pixels, pitch) < 0) {
44 fprintf(stderr, "Failed to lock texture: %s\n", SDL_GetError()); 132 fprintf(stderr, "Failed to lock texture: %s\n", SDL_GetError());
45 return NULL; 133 return NULL;
46 } 134 }
47 return pixels; 135 return pixels;
48 } 136 }
49 137
50 //Should be called once per frame at the competion of rendering
51 //The pointer returned by system_get_framebuffer should be discarded after calling this function
52 void system_framebuffer_updated() 138 void system_framebuffer_updated()
53 { 139 {
54 SDL_UnlockTexture(texture); 140 SDL_UnlockTexture(texture);
55 SDL_RenderCopy(renderer, texture, NULL, NULL); 141 SDL_RenderCopy(renderer, texture, NULL, NULL);
56 SDL_RenderPresent(renderer); 142 SDL_RenderPresent(renderer);