summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/talk.c17
-rw-r--r--apps/voice_thread.c25
2 files changed, 36 insertions, 6 deletions
diff --git a/apps/talk.c b/apps/talk.c
index a49de09..ab9ca8c 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -636,11 +636,10 @@ static bool load_voicefile_data(int fd)
return true;
}
-/* most, if not all, clips should be well below 32k (largest in english.lang is
- * 4.5K). Currently there is a problem with voice decoding such that clips
- * cannot be decoded in chunks. Once that is resolved this buffer could be
- * smaller and clips be decoded in multiple chunks */
-static unsigned char commit_buffer[32<<10];
+/* Use a static buffer to avoid difficulties with buflib during DMA
+ * (hwcodec)/buffer passing to the voice_thread (swcodec). Clips
+ * can be played in chunks so the size is not that important */
+static unsigned char commit_buffer[1<<10];
static void* commit_transfer(struct queue_entry *qe, size_t *size)
{
@@ -658,7 +657,6 @@ static void* commit_transfer(struct queue_entry *qe, size_t *size)
memcpy(bufpos, buf, sent);
*size = sent;
-
return commit_buffer;
}
@@ -674,6 +672,13 @@ static inline bool is_silence(struct queue_entry *qe)
static void mp3_callback(const void** start, size_t* size)
{
struct queue_entry *qe = &queue[queue_read];
+#if CONFIG_CODEC == SWCODEC
+ /* voice_thread.c hints us how many of the buffer we provided it actually
+ * consumed. Because buffers have to be frame-aligned for speex
+ * it might be less than what we presented */
+ if (*size)
+ sent = *size;
+#endif
qe->remaining -= sent; /* we completed this */
if (qe->remaining > 0) /* current clip not finished? */
diff --git a/apps/voice_thread.c b/apps/voice_thread.c
index 72ecb37..dcb7eef 100644
--- a/apps/voice_thread.c
+++ b/apps/voice_thread.c
@@ -63,9 +63,17 @@
latency */
#define PRIORITY_VOICE (PRIORITY_PLAYBACK-4)
+/* A speex frame generally consists of 20ms of audio
+ * (http://www.speex.org/docs/manual/speex-manual/node10.html)
+ * for wideband mode this results in 320 samples of decoded PCM.
+ */
#define VOICE_FRAME_COUNT 320 /* Samples / frame */
#define VOICE_SAMPLE_RATE 16000 /* Sample rate in HZ */
#define VOICE_SAMPLE_DEPTH 16 /* Sample depth in bits */
+/* The max. wideband bitrate is 42.4 kbps
+ * (http://www.speex.org/docs/manual/speex-manual/node11.html). For 20ms
+ * this gives a maximum of 106 bytes for an encoded speex frame */
+#define VOICE_MAX_ENCODED_FRAME_SIZE 106
/* Voice thread variables */
static unsigned int voice_thread_id = 0;
@@ -449,6 +457,23 @@ static enum voice_state voice_decode(struct voice_thread_data *td)
}
else
{
+ if (td->vi.size > VOICE_MAX_ENCODED_FRAME_SIZE
+ && td->bits.charPtr > (td->vi.size - VOICE_MAX_ENCODED_FRAME_SIZE)
+ && td->vi.get_more != NULL)
+ {
+ /* request more data _before_ running out of data (requesting
+ * more after the fact prevents speex from successful decoding)
+ * place a hint telling the callback how much of the
+ * previous buffer we have consumed such that it can rewind
+ * as necessary */
+ int bitPtr = td->bits.bitPtr;
+ td->vi.size = td->bits.charPtr;
+ td->vi.get_more(&td->vi.start, &td->vi.size);
+ speex_bits_set_bit_buffer(&td->bits, (void *)td->vi.start,
+ td->vi.size);
+ td->bits.bitPtr = bitPtr;
+ }
+
yield();
/* Output the decoded frame */