summaryrefslogtreecommitdiff
path: root/apps/talk.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/talk.c')
-rw-r--r--apps/talk.c105
1 files changed, 6 insertions, 99 deletions
diff --git a/apps/talk.c b/apps/talk.c
index 3aedaf34ec..4b65700a5d 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -32,11 +32,7 @@
32#include "settings.h" 32#include "settings.h"
33#include "settings_list.h" 33#include "settings_list.h"
34#include "splash.h" 34#include "splash.h"
35#if CONFIG_CODEC == SWCODEC
36#include "voice_thread.h" 35#include "voice_thread.h"
37#else
38#include "mp3_playback.h"
39#endif
40#include "audio.h" 36#include "audio.h"
41#include "lang.h" 37#include "lang.h"
42#include "talk.h" 38#include "talk.h"
@@ -107,7 +103,7 @@ struct voicefile_header /* file format of our voice file */
107 103
108/***************** Globals *****************/ 104/***************** Globals *****************/
109 105
110#if (CONFIG_CODEC == SWCODEC && MEMORYSIZE <= 2) 106#if MEMORYSIZE <= 2
111/* On low memory swcodec targets the entire voice file wouldn't fit in memory 107/* On low memory swcodec targets the entire voice file wouldn't fit in memory
112 * together with codecs, so we load clips each time they are accessed. */ 108 * together with codecs, so we load clips each time they are accessed. */
113#define TALK_PROGRESSIVE_LOAD 109#define TALK_PROGRESSIVE_LOAD
@@ -131,15 +127,10 @@ static bool force_enqueue_next; /* enqueue next utterance even if enqueue is fal
131static int queue_write; /* write index of queue, by application */ 127static int queue_write; /* write index of queue, by application */
132static int queue_read; /* read index of queue, by ISR context */ 128static int queue_read; /* read index of queue, by ISR context */
133static enum talk_status talk_status = TALK_STATUS_OK; 129static enum talk_status talk_status = TALK_STATUS_OK;
134#if CONFIG_CODEC == SWCODEC
135/* protects queue_read, queue_write and thumbnail_buf_used */ 130/* protects queue_read, queue_write and thumbnail_buf_used */
136static struct mutex queue_mutex SHAREDBSS_ATTR; 131static struct mutex queue_mutex SHAREDBSS_ATTR;
137#define talk_queue_lock() ({ mutex_lock(&queue_mutex); }) 132#define talk_queue_lock() ({ mutex_lock(&queue_mutex); })
138#define talk_queue_unlock() ({ mutex_unlock(&queue_mutex); }) 133#define talk_queue_unlock() ({ mutex_unlock(&queue_mutex); })
139#else
140#define talk_queue_lock() ({ })
141#define talk_queue_unlock() ({ })
142#endif /* CONFIG_CODEC */
143static int sent; /* how many bytes handed over to playback, owned by ISR */ 134static int sent; /* how many bytes handed over to playback, owned by ISR */
144static unsigned char curr_hd[3]; /* current frame header, for re-sync */ 135static unsigned char curr_hd[3]; /* current frame header, for re-sync */
145static unsigned char last_lang[MAX_FILENAME+1]; /* name of last used lang file (in talk_init) */ 136static unsigned char last_lang[MAX_FILENAME+1]; /* name of last used lang file (in talk_init) */
@@ -186,16 +177,8 @@ static int move_callback(int handle, void *current, void *new)
186 177
187static struct mutex read_buffer_mutex; 178static struct mutex read_buffer_mutex;
188 179
189 180static inline bool check_audio_status(void)
190/* on HWCODEC only voice xor audio can be active at a time */
191static bool check_audio_status(void)
192{ 181{
193#if CONFIG_CODEC != SWCODEC
194 if (audio_status()) /* busy, buffer in use */
195 return false;
196 /* ensure playback is given up on the buffer */
197 audio_hard_stop();
198#endif
199 return true; 182 return true;
200} 183}
201 184
@@ -670,20 +653,16 @@ static bool load_voicefile_data(int fd)
670 return true; 653 return true;
671} 654}
672 655
673/* Use a static buffer to avoid difficulties with buflib during DMA 656/* Use a static buffer to avoid difficulties with buflib during
674 * (hwcodec)/buffer passing to the voice_thread (swcodec). Clips 657 * buffer passing to the voice_thread (swcodec). Clips can be played
675 * can be played in chunks so the size is not that important */ 658 in chunks so the size is not that important */
676static unsigned char commit_buffer[2<<10]; 659static unsigned char commit_buffer[2<<10];
677 660
678static void* commit_transfer(struct queue_entry *qe, size_t *size) 661static void* commit_transfer(struct queue_entry *qe, size_t *size)
679{ 662{
680 void *buf = NULL; /* shut up gcc */ 663 void *buf = NULL; /* shut up gcc */
681 static unsigned char *bufpos = commit_buffer; 664 static unsigned char *bufpos = commit_buffer;
682#if CONFIG_CODEC != SWCODEC
683 sent = MIN(qe->remaining, 0xFFFF);
684#else
685 sent = qe->remaining; 665 sent = qe->remaining;
686#endif
687 sent = MIN((size_t)sent, sizeof(commit_buffer)); 666 sent = MIN((size_t)sent, sizeof(commit_buffer));
688 buf = buflib_get_data(&clip_ctx, qe->handle); 667 buf = buflib_get_data(&clip_ctx, qe->handle);
689 /* adjust buffer position to what has been played already */ 668 /* adjust buffer position to what has been played already */
@@ -706,13 +685,11 @@ static inline bool is_silence(struct queue_entry *qe)
706static void mp3_callback(const void** start, size_t* size) 685static void mp3_callback(const void** start, size_t* size)
707{ 686{
708 struct queue_entry *qe = &queue[queue_read]; 687 struct queue_entry *qe = &queue[queue_read];
709#if CONFIG_CODEC == SWCODEC
710 /* voice_thread.c hints us how many of the buffer we provided it actually 688 /* voice_thread.c hints us how many of the buffer we provided it actually
711 * consumed. Because buffers have to be frame-aligned for speex 689 * consumed. Because buffers have to be frame-aligned for speex
712 * it might be less than what we presented */ 690 * it might be less than what we presented */
713 if (*size) 691 if (*size)
714 sent = *size; 692 sent = *size;
715#endif
716 qe->remaining -= sent; /* we completed this */ 693 qe->remaining -= sent; /* we completed this */
717 694
718 if (qe->remaining > 0) /* current clip not finished? */ 695 if (qe->remaining > 0) /* current clip not finished? */
@@ -757,55 +734,7 @@ static void mp3_callback(const void** start, size_t* size)
757/* stop the playback and the pending clips */ 734/* stop the playback and the pending clips */
758void talk_force_shutup(void) 735void talk_force_shutup(void)
759{ 736{
760 /* Most of this is MAS only */ 737 /* Had nothing to do (was frame boundary or not our clip) */
761#if CONFIG_CODEC != SWCODEC
762#ifdef SIMULATOR
763 return;
764#endif
765 unsigned char* pos;
766 unsigned char* search;
767 unsigned char* end;
768 int len;
769 if (QUEUE_LEVEL == 0) /* has ended anyway */
770 return;
771
772 /* search next frame boundary and continue up to there */
773 pos = search = mp3_get_pos();
774 end = buflib_get_data(&clip_ctx, queue[queue_read].handle);
775 len = queue[queue_read].length;
776
777 if (pos >= end && pos <= (end+len)) /* really our clip? */
778 { /* (for strange reasons this isn't nesessarily the case) */
779 /* find the next frame boundary */
780 while (search < (end+len)) /* search the remaining data */
781 {
782 if (*search++ != 0xFF) /* quick search for frame sync byte */
783 continue; /* (this does the majority of the job) */
784
785 /* look at the (bitswapped) rest of header candidate */
786 if (search[0] == curr_hd[0] /* do the quicker checks first */
787 && search[2] == curr_hd[2]
788 && (search[1] & 0x30) == (curr_hd[1] & 0x30)) /* sample rate */
789 {
790 search--; /* back to the sync byte */
791 break; /* From looking at it, this is our header. */
792 }
793 }
794
795 if (search-pos)
796 { /* play old data until the frame end, to keep the MAS in sync */
797 sent = search-pos;
798
799 queue_write = (queue_read + 1) & QUEUE_MASK; /* will be empty after next callback */
800 queue[queue_read].length = sent; /* current one ends after this */
801
802 thumbnail_buf_used = 0;
803 return;
804 }
805 }
806#endif /* CONFIG_CODEC != SWCODEC */
807
808 /* Either SWCODEC, or MAS had nothing to do (was frame boundary or not our clip) */
809 mp3_play_stop(); 738 mp3_play_stop();
810 talk_queue_lock(); 739 talk_queue_lock();
811 queue_write = queue_read = 0; /* reset the queue */ 740 queue_write = queue_read = 0; /* reset the queue */
@@ -885,9 +814,7 @@ void talk_init(void)
885 814
886 if(!talk_initialized) 815 if(!talk_initialized)
887 { 816 {
888#if CONFIG_CODEC == SWCODEC
889 mutex_init(&queue_mutex); 817 mutex_init(&queue_mutex);
890#endif /* CONFIG_CODEC == SWCODEC */
891 mutex_init(&read_buffer_mutex); 818 mutex_init(&read_buffer_mutex);
892 } 819 }
893 820
@@ -957,11 +884,9 @@ void talk_init(void)
957 884
958 load_voicefile_data(filehandle); 885 load_voicefile_data(filehandle);
959 886
960#if CONFIG_CODEC == SWCODEC
961 /* Initialize the actual voice clip playback engine as well */ 887 /* Initialize the actual voice clip playback engine as well */
962 if (talk_voice_required()) 888 if (talk_voice_required())
963 voice_thread_init(); 889 voice_thread_init();
964#endif
965 890
966out: 891out:
967 close(filehandle); /* close again, this was just to detect presence */ 892 close(filehandle); /* close again, this was just to detect presence */
@@ -1062,9 +987,6 @@ static int _talk_file(const char* filename,
1062 int fd; 987 int fd;
1063 int size; 988 int size;
1064 int handle, oldest = -1; 989 int handle, oldest = -1;
1065#if CONFIG_CODEC != SWCODEC
1066 struct mp3entry info;
1067#endif
1068 990
1069 /* reload needed? */ 991 /* reload needed? */
1070 if (talk_temp_disable_count > 0) 992 if (talk_temp_disable_count > 0)
@@ -1080,13 +1002,6 @@ static int _talk_file(const char* filename,
1080 close(fd); 1002 close(fd);
1081 } 1003 }
1082 1004
1083#if CONFIG_CODEC != SWCODEC
1084 if(mp3info(&info, filename)) /* use this to find real start */
1085 {
1086 return 0; /* failed to open, or invalid */
1087 }
1088#endif
1089
1090 if (!enqueue) 1005 if (!enqueue)
1091 /* shutup now to free the thumbnail buffer */ 1006 /* shutup now to free the thumbnail buffer */
1092 talk_shutup(); 1007 talk_shutup();
@@ -1098,10 +1013,6 @@ static int _talk_file(const char* filename,
1098 } 1013 }
1099 size = filesize(fd); 1014 size = filesize(fd);
1100 1015
1101#if CONFIG_CODEC != SWCODEC
1102 size -= lseek(fd, info.first_frame_offset, SEEK_SET); /* behind ID data */
1103#endif
1104
1105 /* free clips from cache until this one succeeds to allocate */ 1016 /* free clips from cache until this one succeeds to allocate */
1106 while ((handle = buflib_alloc(&clip_ctx, size)) < 0) 1017 while ((handle = buflib_alloc(&clip_ctx, size)) < 0)
1107 oldest = free_oldest_clip(); 1018 oldest = free_oldest_clip();
@@ -1116,10 +1027,6 @@ static int _talk_file(const char* filename,
1116 struct queue_entry clip; 1027 struct queue_entry clip;
1117 clip.handle = handle; 1028 clip.handle = handle;
1118 clip.length = clip.remaining = size; 1029 clip.length = clip.remaining = size;
1119#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
1120 /* bitswap doesnt yield() */
1121 bitswap(buflib_get_data(&clip_ctx, handle), size);
1122#endif
1123 if(prefix_ids) 1030 if(prefix_ids)
1124 /* prefix thumbnail by speaking these ids, but only now 1031 /* prefix thumbnail by speaking these ids, but only now
1125 that we know there's actually a thumbnail to be 1032 that we know there's actually a thumbnail to be