summaryrefslogtreecommitdiffstats
path: root/apps/playback.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2012-05-02 17:22:28 -0400
committerMichael Sevakis <jethead71@rockbox.org>2012-05-02 17:22:28 -0400
commitda6cebb6b0b17b4a75a2bd4f51b7cf70b5dafe40 (patch)
treedf0eb18120c38ec7b08d3ae1e0837f0781065e87 /apps/playback.c
parent3d3a144cf68186fd34f7bf11181b7757c7a6018d (diff)
downloadrockbox-da6cebb6b0b17b4a75a2bd4f51b7cf70b5dafe40.tar.gz
rockbox-da6cebb6b0b17b4a75a2bd4f51b7cf70b5dafe40.tar.bz2
rockbox-da6cebb6b0b17b4a75a2bd4f51b7cf70b5dafe40.zip
Use buflib for the allocation of voice PCM resources.
Buffers are not allocated and thread is not created until the first call where voice is required. Adds a different callback (sync_callback) to buflib so that other sorts of synchonization are possible, such as briefly locking-out the PCM callback for a buffer move. It's sort of a messy addition but it is needed so voice decoding won't have to be stopped when its buffer is moved. Change-Id: I4d4d8c35eed5dd15fb7ee7df9323af3d036e92b3
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c95
1 files changed, 39 insertions, 56 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 997a374410..bd7dd813c9 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -753,11 +753,12 @@ size_t audio_buffer_available(void)
/* Set up the audio buffer for playback
* filebuflen must be pre-initialized with the maximum size */
-static void audio_reset_buffer_noalloc(void* filebuf)
+static void audio_reset_buffer_noalloc(
+ void *filebuf, enum audio_buffer_state state)
{
/*
* Layout audio buffer as follows:
- * [[|TALK]|SCRATCH|BUFFERING|PCM|[VOICE|]]
+ * [[|TALK]|SCRATCH|BUFFERING|PCM]
*/
/* see audio_get_recording_buffer if this is modified */
@@ -770,7 +771,8 @@ static void audio_reset_buffer_noalloc(void* filebuf)
/* Initially set up file buffer as all space available */
size_t allocsize;
- /* Subtract whatever voice needs */
+ /* Subtract whatever voice needs (we're called when promoting
+ the state only) */
allocsize = talkbuf_init(filebuf);
allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
if (allocsize > filebuflen)
@@ -779,41 +781,33 @@ static void audio_reset_buffer_noalloc(void* filebuf)
filebuf += allocsize;
filebuflen -= allocsize;
- if (talk_voice_required())
+ if (state == AUDIOBUF_STATE_INITIALIZED)
{
- /* Need a space for voice PCM output */
- allocsize = voicebuf_init(filebuf + filebuflen);
+ /* Subtract whatever the pcm buffer says it used plus the guard
+ buffer */
+ allocsize = pcmbuf_init(filebuf + filebuflen);
+ /* Make sure filebuflen is a pointer sized multiple after
+ adjustment */
allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
if (allocsize > filebuflen)
goto bufpanic;
-
+
filebuflen -= allocsize;
- }
-
- /* Subtract whatever the pcm buffer says it used plus the guard buffer */
- allocsize = pcmbuf_init(filebuf + filebuflen);
-
- /* Make sure filebuflen is a pointer sized multiple after adjustment */
- allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
- if (allocsize > filebuflen)
- goto bufpanic;
- filebuflen -= allocsize;
-
- /* Scratch memory */
- allocsize = scratch_mem_size();
- if (allocsize > filebuflen)
- goto bufpanic;
+ /* Scratch memory */
+ allocsize = scratch_mem_size();
+ if (allocsize > filebuflen)
+ goto bufpanic;
- scratch_mem_init(filebuf);
- filebuf += allocsize;
- filebuflen -= allocsize;
+ scratch_mem_init(filebuf);
+ filebuf += allocsize;
+ filebuflen -= allocsize;
- buffering_reset(filebuf, filebuflen);
+ buffering_reset(filebuf, filebuflen);
+ }
- /* Clear any references to the file buffer */
- buffer_state = AUDIOBUF_STATE_INITIALIZED;
+ buffer_state = state;
#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
/* Make sure everything adds up - yes, some info is a bit redundant but
@@ -891,11 +885,12 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
{
case BUFLIB_SHRINK_POS_BACK:
core_shrink(handle, start, size);
- audio_reset_buffer_noalloc(start);
+ audio_reset_buffer_noalloc(start, buffer_state);
break;
case BUFLIB_SHRINK_POS_FRONT:
core_shrink(handle, start + wanted_size, size);
- audio_reset_buffer_noalloc(start + wanted_size);
+ audio_reset_buffer_noalloc(start + wanted_size,
+ buffer_state);
break;
}
if (playing || play_queued)
@@ -912,7 +907,7 @@ static struct buflib_callbacks ops = {
.shrink_callback = shrink_callback,
};
-static void audio_reset_buffer(void)
+static void audio_reset_buffer(enum audio_buffer_state state)
{
if (audiobuf_handle > 0)
{
@@ -922,7 +917,7 @@ static void audio_reset_buffer(void)
audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops);
unsigned char *filebuf = core_get_data(audiobuf_handle);
- audio_reset_buffer_noalloc(filebuf);
+ audio_reset_buffer_noalloc(filebuf, state);
}
/* Set the buffer margin to begin rebuffering when 'seconds' from empty */
@@ -2051,7 +2046,7 @@ static int audio_fill_file_buffer(void)
file size shouldn't have changed so we can go straight from
AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
- audio_reset_buffer();
+ audio_reset_buffer(AUDIOBUF_STATE_INITIALIZED);
logf("Starting buffer fill");
@@ -3649,14 +3644,9 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
logf("get buffer: audio");
/* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
still AUDIOBUF_STATE_INITIALIZED */
- /* Skip talk buffer and move pcm buffer to end to maximize available
- contiguous memory - no audio running means voice will not need the
- swap space */
- size_t talkbuf_size;
- buf += talkbuf_size = talkbuf_init(buf);
+ size_t talkbuf_size = talkbuf_init(buf);
+ buf += talkbuf_size; /* Skip talk buffer */
filebuflen -= talkbuf_size;
- filebuflen -= voicebuf_init(buf + filebuflen);
-
buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
}
@@ -3673,19 +3663,18 @@ unsigned char * audio_get_recording_buffer(size_t *buffer_size)
}
#endif /* HAVE_RECORDING */
-/* Restore audio buffer to a particular state (one more valid than the current
- state) */
+/* Restore audio buffer to a particular state (promoting status) */
bool audio_restore_playback(int type)
{
switch (type)
{
case AUDIO_WANT_PLAYBACK:
if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
- audio_reset_buffer();
+ audio_reset_buffer(AUDIOBUF_STATE_INITIALIZED);
return true;
case AUDIO_WANT_VOICE:
if (buffer_state == AUDIOBUF_STATE_TRASHED)
- audio_reset_buffer();
+ audio_reset_buffer(AUDIOBUF_STATE_VOICED_ONLY);
return true;
default:
return false;
@@ -3910,24 +3899,18 @@ void audio_init(void)
queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
audio_thread_id);
-#ifdef PLAYBACK_VOICE
- voice_thread_init();
-#endif
-
- /* audio_reset_buffer must know the size of voice buffer so init
- talk first */
- talk_init();
+ /* Initialize the track buffering system */
+ track_list_init();
+ buffering_init();
#ifdef HAVE_CROSSFADE
/* Set crossfade setting for next buffer init which should be about... */
pcmbuf_request_crossfade_enable(global_settings.crossfade);
#endif
- /* Initialize the buffering system */
- track_list_init();
- buffering_init();
- /* ...now! Set up the buffers */
- audio_reset_buffer();
+ /* ...now...audio_reset_buffer must know the size of voicefile buffer so
+ init talk first which will init the buffers */
+ talk_init();
/* Probably safe to say */
audio_is_initialized = true;