summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c507
1 files changed, 405 insertions, 102 deletions
diff --git a/apps/playback.c b/apps/playback.c
index e12b01ee55..8829757949 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -60,18 +60,20 @@
60#include "misc.h" 60#include "misc.h"
61#include "sound.h" 61#include "sound.h"
62#include "metadata.h" 62#include "metadata.h"
63#include "talk.h"
63 64
64static volatile bool codec_loaded; 65static volatile bool audio_codec_loaded;
66static volatile bool voice_codec_loaded;
65static volatile bool playing; 67static volatile bool playing;
66static volatile bool paused; 68static volatile bool paused;
67 69
68#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"; 70#define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
69#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"; 71#define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
70#define CODEC_FLAC "/.rockbox/codecs/flac.codec"; 72#define CODEC_FLAC "/.rockbox/codecs/flac.codec"
71#define CODEC_WAV "/.rockbox/codecs/wav.codec"; 73#define CODEC_WAV "/.rockbox/codecs/wav.codec"
72#define CODEC_A52 "/.rockbox/codecs/a52.codec"; 74#define CODEC_A52 "/.rockbox/codecs/a52.codec"
73#define CODEC_MPC "/.rockbox/codecs/mpc.codec"; 75#define CODEC_MPC "/.rockbox/codecs/mpc.codec"
74#define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"; 76#define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"
75 77
76#define AUDIO_FILL_CYCLE (1024*256) 78#define AUDIO_FILL_CYCLE (1024*256)
77#define AUDIO_DEFAULT_WATERMARK (1024*512) 79#define AUDIO_DEFAULT_WATERMARK (1024*512)
@@ -96,6 +98,10 @@ static volatile bool paused;
96#define MALLOC_BUFSIZE (512*1024) 98#define MALLOC_BUFSIZE (512*1024)
97#define GUARD_BUFSIZE (8*1024) 99#define GUARD_BUFSIZE (8*1024)
98 100
101/* As defined in plugin.lds */
102#define CODEC_IRAM_ORIGIN 0x10010000
103#define CODEC_IRAM_SIZE 0x8000
104
99extern bool audio_is_initialized; 105extern bool audio_is_initialized;
100 106
101/* Buffer control thread. */ 107/* Buffer control thread. */
@@ -108,19 +114,39 @@ static struct event_queue codec_queue;
108static long codec_stack[(DEFAULT_STACK_SIZE + 0x2500)/sizeof(long)] IDATA_ATTR; 114static long codec_stack[(DEFAULT_STACK_SIZE + 0x2500)/sizeof(long)] IDATA_ATTR;
109static const char codec_thread_name[] = "codec"; 115static const char codec_thread_name[] = "codec";
110 116
117/* Voice codec thread. */
118static struct event_queue voice_codec_queue;
119/* Not enough IRAM for this. */
120static long voice_codec_stack[(DEFAULT_STACK_SIZE + 0x2500)/sizeof(long)];
121static const char voice_codec_thread_name[] = "voice codec";
122
111static struct mutex mutex_bufferfill; 123static struct mutex mutex_bufferfill;
124static struct mutex mutex_codecthread;
125
126static struct mp3entry id3_voice;
127
128#define CODEC_IDX_AUDIO 0
129#define CODEC_IDX_VOICE 1
130
131static char *voicebuf;
132static int voice_remaining;
133static bool voice_is_playing;
134static void (*voice_getmore)(unsigned char** start, int* size);
112 135
113/* Is file buffer currently being refilled? */ 136/* Is file buffer currently being refilled? */
114static volatile bool filling; 137static volatile bool filling;
115 138
139volatile int current_codec;
140extern unsigned char codecbuf[];
141
116/* Ring buffer where tracks and codecs are loaded. */ 142/* Ring buffer where tracks and codecs are loaded. */
117static char *codecbuf; 143static char *filebuf;
118 144
119/* Total size of the ring buffer. */ 145/* Total size of the ring buffer. */
120int codecbuflen; 146int filebuflen;
121 147
122/* Bytes available in the buffer. */ 148/* Bytes available in the buffer. */
123int codecbufused; 149int filebufused;
124 150
125/* Ring buffer read and write indexes. */ 151/* Ring buffer read and write indexes. */
126static volatile int buf_ridx; 152static volatile int buf_ridx;
@@ -153,6 +179,7 @@ static struct track_info *cur_ti;
153 179
154/* Codec API including function callbacks. */ 180/* Codec API including function callbacks. */
155extern struct codec_api ci; 181extern struct codec_api ci;
182extern struct codec_api ci_voice;
156 183
157/* When we change a song and buffer is not in filling state, this 184/* When we change a song and buffer is not in filling state, this
158 variable keeps information about whether to go a next/previous track. */ 185 variable keeps information about whether to go a next/previous track. */
@@ -174,6 +201,59 @@ static bool v1first = false;
174static void mp3_set_elapsed(struct mp3entry* id3); 201static void mp3_set_elapsed(struct mp3entry* id3);
175int mp3_get_file_pos(void); 202int mp3_get_file_pos(void);
176 203
204static void do_swap(int idx_old, int idx_new)
205{
206#ifndef SIMULATOR
207 unsigned char *iram_p = (unsigned char *)(CODEC_IRAM_ORIGIN);
208 unsigned char *iram_buf[2];
209#endif
210 unsigned char *dram_buf[2];
211
212
213#ifndef SIMULATOR
214 iram_buf[0] = &filebuf[filebuflen];
215 iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE];
216 memcpy(iram_buf[idx_old], iram_p, CODEC_IRAM_SIZE);
217 memcpy(iram_p, iram_buf[idx_new], CODEC_IRAM_SIZE);
218#endif
219
220 dram_buf[0] = &filebuf[filebuflen+CODEC_IRAM_SIZE*2];
221 dram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE];
222 memcpy(dram_buf[idx_old], codecbuf, CODEC_SIZE);
223 memcpy(codecbuf, dram_buf[idx_new], CODEC_SIZE);
224}
225
226static void swap_codec(void)
227{
228 int last_codec;
229
230 logf("swapping codec:%d", current_codec);
231
232 /* We should swap codecs' IRAM contents and code space. */
233 do_swap(current_codec, !current_codec);
234
235 last_codec = current_codec;
236 current_codec = !current_codec;
237
238 /* Release the semaphore and force a task switch. */
239 mutex_unlock(&mutex_codecthread);
240 sleep(1);
241
242 /* Waiting until we are ready to run again. */
243 mutex_lock(&mutex_codecthread);
244
245 /* Check if codec swap did not happen. */
246 if (current_codec != last_codec)
247 {
248 logf("no codec switch happened!");
249 do_swap(current_codec, !current_codec);
250 current_codec = !current_codec;
251 }
252
253 invalidate_icache();
254 logf("codec resuming:%d", current_codec);
255}
256
177bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2, 257bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2,
178 long length) 258 long length)
179{ 259{
@@ -209,12 +289,41 @@ bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2,
209 pcmbuf_flush_buffer(0); 289 pcmbuf_flush_buffer(0);
210 DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n", 290 DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n",
211 output_size, length, input_size); 291 output_size, length, input_size);
212 /* should we really continue, or should we break? */ 292 /* should we really continue, or should we break?
293 * We should probably continue because calling pcmbuf_flush_buffer(0)
294 * will wrap the buffer if it was fully filled and so next call to
295 * pcmbuf_request_buffer should give the requested output_size. */
213 continue; 296 continue;
214 } 297 }
215 298
216 output_size = dsp_process(dest, src, input_size); 299 output_size = dsp_process(dest, src, input_size);
217 pcmbuf_flush_buffer(output_size); 300
301 /* Hotswap between audio and voice codecs as necessary. */
302 switch (current_codec)
303 {
304 case CODEC_IDX_AUDIO:
305 pcmbuf_flush_buffer(output_size);
306 if (voice_is_playing && pcmbuf_usage() > 30
307 && pcmbuf_mix_usage() < 20)
308 {
309 cpu_boost(true);
310 swap_codec();
311 cpu_boost(false);
312 }
313 break ;
314
315 case CODEC_IDX_VOICE:
316 if (audio_codec_loaded) {
317 pcmbuf_mix(dest, output_size);
318 if ((pcmbuf_usage() < 10)
319 || pcmbuf_mix_usage() > 70)
320 swap_codec();
321 } else {
322 pcmbuf_flush_buffer(output_size);
323 }
324 break ;
325 }
326
218 length -= input_size; 327 length -= input_size;
219 } 328 }
220 329
@@ -241,6 +350,9 @@ bool codec_pcmbuf_insert_callback(char *buf, long length)
241void* get_codec_memory_callback(long *size) 350void* get_codec_memory_callback(long *size)
242{ 351{
243 *size = MALLOC_BUFSIZE; 352 *size = MALLOC_BUFSIZE;
353 if (voice_codec_loaded)
354 return &audiobuf[talk_get_bufsize()];
355
244 return &audiobuf[0]; 356 return &audiobuf[0];
245} 357}
246 358
@@ -248,7 +360,7 @@ void codec_set_elapsed_callback(unsigned int value)
248{ 360{
249 unsigned int latency; 361 unsigned int latency;
250 362
251 if (ci.stop_codec) 363 if (ci.stop_codec || current_codec == CODEC_IDX_VOICE)
252 return ; 364 return ;
253 365
254 latency = pcmbuf_get_latency(); 366 latency = pcmbuf_get_latency();
@@ -265,7 +377,7 @@ void codec_set_offset_callback(unsigned int value)
265{ 377{
266 unsigned int latency; 378 unsigned int latency;
267 379
268 if (ci.stop_codec) 380 if (ci.stop_codec || current_codec == CODEC_IDX_VOICE)
269 return ; 381 return ;
270 382
271 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8; 383 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
@@ -283,7 +395,7 @@ long codec_filebuf_callback(void *ptr, long size)
283 int copy_n; 395 int copy_n;
284 int part_n; 396 int part_n;
285 397
286 if (ci.stop_codec || !playing) 398 if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
287 return 0; 399 return 0;
288 400
289 copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem); 401 copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem);
@@ -297,26 +409,78 @@ long codec_filebuf_callback(void *ptr, long size)
297 if (copy_n == 0) 409 if (copy_n == 0)
298 return 0; 410 return 0;
299 411
300 part_n = MIN(copy_n, codecbuflen - buf_ridx); 412 part_n = MIN(copy_n, filebuflen - buf_ridx);
301 memcpy(buf, &codecbuf[buf_ridx], part_n); 413 memcpy(buf, &filebuf[buf_ridx], part_n);
302 if (part_n < copy_n) { 414 if (part_n < copy_n) {
303 memcpy(&buf[part_n], &codecbuf[0], copy_n - part_n); 415 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
304 } 416 }
305 417
306 buf_ridx += copy_n; 418 buf_ridx += copy_n;
307 if (buf_ridx >= codecbuflen) 419 if (buf_ridx >= filebuflen)
308 buf_ridx -= codecbuflen; 420 buf_ridx -= filebuflen;
309 ci.curpos += copy_n; 421 ci.curpos += copy_n;
310 cur_ti->available -= copy_n; 422 cur_ti->available -= copy_n;
311 codecbufused -= copy_n; 423 filebufused -= copy_n;
312 424
313 return copy_n; 425 return copy_n;
314} 426}
315 427
428void* voice_request_data(long *realsize, long reqsize)
429{
430 while (queue_empty(&voice_codec_queue) && (voice_remaining == 0
431 || voicebuf == NULL) && !ci_voice.stop_codec)
432 {
433 yield();
434 if (audio_codec_loaded && (pcmbuf_usage() < 30
435 || !voice_is_playing || voicebuf == NULL))
436 {
437 swap_codec();
438 }
439 if (!voice_is_playing)
440 sleep(HZ/16);
441
442 if (voice_remaining)
443 {
444 voice_is_playing = true;
445 break ;
446 }
447
448 if (voice_getmore != NULL)
449 {
450 voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
451
452 if (!voice_remaining)
453 {
454 voice_is_playing = false;
455 /* Force pcm playback. */
456 pcmbuf_play_start();
457 }
458 }
459 }
460
461 if (reqsize < 0)
462 reqsize = 0;
463
464 voice_is_playing = true;
465 *realsize = voice_remaining;
466 if (*realsize > reqsize)
467 *realsize = reqsize;
468
469 if (*realsize == 0)
470 return NULL;
471
472 return voicebuf;
473}
474
316void* codec_request_buffer_callback(long *realsize, long reqsize) 475void* codec_request_buffer_callback(long *realsize, long reqsize)
317{ 476{
318 long part_n; 477 long part_n;
319 478
479 /* Voice codec. */
480 if (current_codec == CODEC_IDX_VOICE) {
481 return voice_request_data(realsize, reqsize);
482 }
483
320 if (ci.stop_codec || !playing) { 484 if (ci.stop_codec || !playing) {
321 *realsize = 0; 485 *realsize = 0;
322 return NULL; 486 return NULL;
@@ -335,22 +499,22 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
335 } 499 }
336 } 500 }
337 501
338 part_n = MIN((int)*realsize, codecbuflen - buf_ridx); 502 part_n = MIN((int)*realsize, filebuflen - buf_ridx);
339 if (part_n < *realsize) { 503 if (part_n < *realsize) {
340 part_n += GUARD_BUFSIZE; 504 part_n += GUARD_BUFSIZE;
341 if (part_n < *realsize) 505 if (part_n < *realsize)
342 *realsize = part_n; 506 *realsize = part_n;
343 memcpy(&codecbuf[codecbuflen], &codecbuf[0], *realsize - 507 memcpy(&filebuf[filebuflen], &filebuf[0], *realsize -
344 (codecbuflen - buf_ridx)); 508 (filebuflen - buf_ridx));
345 } 509 }
346 510
347 return (char *)&codecbuf[buf_ridx]; 511 return (char *)&filebuf[buf_ridx];
348} 512}
349 513
350static bool rebuffer_and_seek(int newpos) 514static bool rebuffer_and_seek(int newpos)
351{ 515{
352 int fd; 516 int fd;
353 517
354 logf("Re-buffering song"); 518 logf("Re-buffering song");
355 mutex_lock(&mutex_bufferfill); 519 mutex_lock(&mutex_bufferfill);
356 520
@@ -367,7 +531,7 @@ static bool rebuffer_and_seek(int newpos)
367 531
368 /* Clear codec buffer. */ 532 /* Clear codec buffer. */
369 audio_invalidate_tracks(); 533 audio_invalidate_tracks();
370 codecbufused = 0; 534 filebufused = 0;
371 buf_ridx = buf_widx = 0; 535 buf_ridx = buf_widx = 0;
372 cur_ti->filerem = cur_ti->filesize - newpos; 536 cur_ti->filerem = cur_ti->filesize - newpos;
373 cur_ti->filepos = newpos; 537 cur_ti->filepos = newpos;
@@ -390,6 +554,15 @@ static bool rebuffer_and_seek(int newpos)
390 554
391void codec_advance_buffer_callback(long amount) 555void codec_advance_buffer_callback(long amount)
392{ 556{
557 if (current_codec == CODEC_IDX_VOICE) {
558 //logf("voice ad.buf:%d", amount);
559 amount = MAX(0, MIN(amount, voice_remaining));
560 voicebuf += amount;
561 voice_remaining -= amount;
562
563 return ;
564 }
565
393 if (amount > cur_ti->available + cur_ti->filerem) 566 if (amount > cur_ti->available + cur_ti->filerem)
394 amount = cur_ti->available + cur_ti->filerem; 567 amount = cur_ti->available + cur_ti->filerem;
395 568
@@ -400,10 +573,10 @@ void codec_advance_buffer_callback(long amount)
400 } 573 }
401 574
402 buf_ridx += amount; 575 buf_ridx += amount;
403 if (buf_ridx >= codecbuflen) 576 if (buf_ridx >= filebuflen)
404 buf_ridx -= codecbuflen; 577 buf_ridx -= filebuflen;
405 cur_ti->available -= amount; 578 cur_ti->available -= amount;
406 codecbufused -= amount; 579 filebufused -= amount;
407 ci.curpos += amount; 580 ci.curpos += amount;
408 codec_set_offset_callback(ci.curpos); 581 codec_set_offset_callback(ci.curpos);
409} 582}
@@ -411,15 +584,18 @@ void codec_advance_buffer_callback(long amount)
411void codec_advance_buffer_loc_callback(void *ptr) 584void codec_advance_buffer_loc_callback(void *ptr)
412{ 585{
413 long amount; 586 long amount;
414 587
415 amount = (int)ptr - (int)&codecbuf[buf_ridx]; 588 if (current_codec == CODEC_IDX_VOICE)
589 amount = (int)ptr - (int)voicebuf;
590 else
591 amount = (int)ptr - (int)&filebuf[buf_ridx];
416 codec_advance_buffer_callback(amount); 592 codec_advance_buffer_callback(amount);
417} 593}
418 594
419off_t codec_mp3_get_filepos_callback(int newtime) 595off_t codec_mp3_get_filepos_callback(int newtime)
420{ 596{
421 off_t newpos; 597 off_t newpos;
422 598
423 cur_ti->id3.elapsed = newtime; 599 cur_ti->id3.elapsed = newtime;
424 newpos = mp3_get_file_pos(); 600 newpos = mp3_get_file_pos();
425 601
@@ -429,7 +605,10 @@ off_t codec_mp3_get_filepos_callback(int newtime)
429bool codec_seek_buffer_callback(off_t newpos) 605bool codec_seek_buffer_callback(off_t newpos)
430{ 606{
431 int difference; 607 int difference;
432 608
609 if (current_codec == CODEC_IDX_VOICE)
610 return false;
611
433 if (newpos < 0) 612 if (newpos < 0)
434 newpos = 0; 613 newpos = 0;
435 614
@@ -457,11 +636,11 @@ bool codec_seek_buffer_callback(off_t newpos)
457 636
458 /* Seeking inside buffer space. */ 637 /* Seeking inside buffer space. */
459 logf("seek: -%d", difference); 638 logf("seek: -%d", difference);
460 codecbufused += difference; 639 filebufused += difference;
461 cur_ti->available += difference; 640 cur_ti->available += difference;
462 buf_ridx -= difference; 641 buf_ridx -= difference;
463 if (buf_ridx < 0) 642 if (buf_ridx < 0)
464 buf_ridx = codecbuflen + buf_ridx; 643 buf_ridx = filebuflen + buf_ridx;
465 ci.curpos -= difference; 644 ci.curpos -= difference;
466 if (!pcmbuf_is_crossfade_active()) 645 if (!pcmbuf_is_crossfade_active())
467 pcmbuf_play_stop(); 646 pcmbuf_play_stop();
@@ -473,8 +652,11 @@ static void set_filebuf_watermark(int seconds)
473{ 652{
474 long bytes; 653 long bytes;
475 654
655 if (current_codec == CODEC_IDX_VOICE)
656 return ;
657
476 bytes = MAX((int)cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark); 658 bytes = MAX((int)cur_ti->id3.bitrate * seconds * (1000/8), conf_watermark);
477 bytes = MIN(bytes, codecbuflen / 2); 659 bytes = MIN(bytes, filebuflen / 2);
478 conf_watermark = bytes; 660 conf_watermark = bytes;
479} 661}
480 662
@@ -540,7 +722,7 @@ void yield_codecs(void)
540 sleep(5); 722 sleep(5);
541 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata()) 723 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
542 && !ci.stop_codec && playing && queue_empty(&audio_queue) 724 && !ci.stop_codec && playing && queue_empty(&audio_queue)
543 && codecbufused > (128*1024)) 725 && filebufused > (128*1024))
544 yield(); 726 yield();
545} 727}
546 728
@@ -552,18 +734,18 @@ void strip_id3v1_tag(void)
552 int tagptr; 734 int tagptr;
553 bool found = true; 735 bool found = true;
554 736
555 if (codecbufused >= 128) 737 if (filebufused >= 128)
556 { 738 {
557 tagptr = buf_widx - 128; 739 tagptr = buf_widx - 128;
558 if (tagptr < 0) 740 if (tagptr < 0)
559 tagptr += codecbuflen; 741 tagptr += filebuflen;
560 742
561 for(i = 0;i < 3;i++) 743 for(i = 0;i < 3;i++)
562 { 744 {
563 if(tagptr >= codecbuflen) 745 if(tagptr >= filebuflen)
564 tagptr -= codecbuflen; 746 tagptr -= filebuflen;
565 747
566 if(codecbuf[tagptr] != tag[i]) 748 if(filebuf[tagptr] != tag[i])
567 { 749 {
568 found = false; 750 found = false;
569 break; 751 break;
@@ -578,7 +760,7 @@ void strip_id3v1_tag(void)
578 logf("Skipping ID3v1 tag\n"); 760 logf("Skipping ID3v1 tag\n");
579 buf_widx -= 128; 761 buf_widx -= 128;
580 tracks[track_widx].available -= 128; 762 tracks[track_widx].available -= 128;
581 codecbufused -= 128; 763 filebufused -= 128;
582 } 764 }
583 } 765 }
584} 766}
@@ -603,9 +785,9 @@ void audio_fill_file_buffer(void)
603 785
604 if (fill_bytesleft == 0) 786 if (fill_bytesleft == 0)
605 break ; 787 break ;
606 rc = MIN(conf_filechunk, codecbuflen - buf_widx); 788 rc = MIN(conf_filechunk, filebuflen - buf_widx);
607 rc = MIN(rc, fill_bytesleft); 789 rc = MIN(rc, fill_bytesleft);
608 rc = read(current_fd, &codecbuf[buf_widx], rc); 790 rc = read(current_fd, &filebuf[buf_widx], rc);
609 if (rc <= 0) { 791 if (rc <= 0) {
610 tracks[track_widx].filerem = 0; 792 tracks[track_widx].filerem = 0;
611 strip_id3v1_tag(); 793 strip_id3v1_tag();
@@ -613,13 +795,13 @@ void audio_fill_file_buffer(void)
613 } 795 }
614 796
615 buf_widx += rc; 797 buf_widx += rc;
616 if (buf_widx >= codecbuflen) 798 if (buf_widx >= filebuflen)
617 buf_widx -= codecbuflen; 799 buf_widx -= filebuflen;
618 i += rc; 800 i += rc;
619 tracks[track_widx].available += rc; 801 tracks[track_widx].available += rc;
620 tracks[track_widx].filerem -= rc; 802 tracks[track_widx].filerem -= rc;
621 tracks[track_widx].filepos += rc; 803 tracks[track_widx].filepos += rc;
622 codecbufused += rc; 804 filebufused += rc;
623 fill_bytesleft -= rc; 805 fill_bytesleft -= rc;
624 } 806 }
625 807
@@ -725,15 +907,15 @@ bool loadcodec(const char *trackname, bool start_play)
725 while (i < size) { 907 while (i < size) {
726 yield_codecs(); 908 yield_codecs();
727 909
728 copy_n = MIN(conf_filechunk, codecbuflen - buf_widx); 910 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
729 rc = read(fd, &codecbuf[buf_widx], copy_n); 911 rc = read(fd, &filebuf[buf_widx], copy_n);
730 if (rc < 0) 912 if (rc < 0)
731 return false; 913 return false;
732 buf_widx += rc; 914 buf_widx += rc;
733 codecbufused += rc; 915 filebufused += rc;
734 fill_bytesleft -= rc; 916 fill_bytesleft -= rc;
735 if (buf_widx >= codecbuflen) 917 if (buf_widx >= filebuflen)
736 buf_widx -= codecbuflen; 918 buf_widx -= filebuflen;
737 i += rc; 919 i += rc;
738 } 920 }
739 close(fd); 921 close(fd);
@@ -840,20 +1022,23 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
840 tracks[track_widx].playlist_offset = peek_offset; 1022 tracks[track_widx].playlist_offset = peek_offset;
841 last_peek_offset = peek_offset; 1023 last_peek_offset = peek_offset;
842 1024
843 if (buf_widx >= codecbuflen) 1025 if (buf_widx >= filebuflen)
844 buf_widx -= codecbuflen; 1026 buf_widx -= filebuflen;
845 1027
846 /* Set default values */ 1028 /* Set default values */
847 if (start_play) { 1029 if (start_play) {
1030 int last_codec = current_codec;
1031 current_codec = CODEC_IDX_AUDIO;
848 conf_bufferlimit = 0; 1032 conf_bufferlimit = 0;
849 conf_watermark = AUDIO_DEFAULT_WATERMARK; 1033 conf_watermark = AUDIO_DEFAULT_WATERMARK;
850 conf_filechunk = AUDIO_DEFAULT_FILECHUNK; 1034 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
851 dsp_configure(DSP_RESET, 0); 1035 dsp_configure(DSP_RESET, 0);
852 ci.configure(CODEC_DSP_ENABLE, false); 1036 ci.configure(CODEC_DSP_ENABLE, false);
1037 current_codec = last_codec;
853 } 1038 }
854 1039
855 /* Load the codec. */ 1040 /* Load the codec. */
856 tracks[track_widx].codecbuf = &codecbuf[buf_widx]; 1041 tracks[track_widx].codecbuf = &filebuf[buf_widx];
857 if (!loadcodec(trackname, start_play)) { 1042 if (!loadcodec(trackname, start_play)) {
858 close(fd); 1043 close(fd);
859 /* Stop buffer filling if codec load failed. */ 1044 /* Stop buffer filling if codec load failed. */
@@ -870,7 +1055,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
870 } 1055 }
871 return false; 1056 return false;
872 } 1057 }
873 // tracks[track_widx].filebuf = &codecbuf[buf_widx]; 1058 // tracks[track_widx].filebuf = &filebuf[buf_widx];
874 tracks[track_widx].start_pos = 0; 1059 tracks[track_widx].start_pos = 0;
875 1060
876 /* Get track metadata if we don't already have it. */ 1061 /* Get track metadata if we don't already have it. */
@@ -933,10 +1118,10 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
933 if (fill_bytesleft == 0) 1118 if (fill_bytesleft == 0)
934 break ; 1119 break ;
935 1120
936 copy_n = MIN(conf_filechunk, codecbuflen - buf_widx); 1121 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
937 copy_n = MIN(size - i, copy_n); 1122 copy_n = MIN(size - i, copy_n);
938 copy_n = MIN((int)fill_bytesleft, copy_n); 1123 copy_n = MIN((int)fill_bytesleft, copy_n);
939 rc = read(fd, &codecbuf[buf_widx], copy_n); 1124 rc = read(fd, &filebuf[buf_widx], copy_n);
940 if (rc < copy_n) { 1125 if (rc < copy_n) {
941 logf("File error!"); 1126 logf("File error!");
942 tracks[track_widx].filesize = 0; 1127 tracks[track_widx].filesize = 0;
@@ -945,12 +1130,12 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
945 return false; 1130 return false;
946 } 1131 }
947 buf_widx += rc; 1132 buf_widx += rc;
948 if (buf_widx >= codecbuflen) 1133 if (buf_widx >= filebuflen)
949 buf_widx -= codecbuflen; 1134 buf_widx -= filebuflen;
950 i += rc; 1135 i += rc;
951 tracks[track_widx].available += rc; 1136 tracks[track_widx].available += rc;
952 tracks[track_widx].filerem -= rc; 1137 tracks[track_widx].filerem -= rc;
953 codecbufused += rc; 1138 filebufused += rc;
954 fill_bytesleft -= rc; 1139 fill_bytesleft -= rc;
955 } 1140 }
956 1141
@@ -997,10 +1182,10 @@ void audio_play_start(int offset)
997 track_ridx = 0; 1182 track_ridx = 0;
998 buf_ridx = 0; 1183 buf_ridx = 0;
999 buf_widx = 0; 1184 buf_widx = 0;
1000 codecbufused = 0; 1185 filebufused = 0;
1001 pcmbuf_set_boost_mode(true); 1186 pcmbuf_set_boost_mode(true);
1002 1187
1003 fill_bytesleft = codecbuflen; 1188 fill_bytesleft = filebuflen;
1004 filling = true; 1189 filling = true;
1005 last_peek_offset = -1; 1190 last_peek_offset = -1;
1006 if (audio_load_track(offset, true, 0)) { 1191 if (audio_load_track(offset, true, 0)) {
@@ -1089,7 +1274,7 @@ void initialize_buffer_fill(void)
1089 int cur_idx, i; 1274 int cur_idx, i;
1090 1275
1091 1276
1092 fill_bytesleft = codecbuflen - codecbufused; 1277 fill_bytesleft = filebuflen - filebufused;
1093 cur_ti->start_pos = ci.curpos; 1278 cur_ti->start_pos = ci.curpos;
1094 1279
1095 pcmbuf_set_boost_mode(true); 1280 pcmbuf_set_boost_mode(true);
@@ -1124,7 +1309,7 @@ void initialize_buffer_fill(void)
1124void audio_check_buffer(void) 1309void audio_check_buffer(void)
1125{ 1310{
1126 /* Start buffer filling as necessary. */ 1311 /* Start buffer filling as necessary. */
1127 if ((codecbufused > conf_watermark || !queue_empty(&audio_queue) 1312 if ((filebufused > conf_watermark || !queue_empty(&audio_queue)
1128 || !playing || ci.stop_codec || ci.reload_codec) && !filling) 1313 || !playing || ci.stop_codec || ci.reload_codec) && !filling)
1129 return ; 1314 return ;
1130 1315
@@ -1132,8 +1317,8 @@ void audio_check_buffer(void)
1132 1317
1133 /* Limit buffering size at first run. */ 1318 /* Limit buffering size at first run. */
1134 if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit 1319 if (conf_bufferlimit && fill_bytesleft > conf_bufferlimit
1135 - codecbufused) { 1320 - filebufused) {
1136 fill_bytesleft = MAX(0, conf_bufferlimit - codecbufused); 1321 fill_bytesleft = MAX(0, conf_bufferlimit - filebufused);
1137 } 1322 }
1138 1323
1139 /* Try to load remainings of the file. */ 1324 /* Try to load remainings of the file. */
@@ -1169,27 +1354,27 @@ void audio_update_trackinfo(void)
1169{ 1354{
1170 if (new_track >= 0) { 1355 if (new_track >= 0) {
1171 buf_ridx += cur_ti->available; 1356 buf_ridx += cur_ti->available;
1172 codecbufused -= cur_ti->available; 1357 filebufused -= cur_ti->available;
1173 1358
1174 cur_ti = &tracks[track_ridx]; 1359 cur_ti = &tracks[track_ridx];
1175 buf_ridx += cur_ti->codecsize; 1360 buf_ridx += cur_ti->codecsize;
1176 codecbufused -= cur_ti->codecsize; 1361 filebufused -= cur_ti->codecsize;
1177 if (buf_ridx >= codecbuflen) 1362 if (buf_ridx >= filebuflen)
1178 buf_ridx -= codecbuflen; 1363 buf_ridx -= filebuflen;
1179 1364
1180 if (!filling) 1365 if (!filling)
1181 pcmbuf_set_boost_mode(false); 1366 pcmbuf_set_boost_mode(false);
1182 } else { 1367 } else {
1183 buf_ridx -= ci.curpos + cur_ti->codecsize; 1368 buf_ridx -= ci.curpos + cur_ti->codecsize;
1184 codecbufused += ci.curpos + cur_ti->codecsize; 1369 filebufused += ci.curpos + cur_ti->codecsize;
1185 cur_ti->available = cur_ti->filesize; 1370 cur_ti->available = cur_ti->filesize;
1186 1371
1187 cur_ti = &tracks[track_ridx]; 1372 cur_ti = &tracks[track_ridx];
1188 buf_ridx -= cur_ti->filesize; 1373 buf_ridx -= cur_ti->filesize;
1189 codecbufused += cur_ti->filesize; 1374 filebufused += cur_ti->filesize;
1190 cur_ti->available = cur_ti->filesize; 1375 cur_ti->available = cur_ti->filesize;
1191 if (buf_ridx < 0) 1376 if (buf_ridx < 0)
1192 buf_ridx = codecbuflen + buf_ridx; 1377 buf_ridx = filebuflen + buf_ridx;
1193 } 1378 }
1194 1379
1195 ci.filesize = cur_ti->filesize; 1380 ci.filesize = cur_ti->filesize;
@@ -1220,7 +1405,7 @@ static void audio_stop_playback(void)
1220 current_fd = -1; 1405 current_fd = -1;
1221 } 1406 }
1222 pcmbuf_play_stop(); 1407 pcmbuf_play_stop();
1223 while (codec_loaded) 1408 while (audio_codec_loaded)
1224 yield(); 1409 yield();
1225 pcm_play_pause(true); 1410 pcm_play_pause(true);
1226 track_count = 0; 1411 track_count = 0;
@@ -1267,6 +1452,11 @@ static int get_codec_base_type(int type)
1267 1452
1268bool codec_request_next_track_callback(void) 1453bool codec_request_next_track_callback(void)
1269{ 1454{
1455 if (current_codec == CODEC_IDX_VOICE) {
1456 voice_remaining = 0;
1457 return !ci_voice.stop_codec;
1458 }
1459
1270 if (ci.stop_codec || !playing) 1460 if (ci.stop_codec || !playing)
1271 return false; 1461 return false;
1272 1462
@@ -1309,8 +1499,8 @@ bool codec_request_next_track_callback(void)
1309 if (--track_ridx < 0) 1499 if (--track_ridx < 0)
1310 track_ridx = MAX_TRACK-1; 1500 track_ridx = MAX_TRACK-1;
1311 if (tracks[track_ridx].filesize == 0 || 1501 if (tracks[track_ridx].filesize == 0 ||
1312 codecbufused+ci.curpos+tracks[track_ridx].filesize 1502 filebufused+ci.curpos+tracks[track_ridx].filesize
1313 /*+ (off_t)tracks[track_ridx].codecsize*/ > codecbuflen) { 1503 /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen) {
1314 logf("Loading from disk..."); 1504 logf("Loading from disk...");
1315 new_track = 0; 1505 new_track = 0;
1316 last_index = -1; 1506 last_index = -1;
@@ -1379,10 +1569,10 @@ void audio_invalidate_tracks(void)
1379 track_widx = track_ridx; 1569 track_widx = track_ridx;
1380 /* Mark all other entries null (also buffered wrong metadata). */ 1570 /* Mark all other entries null (also buffered wrong metadata). */
1381 audio_clear_track_entries(false); 1571 audio_clear_track_entries(false);
1382 codecbufused = cur_ti->available; 1572 filebufused = cur_ti->available;
1383 buf_widx = buf_ridx + cur_ti->available; 1573 buf_widx = buf_ridx + cur_ti->available;
1384 if (buf_widx >= codecbuflen) 1574 if (buf_widx >= filebuflen)
1385 buf_widx -= codecbuflen; 1575 buf_widx -= filebuflen;
1386 read_next_metadata(); 1576 read_next_metadata();
1387} 1577}
1388 1578
@@ -1436,7 +1626,7 @@ void audio_thread(void)
1436 ci.reload_codec = false; 1626 ci.reload_codec = false;
1437 ci.seek_time = 0; 1627 ci.seek_time = 0;
1438 pcmbuf_crossfade_init(CROSSFADE_MODE_CROSSFADE); 1628 pcmbuf_crossfade_init(CROSSFADE_MODE_CROSSFADE);
1439 while (codec_loaded) 1629 while (audio_codec_loaded)
1440 yield(); 1630 yield();
1441 audio_play_start((int)ev.data); 1631 audio_play_start((int)ev.data);
1442 playlist_update_resume_info(audio_current_track()); 1632 playlist_update_resume_info(audio_current_track());
@@ -1462,11 +1652,13 @@ void audio_thread(void)
1462 1652
1463 case AUDIO_NEXT: 1653 case AUDIO_NEXT:
1464 logf("audio_next"); 1654 logf("audio_next");
1655 pcmbuf_beep(5000, 100, 5000);
1465 initiate_track_change(1); 1656 initiate_track_change(1);
1466 break ; 1657 break ;
1467 1658
1468 case AUDIO_PREV: 1659 case AUDIO_PREV:
1469 logf("audio_prev"); 1660 logf("audio_prev");
1661 pcmbuf_beep(5000, 100, 5000);
1470 initiate_track_change(-1); 1662 initiate_track_change(-1);
1471 break; 1663 break;
1472 1664
@@ -1514,8 +1706,11 @@ void codec_thread(void)
1514 switch (ev.id) { 1706 switch (ev.id) {
1515 case CODEC_LOAD_DISK: 1707 case CODEC_LOAD_DISK:
1516 ci.stop_codec = false; 1708 ci.stop_codec = false;
1517 codec_loaded = true; 1709 audio_codec_loaded = true;
1518 status = codec_load_file((char *)ev.data); 1710 mutex_lock(&mutex_codecthread);
1711 current_codec = CODEC_IDX_AUDIO;
1712 status = codec_load_file((char *)ev.data, &ci);
1713 mutex_unlock(&mutex_codecthread);
1519 break ; 1714 break ;
1520 1715
1521 case CODEC_LOAD: 1716 case CODEC_LOAD:
@@ -1531,10 +1726,13 @@ void codec_thread(void)
1531 } 1726 }
1532 1727
1533 ci.stop_codec = false; 1728 ci.stop_codec = false;
1534 wrap = (int)&codecbuf[codecbuflen] - (int)cur_ti->codecbuf; 1729 wrap = (int)&filebuf[filebuflen] - (int)cur_ti->codecbuf;
1535 codec_loaded = true; 1730 audio_codec_loaded = true;
1536 status = codec_load_ram(cur_ti->codecbuf, codecsize, 1731 mutex_lock(&mutex_codecthread);
1537 &codecbuf[0], wrap); 1732 current_codec = CODEC_IDX_AUDIO;
1733 status = codec_load_ram(cur_ti->codecbuf, codecsize,
1734 &filebuf[0], wrap, &ci);
1735 mutex_unlock(&mutex_codecthread);
1538 break ; 1736 break ;
1539 1737
1540#ifndef SIMULATOR 1738#ifndef SIMULATOR
@@ -1545,7 +1743,7 @@ void codec_thread(void)
1545#endif 1743#endif
1546 } 1744 }
1547 1745
1548 codec_loaded = false; 1746 audio_codec_loaded = false;
1549 1747
1550 switch (ev.id) { 1748 switch (ev.id) {
1551 case CODEC_LOAD_DISK: 1749 case CODEC_LOAD_DISK:
@@ -1569,6 +1767,83 @@ void codec_thread(void)
1569 } 1767 }
1570} 1768}
1571 1769
1770static void reset_buffer(void)
1771{
1772 filebuf = &audiobuf[MALLOC_BUFSIZE];
1773 filebuflen = audiobufend - audiobuf - pcmbuf_get_bufsize()
1774 - PCMBUF_GUARD - MALLOC_BUFSIZE - GUARD_BUFSIZE;
1775
1776 if (talk_get_bufsize() && voice_codec_loaded)
1777 {
1778 filebuf = &filebuf[talk_get_bufsize()];
1779 filebuflen -= 2*CODEC_IRAM_SIZE + 2*CODEC_SIZE + talk_get_bufsize();
1780 }
1781}
1782
1783void voice_codec_thread(void)
1784{
1785 struct event ev;
1786 int status;
1787
1788 current_codec = CODEC_IDX_AUDIO;
1789 voice_codec_loaded = false;
1790 while (1) {
1791 status = 0;
1792 queue_wait(&voice_codec_queue, &ev);
1793 switch (ev.id) {
1794 case CODEC_LOAD_DISK:
1795 logf("Loading voice codec");
1796 audio_stop_playback();
1797 mutex_lock(&mutex_codecthread);
1798 current_codec = CODEC_IDX_VOICE;
1799 dsp_configure(DSP_RESET, 0);
1800 ci.configure(CODEC_DSP_ENABLE, (bool *)true);
1801 voice_remaining = 0;
1802 voice_getmore = NULL;
1803 voice_codec_loaded = true;
1804 reset_buffer();
1805 ci_voice.stop_codec = false;
1806
1807 status = codec_load_file((char *)ev.data, &ci_voice);
1808
1809 logf("Voice codec finished");
1810 audio_stop_playback();
1811 mutex_unlock(&mutex_codecthread);
1812 current_codec = CODEC_IDX_AUDIO;
1813 voice_codec_loaded = false;
1814 reset_buffer();
1815 break ;
1816
1817#ifndef SIMULATOR
1818 case SYS_USB_CONNECTED:
1819 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1820 usb_wait_for_disconnect(&voice_codec_queue);
1821 break ;
1822#endif
1823 }
1824 }
1825}
1826
1827void voice_init(void)
1828{
1829 while (voice_codec_loaded)
1830 {
1831 logf("Terminating voice codec");
1832 ci_voice.stop_codec = true;
1833 if (current_codec != CODEC_IDX_VOICE)
1834 swap_codec();
1835 sleep(1);
1836 }
1837
1838 if (!talk_get_bufsize())
1839 return ;
1840
1841 logf("Starting voice codec");
1842 queue_post(&voice_codec_queue, CODEC_LOAD_DISK, (void *)CODEC_MPA_L3);
1843 while (!voice_codec_loaded)
1844 sleep(1);
1845}
1846
1572struct mp3entry* audio_current_track(void) 1847struct mp3entry* audio_current_track(void)
1573{ 1848{
1574 // logf("audio_current_track"); 1849 // logf("audio_current_track");
@@ -1620,7 +1895,7 @@ void audio_stop(void)
1620{ 1895{
1621 logf("audio_stop"); 1896 logf("audio_stop");
1622 queue_post(&audio_queue, AUDIO_STOP, 0); 1897 queue_post(&audio_queue, AUDIO_STOP, 0);
1623 while (playing || codec_loaded) 1898 while (playing || audio_codec_loaded)
1624 yield(); 1899 yield();
1625} 1900}
1626 1901
@@ -1805,6 +2080,16 @@ int mp3_get_file_pos(void)
1805 return pos; 2080 return pos;
1806} 2081}
1807 2082
2083void mp3_play_data(const unsigned char* start, int size,
2084 void (*get_more)(unsigned char** start, int* size))
2085{
2086 voice_getmore = get_more;
2087 voicebuf = (unsigned char *)start;
2088 voice_remaining = size;
2089 voice_is_playing = true;
2090 pcmbuf_reset_mixpos();
2091}
2092
1808void audio_set_buffer_margin(int setting) 2093void audio_set_buffer_margin(int setting)
1809{ 2094{
1810 int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600}; 2095 int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
@@ -1827,7 +2112,7 @@ void audio_set_crossfade(int type)
1827 offset = cur_ti->id3.offset; 2112 offset = cur_ti->id3.offset;
1828 2113
1829 if (type == CROSSFADE_MODE_OFF) 2114 if (type == CROSSFADE_MODE_OFF)
1830 seconds = 0; 2115 seconds = 1;
1831 2116
1832 /* Buffer has to be at least 2s long. */ 2117 /* Buffer has to be at least 2s long. */
1833 seconds += 2; 2118 seconds += 2;
@@ -1843,12 +2128,13 @@ void audio_set_crossfade(int type)
1843 if (was_playing) 2128 if (was_playing)
1844 splash(0, true, str(LANG_RESTARTING_PLAYBACK)); 2129 splash(0, true, str(LANG_RESTARTING_PLAYBACK));
1845 pcmbuf_init(size); 2130 pcmbuf_init(size);
1846 pcmbuf_crossfade_enable(seconds > 2); 2131 pcmbuf_crossfade_enable(type != CROSSFADE_MODE_OFF);
1847 codecbuflen = audiobufend - audiobuf - pcmbuf_get_bufsize() 2132 reset_buffer();
1848 - PCMBUF_GUARD - MALLOC_BUFSIZE - GUARD_BUFSIZE;
1849 logf("abuf:%dB", pcmbuf_get_bufsize()); 2133 logf("abuf:%dB", pcmbuf_get_bufsize());
1850 logf("fbuf:%dB", codecbuflen); 2134 logf("fbuf:%dB", filebuflen);
1851 2135
2136 voice_init();
2137
1852 /* Restart playback. */ 2138 /* Restart playback. */
1853 if (was_playing) { 2139 if (was_playing) {
1854 audio_play(offset); 2140 audio_play(offset);
@@ -1856,7 +2142,7 @@ void audio_set_crossfade(int type)
1856 /* Wait for the playback to start again (and display the splash 2142 /* Wait for the playback to start again (and display the splash
1857 screen during that period. */ 2143 screen during that period. */
1858 playing = true; 2144 playing = true;
1859 while (playing && !codec_loaded) 2145 while (playing && !audio_codec_loaded)
1860 yield(); 2146 yield();
1861 } 2147 }
1862} 2148}
@@ -1884,13 +2170,17 @@ void test_unbuffer_event(struct mp3entry *id3, bool last_track)
1884 2170
1885void audio_init(void) 2171void audio_init(void)
1886{ 2172{
2173 static bool voicetagtrue = true;
2174
1887 logf("audio api init"); 2175 logf("audio api init");
1888 pcm_init(); 2176 pcm_init();
1889 codecbufused = 0; 2177 filebufused = 0;
1890 filling = false; 2178 filling = false;
1891 codecbuf = &audiobuf[MALLOC_BUFSIZE]; 2179 current_codec = CODEC_IDX_AUDIO;
2180 filebuf = &audiobuf[MALLOC_BUFSIZE];
1892 playing = false; 2181 playing = false;
1893 codec_loaded = false; 2182 audio_codec_loaded = false;
2183 voice_is_playing = false;
1894 paused = false; 2184 paused = false;
1895 track_changed = false; 2185 track_changed = false;
1896 current_fd = -1; 2186 current_fd = -1;
@@ -1918,12 +2208,25 @@ void audio_init(void)
1918 ci.set_offset = codec_set_offset_callback; 2208 ci.set_offset = codec_set_offset_callback;
1919 ci.configure = codec_configure_callback; 2209 ci.configure = codec_configure_callback;
1920 2210
2211 memcpy(&ci_voice, &ci, sizeof(struct codec_api));
2212 memset(&id3_voice, 0, sizeof(struct mp3entry));
2213 ci_voice.taginfo_ready = &voicetagtrue;
2214 ci_voice.id3 = &id3_voice;
2215 ci_voice.pcmbuf_insert = codec_pcmbuf_insert_callback;
2216 id3_voice.frequency = 11200;
2217 id3_voice.length = 1000000L;
2218
1921 mutex_init(&mutex_bufferfill); 2219 mutex_init(&mutex_bufferfill);
2220 mutex_init(&mutex_codecthread);
2221
1922 queue_init(&audio_queue); 2222 queue_init(&audio_queue);
1923 queue_init(&codec_queue); 2223 queue_init(&codec_queue);
2224 queue_init(&voice_codec_queue);
1924 2225
1925 create_thread(codec_thread, codec_stack, sizeof(codec_stack), 2226 create_thread(codec_thread, codec_stack, sizeof(codec_stack),
1926 codec_thread_name); 2227 codec_thread_name);
2228 create_thread(voice_codec_thread, voice_codec_stack,
2229 sizeof(voice_codec_stack), voice_codec_thread_name);
1927 create_thread(audio_thread, audio_stack, sizeof(audio_stack), 2230 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
1928 audio_thread_name); 2231 audio_thread_name);
1929} 2232}