blob: 59568d8ff90b1da1c27c37f0f8003dda7e0458e6 [file] [log] [blame]
Michael Sevakis99617d72007-11-18 17:12:19 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Michael Sevakis
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Michael Sevakis99617d72007-11-18 17:12:19 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Thomas Martitz281d1fa2014-01-05 01:22:19 +010021
Michael Sevakisd37bf242013-05-23 13:58:51 -040022#include "config.h"
Michael Sevakis99617d72007-11-18 17:12:19 +000023#include "system.h"
Thomas Martitz281d1fa2014-01-05 01:22:19 +010024#include "kernel.h"
Michael Sevakisda6cebb2012-05-02 17:22:28 -040025#include "core_alloc.h"
Michael Sevakis99617d72007-11-18 17:12:19 +000026#include "thread.h"
Michael Sevakise62cb562013-05-31 18:45:51 -040027#include "appevents.h"
Michael Sevakis99617d72007-11-18 17:12:19 +000028#include "voice_thread.h"
29#include "talk.h"
Michael Sevakis56f17c42012-04-29 17:31:30 -040030#include "dsp_core.h"
Michael Sevakisa2b67032011-06-29 06:37:04 +000031#include "pcm.h"
32#include "pcm_mixer.h"
Michael Sevakis99617d72007-11-18 17:12:19 +000033#include "codecs/libspeex/speex/speex.h"
34
Michael Sevakisd37bf242013-05-23 13:58:51 -040035/* Default number of PCM frames to queue - adjust as necessary per-target */
Michael Sevakisda6cebb2012-05-02 17:22:28 -040036#define VOICE_FRAMES 4
37
Jeffrey Goode09cd1882010-05-04 14:43:01 +000038/* Define any of these as "1" and uncomment the LOGF_ENABLE line to log
39 regular and/or timeout messages */
Michael Sevakis99617d72007-11-18 17:12:19 +000040#define VOICE_LOGQUEUES 0
41#define VOICE_LOGQUEUES_SYS_TIMEOUT 0
42
Jeffrey Goode09cd1882010-05-04 14:43:01 +000043/*#define LOGF_ENABLE*/
44#include "logf.h"
45
Michael Sevakis99617d72007-11-18 17:12:19 +000046#if VOICE_LOGQUEUES
47#define LOGFQUEUE logf
48#else
49#define LOGFQUEUE(...)
50#endif
51
52#if VOICE_LOGQUEUES_SYS_TIMEOUT
53#define LOGFQUEUE_SYS_TIMEOUT logf
54#else
55#define LOGFQUEUE_SYS_TIMEOUT(...)
56#endif
57
58#ifndef IBSS_ATTR_VOICE_STACK
59#define IBSS_ATTR_VOICE_STACK IBSS_ATTR
60#endif
61
Michael Sevakisa2b67032011-06-29 06:37:04 +000062/* Minimum priority needs to be a bit elevated since voice has fairly low
63 latency */
64#define PRIORITY_VOICE (PRIORITY_PLAYBACK-4)
65
Thomas Martitze5eb7452014-01-21 23:22:37 +010066/* A speex frame generally consists of 20ms of audio
67 * (http://www.speex.org/docs/manual/speex-manual/node10.html)
68 * for wideband mode this results in 320 samples of decoded PCM.
69 */
Michael Sevakiscfc32fe2012-04-26 15:57:07 -040070#define VOICE_FRAME_COUNT 320 /* Samples / frame */
Michael Sevakis99617d72007-11-18 17:12:19 +000071#define VOICE_SAMPLE_RATE 16000 /* Sample rate in HZ */
72#define VOICE_SAMPLE_DEPTH 16 /* Sample depth in bits */
Thomas Martitze5eb7452014-01-21 23:22:37 +010073/* The max. wideband bitrate is 42.4 kbps
74 * (http://www.speex.org/docs/manual/speex-manual/node11.html). For 20ms
75 * this gives a maximum of 106 bytes for an encoded speex frame */
76#define VOICE_MAX_ENCODED_FRAME_SIZE 106
Michael Sevakis99617d72007-11-18 17:12:19 +000077
78/* Voice thread variables */
Michael Sevakis8cfbd362008-12-10 08:57:10 +000079static unsigned int voice_thread_id = 0;
Michael Sevakisa2b67032011-06-29 06:37:04 +000080#ifdef CPU_COLDFIRE
81/* ISR uses any available stack - need a bit more room */
82#define VOICE_STACK_EXTRA 0x400
83#else
84#define VOICE_STACK_EXTRA 0x3c0
85#endif
86static long voice_stack[(DEFAULT_STACK_SIZE + VOICE_STACK_EXTRA)/sizeof(long)]
87 IBSS_ATTR_VOICE_STACK;
Michael Sevakis99617d72007-11-18 17:12:19 +000088static const char voice_thread_name[] = "voice";
89
90/* Voice thread synchronization objects */
Michael Sevakis05099142008-04-06 04:34:57 +000091static struct event_queue voice_queue SHAREDBSS_ATTR;
Michael Sevakis05099142008-04-06 04:34:57 +000092static struct queue_sender_list voice_queue_sender_list SHAREDBSS_ATTR;
Michael Sevakis456170a2011-08-30 15:35:25 +000093static int quiet_counter SHAREDDATA_ATTR = 0;
Michael Sevakise62cb562013-05-31 18:45:51 -040094static bool voice_playing = false;
Michael Sevakis99617d72007-11-18 17:12:19 +000095
Michael Sevakisd37bf242013-05-23 13:58:51 -040096#define VOICE_PCM_FRAME_COUNT ((PLAY_SAMPR_MAX*VOICE_FRAME_COUNT + \
97 VOICE_SAMPLE_RATE) / VOICE_SAMPLE_RATE)
Michael Sevakiscfc32fe2012-04-26 15:57:07 -040098#define VOICE_PCM_FRAME_SIZE (VOICE_PCM_FRAME_COUNT*2*sizeof (int16_t))
Michael Sevakisa2b67032011-06-29 06:37:04 +000099
Michael Sevakis456170a2011-08-30 15:35:25 +0000100/* Voice processing states */
101enum voice_state
102{
103 VOICE_STATE_MESSAGE = 0,
104 VOICE_STATE_DECODE,
105 VOICE_STATE_BUFFER_INSERT,
106};
107
Michael Sevakisa2b67032011-06-29 06:37:04 +0000108/* A delay to not bring audio back to normal level too soon */
109#define QUIET_COUNT 3
110
Michael Sevakis99617d72007-11-18 17:12:19 +0000111enum voice_thread_messages
112{
Michael Sevakis456170a2011-08-30 15:35:25 +0000113 Q_VOICE_PLAY = 0, /* Play a clip */
Michael Sevakis99617d72007-11-18 17:12:19 +0000114 Q_VOICE_STOP, /* Stop current clip */
Michael Sevakis99617d72007-11-18 17:12:19 +0000115};
116
117/* Structure to store clip data callback info */
118struct voice_info
119{
Michael Sevakis286a4c52012-02-23 08:14:46 -0500120 /* Callback to get more clips */
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500121 mp3_play_callback_t get_more;
Michael Sevakis286a4c52012-02-23 08:14:46 -0500122 /* Start of clip */
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500123 const void *start;
Michael Sevakis286a4c52012-02-23 08:14:46 -0500124 /* Size of clip */
125 size_t size;
Michael Sevakis99617d72007-11-18 17:12:19 +0000126};
127
128/* Private thread data for its current state that must be passed to its
129 * internal functions */
130struct voice_thread_data
131{
Michael Sevakis99617d72007-11-18 17:12:19 +0000132 struct queue_event ev; /* Last queue event pulled from queue */
133 void *st; /* Decoder instance */
134 SpeexBits bits; /* Bit cursor */
135 struct dsp_config *dsp; /* DSP used for voice output */
136 struct voice_info vi; /* Copy of clip data */
Michael Sevakis99617d72007-11-18 17:12:19 +0000137 int lookahead; /* Number of samples to drop at start of clip */
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400138 struct dsp_buffer src; /* Speex output buffer/input to DSP */
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400139 struct dsp_buffer *dst; /* Pointer to DSP output buffer for PCM */
Michael Sevakis99617d72007-11-18 17:12:19 +0000140};
141
Michael Sevakis456170a2011-08-30 15:35:25 +0000142/* Functions called in their repective state that return the next state to
143 state machine loop - compiler may inline them at its discretion */
144static enum voice_state voice_message(struct voice_thread_data *td);
145static enum voice_state voice_decode(struct voice_thread_data *td);
146static enum voice_state voice_buffer_insert(struct voice_thread_data *td);
147
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400148/* Might have lookahead and be skipping samples, so size is needed */
149static struct voice_buf
150{
151 /* Buffer for decoded samples */
152 spx_int16_t spx_outbuf[VOICE_FRAME_COUNT];
153 /* Queue frame indexes */
Michael Sevakis77220142012-05-30 12:55:26 -0400154 unsigned int volatile frame_in;
155 unsigned int volatile frame_out;
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400156 /* For PCM pointer adjustment */
157 struct voice_thread_data *td;
158 /* Buffers for mixing voice */
159 struct voice_pcm_frame
160 {
161 size_t size;
162 int16_t pcm[2*VOICE_PCM_FRAME_COUNT];
163 } frames[VOICE_FRAMES];
164} *voice_buf = NULL;
165
166static int voice_buf_hid = 0;
167
168static int move_callback(int handle, void *current, void *new)
169{
170 /* Have to adjust the pointers that point into things in voice_buf */
171 off_t diff = new - current;
172 struct voice_thread_data *td = voice_buf->td;
Michael Sevakis8bbd4d92012-05-17 11:16:20 -0400173
174 if (td != NULL)
175 {
176 td->src.p32[0] = SKIPBYTES(td->src.p32[0], diff);
177 td->src.p32[1] = SKIPBYTES(td->src.p32[1], diff);
178
179 if (td->dst != NULL) /* Only when calling dsp_process */
180 td->dst->p16out = SKIPBYTES(td->dst->p16out, diff);
181
182 mixer_adjust_channel_address(PCM_MIXER_CHAN_VOICE, diff);
183 }
184
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400185 voice_buf = new;
186
187 return BUFLIB_CB_OK;
188 (void)handle;
189};
190
191static void sync_callback(int handle, bool sync_on)
192{
193 /* A move must not allow PCM to access the channel */
194 if (sync_on)
195 pcm_play_lock();
196 else
197 pcm_play_unlock();
198
199 (void)handle;
200}
201
202static struct buflib_callbacks ops =
203{
204 .move_callback = move_callback,
205 .sync_callback = sync_callback,
206};
207
Michael Sevakisa2b67032011-06-29 06:37:04 +0000208/* Number of frames in queue */
Michael Sevakis77220142012-05-30 12:55:26 -0400209static unsigned int voice_unplayed_frames(void)
Michael Sevakis99617d72007-11-18 17:12:19 +0000210{
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400211 return voice_buf->frame_in - voice_buf->frame_out;
Michael Sevakisa2b67032011-06-29 06:37:04 +0000212}
213
214/* Mixer channel callback */
Michael Sevakis286a4c52012-02-23 08:14:46 -0500215static void voice_pcm_callback(const void **start, size_t *size)
Michael Sevakisa2b67032011-06-29 06:37:04 +0000216{
Michael Sevakis77220142012-05-30 12:55:26 -0400217 unsigned int frame_out = ++voice_buf->frame_out;
218
Michael Sevakisa2b67032011-06-29 06:37:04 +0000219 if (voice_unplayed_frames() == 0)
220 return; /* Done! */
221
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400222 struct voice_pcm_frame *frame =
Michael Sevakis77220142012-05-30 12:55:26 -0400223 &voice_buf->frames[frame_out % VOICE_FRAMES];
Michael Sevakisa2b67032011-06-29 06:37:04 +0000224
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400225 *start = frame->pcm;
226 *size = frame->size;
Michael Sevakisa2b67032011-06-29 06:37:04 +0000227}
228
229/* Start playback of voice channel if not already playing */
230static void voice_start_playback(void)
231{
Michael Sevakiscfc32fe2012-04-26 15:57:07 -0400232 if (mixer_channel_status(PCM_MIXER_CHAN_VOICE) != CHANNEL_STOPPED ||
Michael Sevakis77220142012-05-30 12:55:26 -0400233 voice_unplayed_frames() == 0)
Michael Sevakisa2b67032011-06-29 06:37:04 +0000234 return;
235
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400236 struct voice_pcm_frame *frame =
237 &voice_buf->frames[voice_buf->frame_out % VOICE_FRAMES];
238
Michael Sevakisa2b67032011-06-29 06:37:04 +0000239 mixer_channel_play_data(PCM_MIXER_CHAN_VOICE, voice_pcm_callback,
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400240 frame->pcm, frame->size);
Michael Sevakisa2b67032011-06-29 06:37:04 +0000241}
242
243/* Stop the voice channel */
244static void voice_stop_playback(void)
245{
246 mixer_channel_stop(PCM_MIXER_CHAN_VOICE);
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400247 voice_buf->frame_in = voice_buf->frame_out = 0;
Michael Sevakisa2b67032011-06-29 06:37:04 +0000248}
249
250/* Grab a free PCM frame */
Michael Sevakis97a535d2012-04-26 16:24:12 -0400251static int16_t * voice_buf_get(void)
Michael Sevakisa2b67032011-06-29 06:37:04 +0000252{
253 if (voice_unplayed_frames() >= VOICE_FRAMES)
254 {
255 /* Full */
256 voice_start_playback();
257 return NULL;
258 }
259
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400260 return voice_buf->frames[voice_buf->frame_in % VOICE_FRAMES].pcm;
Michael Sevakisa2b67032011-06-29 06:37:04 +0000261}
262
263/* Commit a frame returned by voice_buf_get and set the actual size */
Michael Sevakiscfc32fe2012-04-26 15:57:07 -0400264static void voice_buf_commit(int count)
Michael Sevakisa2b67032011-06-29 06:37:04 +0000265{
Michael Sevakiscfc32fe2012-04-26 15:57:07 -0400266 if (count > 0)
267 {
Michael Sevakis77220142012-05-30 12:55:26 -0400268 unsigned int frame_in = voice_buf->frame_in;
269 voice_buf->frames[frame_in % VOICE_FRAMES].size =
Michael Sevakiscfc32fe2012-04-26 15:57:07 -0400270 count * 2 * sizeof (int16_t);
Michael Sevakis77220142012-05-30 12:55:26 -0400271 voice_buf->frame_in = frame_in + 1;
Michael Sevakiscfc32fe2012-04-26 15:57:07 -0400272 }
Michael Sevakis99617d72007-11-18 17:12:19 +0000273}
274
275/* Stop any current clip and start playing a new one */
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500276void mp3_play_data(const void *start, size_t size,
277 mp3_play_callback_t get_more)
Michael Sevakis99617d72007-11-18 17:12:19 +0000278{
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400279 if (voice_thread_id && start && size && get_more)
Michael Sevakis99617d72007-11-18 17:12:19 +0000280 {
Michael Sevakisa2b67032011-06-29 06:37:04 +0000281 struct voice_info voice_clip =
282 {
283 .get_more = get_more,
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500284 .start = start,
Michael Sevakisa2b67032011-06-29 06:37:04 +0000285 .size = size,
286 };
Michael Sevakis99617d72007-11-18 17:12:19 +0000287
Michael Sevakis99617d72007-11-18 17:12:19 +0000288 LOGFQUEUE("mp3 >| voice Q_VOICE_PLAY");
289 queue_send(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
Michael Sevakis99617d72007-11-18 17:12:19 +0000290 }
291}
292
293/* Stop current voice clip from playing */
294void mp3_play_stop(void)
295{
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400296 if (voice_thread_id != 0)
297 {
298 LOGFQUEUE("mp3 >| voice Q_VOICE_STOP");
299 queue_send(&voice_queue, Q_VOICE_STOP, 0);
300 }
Michael Sevakis99617d72007-11-18 17:12:19 +0000301}
302
303void mp3_play_pause(bool play)
304{
305 /* a dummy */
306 (void)play;
307}
308
Michael Sevakisa2b67032011-06-29 06:37:04 +0000309/* Tell if voice is still in a playing state */
Michael Sevakis99617d72007-11-18 17:12:19 +0000310bool mp3_is_playing(void)
311{
Michael Sevakise62cb562013-05-31 18:45:51 -0400312 return voice_playing;
Michael Sevakis99617d72007-11-18 17:12:19 +0000313}
314
315/* This function is meant to be used by the buffer request functions to
316 ensure the codec is no longer active */
317void voice_stop(void)
318{
Michael Sevakis99617d72007-11-18 17:12:19 +0000319 /* Unqueue all future clips */
320 talk_force_shutup();
Michael Sevakisa2b67032011-06-29 06:37:04 +0000321}
Michael Sevakis99617d72007-11-18 17:12:19 +0000322
323/* Wait for voice to finish speaking. */
324void voice_wait(void)
325{
326 /* NOTE: One problem here is that we can't tell if another thread started a
327 * new clip by the time we wait. This should be resolvable if conditions
328 * ever require knowing the very clip you requested has finished. */
Michael Sevakiseffceea2008-10-23 13:13:00 +0000329
Michael Sevakise62cb562013-05-31 18:45:51 -0400330 while (voice_playing)
Stéphane Doyon686b1142007-11-24 14:21:04 +0000331 sleep(1);
Michael Sevakis99617d72007-11-18 17:12:19 +0000332}
333
334/* Initialize voice thread data that must be valid upon starting and the
335 * setup the DSP parameters */
336static void voice_data_init(struct voice_thread_data *td)
337{
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400338 td->dsp = dsp_get_config(CODEC_IDX_VOICE);
Michael Sevakis99617d72007-11-18 17:12:19 +0000339 dsp_configure(td->dsp, DSP_RESET, 0);
340 dsp_configure(td->dsp, DSP_SET_FREQUENCY, VOICE_SAMPLE_RATE);
341 dsp_configure(td->dsp, DSP_SET_SAMPLE_DEPTH, VOICE_SAMPLE_DEPTH);
342 dsp_configure(td->dsp, DSP_SET_STEREO_MODE, STEREO_MONO);
Michael Sevakisa2b67032011-06-29 06:37:04 +0000343
344 mixer_channel_set_amplitude(PCM_MIXER_CHAN_VOICE, MIX_AMP_UNITY);
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400345 voice_buf->td = td;
Thomas Martitzb985d5c2012-09-11 06:39:53 +0200346 td->dst = NULL;
Michael Sevakis99617d72007-11-18 17:12:19 +0000347}
348
349/* Voice thread message processing */
Michael Sevakis456170a2011-08-30 15:35:25 +0000350static enum voice_state voice_message(struct voice_thread_data *td)
Michael Sevakis99617d72007-11-18 17:12:19 +0000351{
Michael Sevakise62cb562013-05-31 18:45:51 -0400352 queue_wait_w_tmo(&voice_queue, &td->ev,
353 quiet_counter > 0 ? HZ/10 : TIMEOUT_BLOCK);
Michael Sevakis456170a2011-08-30 15:35:25 +0000354
355 switch (td->ev.id)
Michael Sevakis99617d72007-11-18 17:12:19 +0000356 {
Michael Sevakis456170a2011-08-30 15:35:25 +0000357 case Q_VOICE_PLAY:
358 LOGFQUEUE("voice < Q_VOICE_PLAY");
359 if (quiet_counter == 0)
Michael Sevakis99617d72007-11-18 17:12:19 +0000360 {
Michael Sevakis456170a2011-08-30 15:35:25 +0000361 /* Boost CPU now */
362 trigger_cpu_boost();
363 }
364 else
365 {
366 /* Stop any clip still playing */
Michael Sevakisa2b67032011-06-29 06:37:04 +0000367 voice_stop_playback();
Michael Sevakisd37bf242013-05-23 13:58:51 -0400368 dsp_configure(td->dsp, DSP_FLUSH, 0);
Michael Sevakis99617d72007-11-18 17:12:19 +0000369 }
370
Michael Sevakise62cb562013-05-31 18:45:51 -0400371 if (quiet_counter <= 0)
372 {
Michael Sevakise62cb562013-05-31 18:45:51 -0400373 voice_playing = true;
Michael Sevakisd37bf242013-05-23 13:58:51 -0400374 dsp_configure(td->dsp, DSP_SET_OUT_FREQUENCY, mixer_get_frequency());
Michael Sevakisc8564f12017-12-12 20:14:34 -0500375 send_event(VOICE_EVENT_IS_PLAYING, &voice_playing);
Michael Sevakise62cb562013-05-31 18:45:51 -0400376 }
377
Michael Sevakis456170a2011-08-30 15:35:25 +0000378 quiet_counter = QUIET_COUNT;
379
380 /* Copy the clip info */
381 td->vi = *(struct voice_info *)td->ev.data;
382
Michael Sevakis456170a2011-08-30 15:35:25 +0000383 /* We need nothing more from the sending thread - let it run */
384 queue_reply(&voice_queue, 1);
385
Michael Sevakis456170a2011-08-30 15:35:25 +0000386 /* Clean-start the decoder */
387 td->st = speex_decoder_init(&speex_wb_mode);
388
389 /* Make bit buffer use our own buffer */
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500390 speex_bits_set_bit_buffer(&td->bits, (void *)td->vi.start,
391 td->vi.size);
Michael Sevakis456170a2011-08-30 15:35:25 +0000392 speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);
393
394 return VOICE_STATE_DECODE;
395
396 case SYS_TIMEOUT:
397 if (voice_unplayed_frames())
398 {
399 /* Waiting for PCM to finish */
400 break;
401 }
402
403 /* Drop through and stop the first time after clip runs out */
404 if (quiet_counter-- != QUIET_COUNT)
405 {
406 if (quiet_counter <= 0)
Michael Sevakise62cb562013-05-31 18:45:51 -0400407 {
408 voice_playing = false;
Michael Sevakisc8564f12017-12-12 20:14:34 -0500409 send_event(VOICE_EVENT_IS_PLAYING, &voice_playing);
Michael Sevakise62cb562013-05-31 18:45:51 -0400410 }
Michael Sevakis456170a2011-08-30 15:35:25 +0000411 break;
412 }
413
414 /* Fall-through */
415 case Q_VOICE_STOP:
416 LOGFQUEUE("voice < Q_VOICE_STOP");
417 cancel_cpu_boost();
418 voice_stop_playback();
419 break;
420
421 /* No default: no other message ids are sent */
Michael Sevakis99617d72007-11-18 17:12:19 +0000422 }
Michael Sevakis456170a2011-08-30 15:35:25 +0000423
424 return VOICE_STATE_MESSAGE;
425}
426
427/* Decode frames or stop if all have completed */
428static enum voice_state voice_decode(struct voice_thread_data *td)
429{
430 if (!queue_empty(&voice_queue))
431 return VOICE_STATE_MESSAGE;
432
433 /* Decode the data */
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400434 if (speex_decode_int(td->st, &td->bits, voice_buf->spx_outbuf) < 0)
Michael Sevakis456170a2011-08-30 15:35:25 +0000435 {
436 /* End of stream or error - get next clip */
437 td->vi.size = 0;
438
439 if (td->vi.get_more != NULL)
440 td->vi.get_more(&td->vi.start, &td->vi.size);
441
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500442 if (td->vi.start != NULL && td->vi.size > 0)
Michael Sevakis456170a2011-08-30 15:35:25 +0000443 {
444 /* Make bit buffer use our own buffer */
Michael Sevakisd18a5ca2012-03-04 14:44:43 -0500445 speex_bits_set_bit_buffer(&td->bits, (void *)td->vi.start,
446 td->vi.size);
Michael Sevakis456170a2011-08-30 15:35:25 +0000447 /* Don't skip any samples when we're stringing clips together */
448 td->lookahead = 0;
449 }
450 else
451 {
452 /* If all clips are done and not playing, force pcm playback. */
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400453 if (voice_unplayed_frames() > 0)
454 voice_start_playback();
Michael Sevakis456170a2011-08-30 15:35:25 +0000455 return VOICE_STATE_MESSAGE;
456 }
457 }
458 else
459 {
Thomas Martitze5eb7452014-01-21 23:22:37 +0100460 if (td->vi.size > VOICE_MAX_ENCODED_FRAME_SIZE
Thomas Martitz10b3bc72014-02-03 12:33:33 +0100461 && td->bits.charPtr > (int)(td->vi.size - VOICE_MAX_ENCODED_FRAME_SIZE)
Thomas Martitze5eb7452014-01-21 23:22:37 +0100462 && td->vi.get_more != NULL)
463 {
464 /* request more data _before_ running out of data (requesting
465 * more after the fact prevents speex from successful decoding)
466 * place a hint telling the callback how much of the
467 * previous buffer we have consumed such that it can rewind
468 * as necessary */
469 int bitPtr = td->bits.bitPtr;
470 td->vi.size = td->bits.charPtr;
471 td->vi.get_more(&td->vi.start, &td->vi.size);
472 speex_bits_set_bit_buffer(&td->bits, (void *)td->vi.start,
473 td->vi.size);
474 td->bits.bitPtr = bitPtr;
475 }
476
Michael Sevakis456170a2011-08-30 15:35:25 +0000477 yield();
478
479 /* Output the decoded frame */
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400480 td->src.remcount = VOICE_FRAME_COUNT - td->lookahead;
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400481 td->src.pin[0] = &voice_buf->spx_outbuf[td->lookahead];
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400482 td->src.pin[1] = NULL;
483 td->src.proc_mask = 0;
484
Michael Sevakiscfc32fe2012-04-26 15:57:07 -0400485 td->lookahead -= MIN(VOICE_FRAME_COUNT, td->lookahead);
Michael Sevakis456170a2011-08-30 15:35:25 +0000486
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400487 if (td->src.remcount > 0)
Michael Sevakis456170a2011-08-30 15:35:25 +0000488 return VOICE_STATE_BUFFER_INSERT;
489 }
490
491 return VOICE_STATE_DECODE;
492}
493
494/* Process the PCM samples in the DSP and send out for mixing */
495static enum voice_state voice_buffer_insert(struct voice_thread_data *td)
496{
497 if (!queue_empty(&voice_queue))
498 return VOICE_STATE_MESSAGE;
499
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400500 struct dsp_buffer dst;
Michael Sevakis456170a2011-08-30 15:35:25 +0000501
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400502 if ((dst.p16out = voice_buf_get()) != NULL)
Michael Sevakis456170a2011-08-30 15:35:25 +0000503 {
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400504 dst.remcount = 0;
505 dst.bufcount = VOICE_PCM_FRAME_COUNT;
506
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400507 td->dst = &dst;
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400508 dsp_process(td->dsp, &td->src, &dst);
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400509 td->dst = NULL;
Michael Sevakisc9bcbe22012-03-27 19:52:15 -0400510
511 voice_buf_commit(dst.remcount);
512
513 /* Unless other effects are introduced to voice that have delays,
514 all output should have been purged to dst in one call */
515 return td->src.remcount > 0 ?
516 VOICE_STATE_BUFFER_INSERT : VOICE_STATE_DECODE;
Michael Sevakis456170a2011-08-30 15:35:25 +0000517 }
518
519 sleep(0);
520 return VOICE_STATE_BUFFER_INSERT;
Michael Sevakis99617d72007-11-18 17:12:19 +0000521}
522
523/* Voice thread entrypoint */
Michael Sevakisa2b67032011-06-29 06:37:04 +0000524static void NORETURN_ATTR voice_thread(void)
Michael Sevakis99617d72007-11-18 17:12:19 +0000525{
526 struct voice_thread_data td;
Michael Sevakis456170a2011-08-30 15:35:25 +0000527 enum voice_state state = VOICE_STATE_MESSAGE;
Michael Sevakis99617d72007-11-18 17:12:19 +0000528
529 voice_data_init(&td);
Stéphane Doyonc893aff2008-07-15 14:06:11 +0000530
Michael Sevakis99617d72007-11-18 17:12:19 +0000531 while (1)
532 {
Michael Sevakis456170a2011-08-30 15:35:25 +0000533 switch (state)
Michael Sevakis99617d72007-11-18 17:12:19 +0000534 {
Michael Sevakis456170a2011-08-30 15:35:25 +0000535 case VOICE_STATE_MESSAGE:
536 state = voice_message(&td);
537 break;
538 case VOICE_STATE_DECODE:
539 state = voice_decode(&td);
540 break;
541 case VOICE_STATE_BUFFER_INSERT:
542 state = voice_buffer_insert(&td);
543 break;
Michael Sevakis99617d72007-11-18 17:12:19 +0000544 }
Michael Sevakis456170a2011-08-30 15:35:25 +0000545 }
Michael Sevakisa2b67032011-06-29 06:37:04 +0000546}
Michael Sevakis99617d72007-11-18 17:12:19 +0000547
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400548/* Initialize buffers, all synchronization objects and create the thread */
Michael Sevakis99617d72007-11-18 17:12:19 +0000549void voice_thread_init(void)
550{
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400551 if (voice_thread_id != 0)
552 return; /* Already did an init and succeeded at it */
553
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400554 voice_buf_hid = core_alloc_ex("voice buf", sizeof (*voice_buf), &ops);
555
556 if (voice_buf_hid <= 0)
557 {
558 logf("voice: core_alloc_ex failed");
559 return;
560 }
561
562 voice_buf = core_get_data(voice_buf_hid);
563
564 if (voice_buf == NULL)
565 {
566 logf("voice: core_get_data failed");
567 core_free(voice_buf_hid);
568 voice_buf_hid = 0;
569 return;
570 }
571
Michael Sevakis8bbd4d92012-05-17 11:16:20 -0400572 memset(voice_buf, 0, sizeof (*voice_buf));
573
Michael Sevakis99617d72007-11-18 17:12:19 +0000574 logf("Starting voice thread");
575 queue_init(&voice_queue, false);
Michael Sevakiseffceea2008-10-23 13:13:00 +0000576
Michael Sevakis8cfbd362008-12-10 08:57:10 +0000577 voice_thread_id = create_thread(voice_thread, voice_stack,
Michael Sevakis6d3a6f72011-09-01 07:32:07 +0000578 sizeof(voice_stack), 0, voice_thread_name
579 IF_PRIO(, PRIORITY_VOICE) IF_COP(, CPU));
Michael Sevakis27cf6772008-03-25 02:34:12 +0000580
581 queue_enable_queue_send(&voice_queue, &voice_queue_sender_list,
Michael Sevakis8cfbd362008-12-10 08:57:10 +0000582 voice_thread_id);
Michael Sevakis99617d72007-11-18 17:12:19 +0000583}
584
585#ifdef HAVE_PRIORITY_SCHEDULING
586/* Set the voice thread priority */
587void voice_thread_set_priority(int priority)
588{
Michael Sevakisda6cebb2012-05-02 17:22:28 -0400589 if (voice_thread_id == 0)
590 return;
591
Michael Sevakisa2b67032011-06-29 06:37:04 +0000592 if (priority > PRIORITY_VOICE)
593 priority = PRIORITY_VOICE;
594
Michael Sevakis8cfbd362008-12-10 08:57:10 +0000595 thread_set_priority(voice_thread_id, priority);
Michael Sevakis99617d72007-11-18 17:12:19 +0000596}
597#endif