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