From a2b6703a369f6cdbfec1f150c408dadc877631fb Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Wed, 29 Jun 2011 06:37:04 +0000 Subject: Commit FS#12150 - Fully-functional audio mixer - and finally whip old limitations about playback of voice and other sounds when paused. Channels are independent in state and amplitude. Fade on stop/pause is handled by the channel's volume control rather than global volume which means it now works from anywhere. Opens up the possibility of plugin sounds during music playback by merely adding an additional channel enum. If any PCM drivers were not properly modified, see one of the last comments in the task for a description of the simple change that is expected. Some params are tunable in firmware/export/pcm-mixer.h as well. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30097 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/hosted/sdl/pcm-sdl.c | 47 ++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'firmware/target/hosted/sdl/pcm-sdl.c') 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 @@ #include "sound.h" #include "audiohw.h" #include "system.h" +#include "panic.h" #ifdef HAVE_RECORDING #include "audiohw.h" @@ -39,6 +40,7 @@ #endif #include "pcm.h" +#include "pcm-internal.h" #include "pcm_sampr.h" /*#define LOGF_ENABLE*/ @@ -71,15 +73,19 @@ static struct pcm_udata static SDL_AudioSpec obtained; static SDL_AudioCVT cvt; +static int audio_locked = 0; +static SDL_mutex *audio_lock; void pcm_play_lock(void) { - SDL_LockAudio(); + if (++audio_locked == 1) + SDL_LockMutex(audio_lock); } void pcm_play_unlock(void) { - SDL_UnlockAudio(); + if (--audio_locked == 0) + SDL_UnlockMutex(audio_lock); } static void pcm_dma_apply_settings_nolock(void) @@ -227,14 +233,19 @@ static void write_to_soundcard(struct pcm_udata *udata) static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) { logf("sdl_audio_callback: len %d, pcm %d\n", len, pcm_data_size); + + bool new_buffer = false; udata->stream = stream; + SDL_LockMutex(audio_lock); + /* Write what we have in the PCM buffer */ if (pcm_data_size > 0) goto start; /* Audio card wants more? Get some more then. */ while (len > 0) { + new_buffer = true; pcm_play_get_more_callback((void **)&pcm_data, &pcm_data_size); start: if (pcm_data_size != 0) { @@ -246,6 +257,28 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) udata->num_in *= pcm_sample_bytes; udata->num_out *= pcm_sample_bytes; + + if (new_buffer) + { + new_buffer = false; + pcm_play_dma_started_callback(); + + if ((size_t)len > udata->num_out) + { + int delay = pcm_data_size*250 / pcm_sampr - 1; + + if (delay > 0) + { + SDL_UnlockMutex(audio_lock); + SDL_Delay(delay); + SDL_LockMutex(audio_lock); + + if (!pcm_is_playing()) + break; + } + } + } + pcm_data += udata->num_in; pcm_data_size -= udata->num_in; udata->stream += udata->num_out; @@ -255,6 +288,8 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len) break; } } + + SDL_UnlockMutex(audio_lock); } const void * pcm_play_dma_get_peak_buffer(int *count) @@ -320,6 +355,14 @@ void pcm_play_dma_init(void) return; } + audio_lock = SDL_CreateMutex(); + + if (!audio_lock) + { + panicf("Could not create audio_lock\n"); + return; + } + SDL_AudioSpec wanted_spec; #ifdef DEBUG udata.debug = NULL; -- cgit v1.2.3