summaryrefslogtreecommitdiff
path: root/apps/talk.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/talk.c')
-rw-r--r--apps/talk.c111
1 files changed, 106 insertions, 5 deletions
diff --git a/apps/talk.c b/apps/talk.c
index a896ca3a1a..b417046a61 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -32,7 +32,11 @@
32#include "lang.h" 32#include "lang.h"
33#include "talk.h" 33#include "talk.h"
34#include "id3.h" 34#include "id3.h"
35#include "logf.h"
35#include "bitswap.h" 36#include "bitswap.h"
37#if CONFIG_HWCODEC == MASNONE
38#include "playback.h"
39#endif
36 40
37/***************** Constants *****************/ 41/***************** Constants *****************/
38 42
@@ -88,6 +92,7 @@ static int filehandle; /* global, so the MMC variant can keep the file open */
88static unsigned char* p_silence; /* VOICE_PAUSE clip, used for termination */ 92static unsigned char* p_silence; /* VOICE_PAUSE clip, used for termination */
89static long silence_len; /* length of the VOICE_PAUSE clip */ 93static long silence_len; /* length of the VOICE_PAUSE clip */
90static unsigned char* p_lastclip; /* address of latest clip, for silence add */ 94static unsigned char* p_lastclip; /* address of latest clip, for silence add */
95static unsigned long voicefile_size = 0; /* size of the loaded voice file */
91 96
92 97
93/***************** Private prototypes *****************/ 98/***************** Private prototypes *****************/
@@ -114,10 +119,28 @@ static int open_voicefile(void)
114 } 119 }
115 120
116 snprintf(buf, sizeof(buf), ROCKBOX_DIR LANG_DIR "/%s.voice", p_lang); 121 snprintf(buf, sizeof(buf), ROCKBOX_DIR LANG_DIR "/%s.voice", p_lang);
117 122
118 return open(buf, O_RDONLY); 123 return open(buf, O_RDONLY);
119} 124}
120 125
126int talk_get_bufsize(void)
127{
128 return voicefile_size;
129}
130
131#ifdef SIMULATOR
132static unsigned short BSWAP16(unsigned short value)
133{
134 return (value >> 8) | (value << 8);
135}
136
137static unsigned long BSWAP32(unsigned long value)
138{
139 unsigned long hi = BSWAP16(value >> 16);
140 unsigned long lo = BSWAP16(value & 0xffff);
141 return (lo << 16) | hi;
142}
143#endif
121 144
122/* load the voice file into the mp3 buffer */ 145/* load the voice file into the mp3 buffer */
123static void load_voicefile(void) 146static void load_voicefile(void)
@@ -125,6 +148,10 @@ static void load_voicefile(void)
125 int load_size; 148 int load_size;
126 int got_size; 149 int got_size;
127 int file_size; 150 int file_size;
151#if CONFIG_HWCODEC == MASNONE
152 int length, i;
153 unsigned char *buf, temp;
154#endif
128 155
129 filehandle = open_voicefile(); 156 filehandle = open_voicefile();
130 if (filehandle < 0) /* failed to open */ 157 if (filehandle < 0) /* failed to open */
@@ -141,8 +168,20 @@ static void load_voicefile(void)
141#endif 168#endif
142 169
143 got_size = read(filehandle, audiobuf, load_size); 170 got_size = read(filehandle, audiobuf, load_size);
144 if (got_size == load_size /* success */ 171 if (got_size != load_size /* failure */)
145 && ((struct voicefile*)audiobuf)->table /* format check */ 172 goto load_err;
173
174#ifdef SIMULATOR
175 logf("Byte swapping voice file");
176 p_voicefile = (struct voicefile*)audiobuf;
177 p_voicefile->version = BSWAP32(p_voicefile->version);
178 p_voicefile->table = BSWAP32(p_voicefile->table);
179 p_voicefile->id1_max = BSWAP32(p_voicefile->id1_max);
180 p_voicefile->id2_max = BSWAP32(p_voicefile->id2_max);
181 p_voicefile = NULL;
182#endif
183
184 if (((struct voicefile*)audiobuf)->table /* format check */
146 == offsetof(struct voicefile, index)) 185 == offsetof(struct voicefile, index))
147 { 186 {
148 p_voicefile = (struct voicefile*)audiobuf; 187 p_voicefile = (struct voicefile*)audiobuf;
@@ -155,7 +194,42 @@ static void load_voicefile(void)
155 else 194 else
156 goto load_err; 195 goto load_err;
157 196
158#ifdef HAVE_MMC 197#ifdef SIMULATOR
198 for (i = 0; i < p_voicefile->id1_max + p_voicefile->id2_max; i++)
199 {
200 struct clip_entry *ce;
201 ce = &p_voicefile->index[i];
202 ce->offset = BSWAP32(ce->offset);
203 ce->size = BSWAP32(ce->size);
204 }
205#endif
206
207 /* Do a bitswap as necessary. */
208#if CONFIG_HWCODEC == MASNONE
209 logf("Bitswapping voice file.");
210 cpu_boost(true);
211 buf = (unsigned char *)(&p_voicefile->index) +
212 (p_voicefile->id1_max + p_voicefile->id2_max) * sizeof(struct clip_entry);
213 length = file_size - offsetof(struct voicefile, index) -
214 (p_voicefile->id1_max - p_voicefile->id2_max) * sizeof(struct clip_entry);
215
216 for (i = 0; i < length; i++)
217 {
218 temp = buf[i];
219 buf[i] = ((temp >> 7) & 0x01)
220 | ((temp >> 5) & 0x02)
221 | ((temp >> 3) & 0x04)
222 | ((temp >> 1) & 0x08)
223 | ((temp << 1) & 0x10)
224 | ((temp << 3) & 0x20)
225 | ((temp << 5) & 0x40)
226 | ((temp << 7) & 0x80);
227 }
228 cpu_boost(false);
229
230#endif
231
232#ifdef HAVE_MMC
159 /* load the index table, now that we know its size from the header */ 233 /* load the index table, now that we know its size from the header */
160 load_size = (p_voicefile->id1_max + p_voicefile->id2_max) 234 load_size = (p_voicefile->id1_max + p_voicefile->id2_max)
161 * sizeof(struct clip_entry); 235 * sizeof(struct clip_entry);
@@ -193,7 +267,11 @@ static void mp3_callback(unsigned char** start, int* size)
193 267
194 if (queue[queue_read].len > 0) /* current clip not finished? */ 268 if (queue[queue_read].len > 0) /* current clip not finished? */
195 { /* feed the next 64K-1 chunk */ 269 { /* feed the next 64K-1 chunk */
270#if CONFIG_HWCODEC != MASNONE
196 sent = MIN(queue[queue_read].len, 0xFFFF); 271 sent = MIN(queue[queue_read].len, 0xFFFF);
272#else
273 sent = queue[queue_read].len;
274#endif
197 *start = queue[queue_read].buf; 275 *start = queue[queue_read].buf;
198 *size = sent; 276 *size = sent;
199 return; 277 return;
@@ -207,7 +285,11 @@ re_check:
207 285
208 if (QUEUE_LEVEL) /* queue is not empty? */ 286 if (QUEUE_LEVEL) /* queue is not empty? */
209 { /* start next clip */ 287 { /* start next clip */
288#if CONFIG_HWCODEC != MASNONE
210 sent = MIN(queue[queue_read].len, 0xFFFF); 289 sent = MIN(queue[queue_read].len, 0xFFFF);
290#else
291 sent = queue[queue_read].len;
292#endif
211 *start = p_lastclip = queue[queue_read].buf; 293 *start = p_lastclip = queue[queue_read].buf;
212 *size = sent; 294 *size = sent;
213 curr_hd[0] = p_lastclip[1]; 295 curr_hd[0] = p_lastclip[1];
@@ -286,7 +368,7 @@ static int shutup(void)
286 /* nothing to do, was frame boundary or not our clip */ 368 /* nothing to do, was frame boundary or not our clip */
287 mp3_play_stop(); 369 mp3_play_stop();
288 queue_write = queue_read = 0; /* reset the queue */ 370 queue_write = queue_read = 0; /* reset the queue */
289 371
290 return 0; 372 return 0;
291} 373}
292 374
@@ -317,7 +399,11 @@ static int queue_clip(unsigned char* buf, long size, bool enqueue)
317 if (queue_level == 0) 399 if (queue_level == 0)
318 { /* queue was empty, we have to do the initial start */ 400 { /* queue was empty, we have to do the initial start */
319 p_lastclip = buf; 401 p_lastclip = buf;
402#if CONFIG_HWCODEC != MASNONE
320 sent = MIN(size, 0xFFFF); /* DMA can do no more */ 403 sent = MIN(size, 0xFFFF); /* DMA can do no more */
404#else
405 sent = size;
406#endif
321 mp3_play_data(buf, sent, mp3_callback); 407 mp3_play_data(buf, sent, mp3_callback);
322 curr_hd[0] = buf[1]; 408 curr_hd[0] = buf[1];
323 curr_hd[1] = buf[2]; 409 curr_hd[1] = buf[2];
@@ -400,12 +486,19 @@ void talk_init(void)
400#else 486#else
401 filehandle = open_voicefile(); 487 filehandle = open_voicefile();
402 has_voicefile = (filehandle >= 0); /* test if we can open it */ 488 has_voicefile = (filehandle >= 0); /* test if we can open it */
489 voicefile_size = 0;
490
403 if (has_voicefile) 491 if (has_voicefile)
404 { 492 {
493 voicefile_size = filesize(filehandle);
494#if CONFIG_HWCODEC == MASNONE
495 voice_init();
496#endif
405 close(filehandle); /* close again, this was just to detect presence */ 497 close(filehandle); /* close again, this was just to detect presence */
406 filehandle = -1; 498 filehandle = -1;
407 } 499 }
408#endif 500#endif
501
409} 502}
410 503
411 504
@@ -432,8 +525,10 @@ int talk_id(long id, bool enqueue)
432 unsigned char* clipbuf; 525 unsigned char* clipbuf;
433 int unit; 526 int unit;
434 527
528#if CONFIG_HWCODEC != MASNONE
435 if (audio_status()) /* busy, buffer in use */ 529 if (audio_status()) /* busy, buffer in use */
436 return -1; 530 return -1;
531#endif
437 532
438 if (p_voicefile == NULL && has_voicefile) 533 if (p_voicefile == NULL && has_voicefile)
439 load_voicefile(); /* reload needed */ 534 load_voicefile(); /* reload needed */
@@ -514,8 +609,10 @@ int talk_number(long n, bool enqueue)
514 int level = 0; /* mille count */ 609 int level = 0; /* mille count */
515 long mil = 1000000000; /* highest possible "-illion" */ 610 long mil = 1000000000; /* highest possible "-illion" */
516 611
612#if CONFIG_HWCODEC != MASNONE
517 if (audio_status()) /* busy, buffer in use */ 613 if (audio_status()) /* busy, buffer in use */
518 return -1; 614 return -1;
615#endif
519 616
520 if (!enqueue) 617 if (!enqueue)
521 shutup(); /* cut off all the pending stuff */ 618 shutup(); /* cut off all the pending stuff */
@@ -593,8 +690,10 @@ int talk_value(long n, int unit, bool enqueue)
593 VOICE_HERTZ, 690 VOICE_HERTZ,
594 }; 691 };
595 692
693#if CONFIG_HWCODEC != MASNONE
596 if (audio_status()) /* busy, buffer in use */ 694 if (audio_status()) /* busy, buffer in use */
597 return -1; 695 return -1;
696#endif
598 697
599 if (unit < 0 || unit >= UNIT_LAST) 698 if (unit < 0 || unit >= UNIT_LAST)
600 unit_id = -1; 699 unit_id = -1;
@@ -625,8 +724,10 @@ int talk_spell(const char* spell, bool enqueue)
625{ 724{
626 char c; /* currently processed char */ 725 char c; /* currently processed char */
627 726
727#if CONFIG_HWCODEC != MASNONE
628 if (audio_status()) /* busy, buffer in use */ 728 if (audio_status()) /* busy, buffer in use */
629 return -1; 729 return -1;
730#endif
630 731
631 if (!enqueue) 732 if (!enqueue)
632 shutup(); /* cut off all the pending stuff */ 733 shutup(); /* cut off all the pending stuff */