Mercurial > repos > simple16
annotate 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 |
rev | line source |
---|---|
15 | 1 #include <SDL.h> |
2 #include <stdint.h> | |
16
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
3 #include <stdlib.h> |
15 | 4 |
5 | |
24 | 6 static SDL_Window *window; |
7 static SDL_Renderer *renderer; | |
8 static SDL_Texture *texture; | |
9 static int sample_rate; | |
10 static int buffer_size; | |
11 static uint8_t quitting; | |
12 | |
13 static SDL_mutex * audio_mutex; | |
14 static SDL_cond * source_ready; | |
15 static SDL_cond * output_ready; | |
16 static int16_t *source_buffer; | |
15 | 17 |
24 | 18 static void audio_callback(void * userdata, uint8_t *stream, int len) |
19 { | |
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() | |
15 | 43 { |
24 | 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) { | |
15 | 75 fprintf(stderr, "Failed to init SDL: %s\n", SDL_GetError()); |
76 return 0; | |
77 } | |
78 atexit(SDL_Quit); | |
17 | 79 window = SDL_CreateWindow("simple16", 0, 0, width, height, 0); |
80 if (!window) { | |
81 fprintf(stderr, "Failed to create window: %s\n", SDL_GetError()); | |
15 | 82 return 0; |
83 } | |
17 | 84 |
85 renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); | |
86 if (!renderer) { | |
87 fprintf(stderr, "Failed to create renderer: %s\n", SDL_GetError()); | |
24 | 88 goto renderer_error; |
17 | 89 } |
90 | |
15 | 91 texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB444, SDL_TEXTUREACCESS_STREAMING, 320, 240); |
92 if (!texture) { | |
93 fprintf(stderr, "Failed to create texture: %s\n", SDL_GetError()); | |
24 | 94 goto error; |
15 | 95 } |
24 | 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 | |
15 | 119 return 1; |
24 | 120 |
121 error: | |
122 SDL_DestroyRenderer(renderer); | |
123 renderer_error: | |
124 SDL_DestroyWindow(window); | |
125 return 0; | |
15 | 126 } |
127 | |
128 uint16_t *system_get_framebuffer(int *pitch) | |
129 { | |
130 void *pixels; | |
131 if (SDL_LockTexture(texture, NULL, &pixels, pitch) < 0) { | |
132 fprintf(stderr, "Failed to lock texture: %s\n", SDL_GetError()); | |
133 return NULL; | |
134 } | |
135 return pixels; | |
136 } | |
137 | |
138 void system_framebuffer_updated() | |
139 { | |
140 SDL_UnlockTexture(texture); | |
141 SDL_RenderCopy(renderer, texture, NULL, NULL); | |
142 SDL_RenderPresent(renderer); | |
143 } | |
144 | |
16
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
145 void system_poll_events() |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
146 { |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
147 SDL_Event event; |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
148 while(SDL_PollEvent(&event)) |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
149 { |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
150 switch (event.type) |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
151 { |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
152 case SDL_QUIT: |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
153 exit(0); |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
154 break; |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
155 } |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
156 } |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
157 } |
ae58e7c3c328
Poll events regularly to avoid unresponsive app warnings. Handle quit event
Michael Pavone <pavone@retrodev.com>
parents:
15
diff
changeset
|
158 |