diff options
Diffstat (limited to 'firmware/target/hosted/sdl')
-rw-r--r-- | firmware/target/hosted/sdl/pcm-sdl.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c index 7780083b99..dfdd90f29b 100644 --- a/firmware/target/hosted/sdl/pcm-sdl.c +++ b/firmware/target/hosted/sdl/pcm-sdl.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "sound.h" | 30 | #include "sound.h" |
31 | #include "audiohw.h" | 31 | #include "audiohw.h" |
32 | #include "system.h" | 32 | #include "system.h" |
33 | #include "panic.h" | ||
33 | 34 | ||
34 | #ifdef HAVE_RECORDING | 35 | #ifdef HAVE_RECORDING |
35 | #include "audiohw.h" | 36 | #include "audiohw.h" |
@@ -39,6 +40,7 @@ | |||
39 | #endif | 40 | #endif |
40 | 41 | ||
41 | #include "pcm.h" | 42 | #include "pcm.h" |
43 | #include "pcm-internal.h" | ||
42 | #include "pcm_sampr.h" | 44 | #include "pcm_sampr.h" |
43 | 45 | ||
44 | /*#define LOGF_ENABLE*/ | 46 | /*#define LOGF_ENABLE*/ |
@@ -71,15 +73,19 @@ static struct pcm_udata | |||
71 | 73 | ||
72 | static SDL_AudioSpec obtained; | 74 | static SDL_AudioSpec obtained; |
73 | static SDL_AudioCVT cvt; | 75 | static SDL_AudioCVT cvt; |
76 | static int audio_locked = 0; | ||
77 | static SDL_mutex *audio_lock; | ||
74 | 78 | ||
75 | void pcm_play_lock(void) | 79 | void pcm_play_lock(void) |
76 | { | 80 | { |
77 | SDL_LockAudio(); | 81 | if (++audio_locked == 1) |
82 | SDL_LockMutex(audio_lock); | ||
78 | } | 83 | } |
79 | 84 | ||
80 | void pcm_play_unlock(void) | 85 | void pcm_play_unlock(void) |
81 | { | 86 | { |
82 | SDL_UnlockAudio(); | 87 | if (--audio_locked == 0) |
88 | SDL_UnlockMutex(audio_lock); | ||
83 | } | 89 | } |
84 | 90 | ||
85 | static void pcm_dma_apply_settings_nolock(void) | 91 | static void pcm_dma_apply_settings_nolock(void) |
@@ -227,14 +233,19 @@ static void write_to_soundcard(struct pcm_udata *udata) | |||
227 | static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) | 233 | static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) |
228 | { | 234 | { |
229 | logf("sdl_audio_callback: len %d, pcm %d\n", len, pcm_data_size); | 235 | logf("sdl_audio_callback: len %d, pcm %d\n", len, pcm_data_size); |
236 | |||
237 | bool new_buffer = false; | ||
230 | udata->stream = stream; | 238 | udata->stream = stream; |
231 | 239 | ||
240 | SDL_LockMutex(audio_lock); | ||
241 | |||
232 | /* Write what we have in the PCM buffer */ | 242 | /* Write what we have in the PCM buffer */ |
233 | if (pcm_data_size > 0) | 243 | if (pcm_data_size > 0) |
234 | goto start; | 244 | goto start; |
235 | 245 | ||
236 | /* Audio card wants more? Get some more then. */ | 246 | /* Audio card wants more? Get some more then. */ |
237 | while (len > 0) { | 247 | while (len > 0) { |
248 | new_buffer = true; | ||
238 | pcm_play_get_more_callback((void **)&pcm_data, &pcm_data_size); | 249 | pcm_play_get_more_callback((void **)&pcm_data, &pcm_data_size); |
239 | start: | 250 | start: |
240 | if (pcm_data_size != 0) { | 251 | if (pcm_data_size != 0) { |
@@ -246,6 +257,28 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) | |||
246 | udata->num_in *= pcm_sample_bytes; | 257 | udata->num_in *= pcm_sample_bytes; |
247 | udata->num_out *= pcm_sample_bytes; | 258 | udata->num_out *= pcm_sample_bytes; |
248 | 259 | ||
260 | |||
261 | if (new_buffer) | ||
262 | { | ||
263 | new_buffer = false; | ||
264 | pcm_play_dma_started_callback(); | ||
265 | |||
266 | if ((size_t)len > udata->num_out) | ||
267 | { | ||
268 | int delay = pcm_data_size*250 / pcm_sampr - 1; | ||
269 | |||
270 | if (delay > 0) | ||
271 | { | ||
272 | SDL_UnlockMutex(audio_lock); | ||
273 | SDL_Delay(delay); | ||
274 | SDL_LockMutex(audio_lock); | ||
275 | |||
276 | if (!pcm_is_playing()) | ||
277 | break; | ||
278 | } | ||
279 | } | ||
280 | } | ||
281 | |||
249 | pcm_data += udata->num_in; | 282 | pcm_data += udata->num_in; |
250 | pcm_data_size -= udata->num_in; | 283 | pcm_data_size -= udata->num_in; |
251 | udata->stream += udata->num_out; | 284 | udata->stream += udata->num_out; |
@@ -255,6 +288,8 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) | |||
255 | break; | 288 | break; |
256 | } | 289 | } |
257 | } | 290 | } |
291 | |||
292 | SDL_UnlockMutex(audio_lock); | ||
258 | } | 293 | } |
259 | 294 | ||
260 | const void * pcm_play_dma_get_peak_buffer(int *count) | 295 | const void * pcm_play_dma_get_peak_buffer(int *count) |
@@ -320,6 +355,14 @@ void pcm_play_dma_init(void) | |||
320 | return; | 355 | return; |
321 | } | 356 | } |
322 | 357 | ||
358 | audio_lock = SDL_CreateMutex(); | ||
359 | |||
360 | if (!audio_lock) | ||
361 | { | ||
362 | panicf("Could not create audio_lock\n"); | ||
363 | return; | ||
364 | } | ||
365 | |||
323 | SDL_AudioSpec wanted_spec; | 366 | SDL_AudioSpec wanted_spec; |
324 | #ifdef DEBUG | 367 | #ifdef DEBUG |
325 | udata.debug = NULL; | 368 | udata.debug = NULL; |