Rev 9288 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8210 | maxcodehac | 1 | #include "SDL_audio.h" |
9789 | turbocat | 2 | #include |
3 | #include |
||
8210 | maxcodehac | 4 | #include |
5 | #include |
||
6 | #include |
||
7 | #include |
||
8 | |||
9789 | turbocat | 9 | extern void SDL_printf(const char * fmt,...); |
8210 | maxcodehac | 10 | |
9789 | turbocat | 11 | #define AUDIO_THREAD_STACK_SIZE 40960 |
12 | |||
13 | static ksys_thread_t thread_info; |
||
14 | static int bInitialized = 0; |
||
15 | static SNDBUF hBuff = 0; |
||
16 | static uint8_t* data = NULL; |
||
17 | static int audio_tid = 0; |
||
8210 | maxcodehac | 18 | static int main_slot; |
9789 | turbocat | 19 | static uint32_t main_tid; |
20 | static char audio_thread_stack[AUDIO_THREAD_STACK_SIZE]; |
||
21 | static uint32_t used_format = 0; |
||
22 | static int mix_size = 0; |
||
8210 | maxcodehac | 23 | |
24 | static void (*callback)(void* userdata, Uint8* stream, int len); |
||
25 | static void* userdata; |
||
26 | |||
27 | int SDL_AudioInit(const char* driver_name) |
||
28 | { |
||
9789 | turbocat | 29 | if (bInitialized) { |
30 | SDL_SetError("Audio already initialized"); |
||
31 | return -1; |
||
32 | } |
||
33 | int ver; |
||
34 | if (InitSound(&ver)) { |
||
35 | SDL_printf("Warning: cannot load drivers, sound output will be disabled\n"); |
||
36 | return 0; |
||
37 | } |
||
38 | bInitialized = 1; |
||
39 | return 0; |
||
8210 | maxcodehac | 40 | } |
41 | |||
9789 | turbocat | 42 | void SDL_AudioQuit(void) {/*STUB*/} |
8210 | maxcodehac | 43 | |
44 | char* SDL_AudioDriverName(char* namebuf, int maxlen) |
||
45 | { |
||
9789 | turbocat | 46 | if (!bInitialized) |
47 | return NULL; |
||
48 | strncpy(namebuf,"KolibriAudio",maxlen); |
||
49 | return namebuf; |
||
8210 | maxcodehac | 50 | } |
51 | |||
52 | #define AUDIO_SUSPEND 1 |
||
53 | #define AUDIO_RESUME 2 |
||
54 | #define AUDIO_DIE 3 |
||
9789 | turbocat | 55 | |
56 | static volatile int audio_command=0, audio_response=0, bLocked=0, bInCallback=0; |
||
57 | |||
8210 | maxcodehac | 58 | static void audio_thread(void) |
59 | { |
||
9789 | turbocat | 60 | SDL_printf("Audio_thread created\n"); |
61 | int bPaused; |
||
62 | ksys_signal_info_t snd_signal; |
||
8210 | maxcodehac | 63 | // initialize |
9789 | turbocat | 64 | if (CreateBuffer(used_format|PCM_RING, 0, &hBuff)) { |
8210 | maxcodehac | 65 | audio_response=1; |
9789 | turbocat | 66 | exit(0); |
67 | } |
||
68 | |||
69 | GetBufferSize(hBuff, &mix_size); |
||
70 | SDL_printf("buffer created, size is %d\n", mix_size); |
||
71 | mix_size >>= 1; |
||
72 | data = malloc(mix_size); |
||
73 | audio_response = 1; |
||
74 | if (!data) exit(0); |
||
75 | |||
76 | // wait for resume |
||
77 | while (audio_command != AUDIO_RESUME) |
||
78 | _ksys_thread_yield(); |
||
79 | audio_command = 0; |
||
80 | bPaused = 0; |
||
81 | audio_response = 1; |
||
82 | PlayBuffer(hBuff, 0); |
||
83 | |||
84 | // main loop |
||
85 | while(1) { |
||
86 | if (audio_command == AUDIO_RESUME) { |
||
87 | PlayBuffer(hBuff, 0); |
||
88 | audio_command = 0; |
||
89 | bPaused = 0; |
||
90 | audio_response = 1; |
||
91 | } else if (audio_command == AUDIO_SUSPEND) { |
||
92 | StopBuffer(hBuff); |
||
93 | audio_command = 0; |
||
94 | bPaused = 1; |
||
95 | audio_response = 1; |
||
96 | }else if (audio_command == AUDIO_DIE) { |
||
97 | audio_response = 1; |
||
98 | StopBuffer(hBuff); |
||
99 | DestroyBuffer(hBuff); |
||
100 | exit(0); |
||
101 | } else { |
||
102 | _ksys_thread_info(&thread_info, main_slot); |
||
103 | if (thread_info.slot_state == KSYS_SLOT_STATE_FREE || thread_info.pid !=main_tid) { |
||
104 | audio_command = AUDIO_DIE; |
||
105 | continue; |
||
106 | } |
||
8210 | maxcodehac | 107 | } |
9789 | turbocat | 108 | if (bPaused) { |
109 | _ksys_delay(5); |
||
110 | } else { |
||
111 | _ksys_wait_signal(&snd_signal); |
||
112 | if (snd_signal.id != 0xFF000001) |
||
113 | continue; |
||
114 | while (bLocked) |
||
115 | _ksys_thread_yield(); |
||
116 | |||
117 | bInCallback=1; |
||
118 | callback(userdata, data, mix_size); |
||
119 | bInCallback=0; |
||
120 | SetBuffer(hBuff, data, ((int*)snd_signal.data)[2], mix_size); |
||
121 | } |
||
122 | } |
||
8210 | maxcodehac | 123 | } |
124 | |||
125 | int SDL_OpenAudio(SDL_AudioSpec* desired, SDL_AudioSpec* obtained) |
||
126 | { |
||
9789 | turbocat | 127 | if (!bInitialized) { |
128 | SDL_SetError("Audio device was not initialized"); |
||
129 | return -1; |
||
130 | } |
||
131 | |||
132 | if (!obtained) { |
||
133 | SDL_SetError("Audio format: software emulation is not supported"); |
||
134 | return -1; |
||
135 | } |
||
136 | |||
137 | if (used_format) { |
||
138 | SDL_SetError("Audio device was already opened"); |
||
139 | return -1; |
||
140 | } |
||
141 | memcpy(obtained, desired, sizeof(SDL_AudioSpec)); |
||
142 | switch (desired->freq) { |
||
8210 | maxcodehac | 143 | |
144 | #define HANDLE_FREQ(freq,symb) \ |
||
145 | case freq: \ |
||
146 | switch (desired->channels) \ |
||
147 | { \ |
||
148 | case 1: \ |
||
149 | switch (desired->format) \ |
||
150 | { \ |
||
151 | case AUDIO_U8: \ |
||
152 | case AUDIO_S8: \ |
||
153 | used_format = PCM_1_8_##symb; \ |
||
154 | break; \ |
||
155 | case AUDIO_U16SYS: \ |
||
156 | case AUDIO_S16SYS: \ |
||
157 | used_format = PCM_1_16_##symb; \ |
||
158 | break; \ |
||
159 | } \ |
||
160 | break; \ |
||
161 | case 2: \ |
||
162 | switch (desired->format) \ |
||
163 | { \ |
||
164 | case AUDIO_U8: \ |
||
165 | case AUDIO_S8: \ |
||
166 | used_format = PCM_2_8_##symb; \ |
||
167 | break; \ |
||
168 | case AUDIO_U16SYS: \ |
||
169 | case AUDIO_S16SYS: \ |
||
170 | used_format = PCM_2_16_##symb; \ |
||
171 | break; \ |
||
172 | } \ |
||
173 | break; \ |
||
174 | } \ |
||
175 | break; |
||
176 | |||
177 | HANDLE_FREQ(48000,48); |
||
178 | HANDLE_FREQ(44100,44); |
||
179 | HANDLE_FREQ(32000,32); |
||
180 | HANDLE_FREQ(24000,24); |
||
181 | HANDLE_FREQ(22050,22); |
||
182 | HANDLE_FREQ(16000,16); |
||
183 | HANDLE_FREQ(12000,12); |
||
184 | HANDLE_FREQ(11025,11); |
||
185 | HANDLE_FREQ(8000,8); |
||
9789 | turbocat | 186 | } |
187 | |||
188 | if (!used_format) { |
||
189 | SDL_SetError("Unknown audio format"); |
||
190 | return -1; |
||
191 | } |
||
192 | |||
193 | callback = desired->callback; |
||
194 | userdata = desired->userdata; |
||
195 | |||
196 | _ksys_thread_info(&thread_info, KSYS_THIS_SLOT); |
||
197 | main_tid = thread_info.pid; |
||
198 | for (main_slot=0 ;; main_slot++) { |
||
199 | _ksys_thread_info(&thread_info, main_slot); |
||
200 | if (thread_info.slot_state != KSYS_SLOT_STATE_FREE && thread_info.pid == main_tid) |
||
201 | break; |
||
202 | } |
||
203 | audio_tid = _ksys_create_thread(audio_thread, audio_thread_stack+AUDIO_THREAD_STACK_SIZE); |
||
204 | if (audio_tid < 0) { |
||
205 | SDL_SetError("Cannot create audio thread"); |
||
206 | return -1; |
||
207 | } |
||
208 | |||
209 | _ksys_focus_window(main_slot); |
||
210 | while (!audio_response) |
||
211 | _ksys_thread_yield(); |
||
212 | |||
213 | if (!hBuff) { |
||
214 | SDL_SetError("Cannot create audio buffer"); |
||
215 | return -1; |
||
216 | } |
||
217 | if (!data){ |
||
218 | SDL_SetError("Cannot allocate audio buffer"); |
||
219 | return -1; |
||
220 | } |
||
221 | obtained->silence = (desired->format == AUDIO_U8 ? 0x80 : 0); |
||
222 | obtained->size = mix_size; |
||
223 | obtained->samples = obtained->size / obtained->channels; |
||
224 | |||
225 | if (desired->format == AUDIO_U16SYS || desired->format == AUDIO_S16SYS) |
||
226 | obtained->samples /= 2; |
||
227 | |||
228 | SDL_printf("obtained size is %d, samples %d\n", obtained->size, obtained->samples); |
||
229 | return 0; |
||
8210 | maxcodehac | 230 | } |
231 | void SDL_CloseAudio(void) |
||
232 | { |
||
9789 | turbocat | 233 | if (!audio_tid) return; |
234 | audio_response = 0; |
||
235 | audio_command = AUDIO_DIE; |
||
236 | while (!audio_response) _ksys_thread_yield(); |
||
237 | free(data); |
||
238 | used_format = 0; |
||
8210 | maxcodehac | 239 | } |
240 | |||
241 | void SDL_PauseAudio(int pause_on) |
||
242 | { |
||
9789 | turbocat | 243 | if (!audio_tid) return; |
244 | audio_response = 0; |
||
245 | audio_command = pause_on ? AUDIO_SUSPEND : AUDIO_RESUME; |
||
246 | while (!audio_response) _ksys_thread_yield(); |
||
8210 | maxcodehac | 247 | } |
248 | void SDL_LockAudio(void) |
||
249 | { |
||
9789 | turbocat | 250 | if (!audio_tid) return; |
251 | bLocked = 1; |
||
252 | while (bInCallback) _ksys_thread_yield(); |
||
8210 | maxcodehac | 253 | } |
254 | void SDL_UnlockAudio(void) |
||
255 | { |
||
9789 | turbocat | 256 | bLocked = 0; |
8210 | maxcodehac | 257 | }> |