diff options
Diffstat (limited to 'apps/talk.c')
-rw-r--r-- | apps/talk.c | 56 |
1 files changed, 46 insertions, 10 deletions
diff --git a/apps/talk.c b/apps/talk.c index 1a1cb81cd1..736c68c7b4 100644 --- a/apps/talk.c +++ b/apps/talk.c | |||
@@ -39,6 +39,23 @@ | |||
39 | #include "playback.h" | 39 | #include "playback.h" |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | |||
43 | /* Memory layout varies between targets because the | ||
44 | Archos (MASCODEC) devices cannot mix voice and audio playback | ||
45 | |||
46 | MASCODEC | MASCODEC | SWCODEC | ||
47 | (playing) | (stopped) | | ||
48 | audiobuf-----------+-----------+----------- | ||
49 | audio | voice | thumbnail | ||
50 | |-----------|----------- | ||
51 | | thumbnail | voice | ||
52 | | |----------- | ||
53 | | | audio | ||
54 | audiobufend----------+-----------+----------- | ||
55 | |||
56 | SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */ | ||
57 | |||
58 | |||
42 | /***************** Constants *****************/ | 59 | /***************** Constants *****************/ |
43 | 60 | ||
44 | #define QUEUE_SIZE 64 /* must be a power of two */ | 61 | #define QUEUE_SIZE 64 /* must be a power of two */ |
@@ -52,6 +69,10 @@ const char* const file_thumbnail_ext = ".talk"; | |||
52 | 69 | ||
53 | #define LOADED_MASK 0x80000000 /* MSB */ | 70 | #define LOADED_MASK 0x80000000 /* MSB */ |
54 | 71 | ||
72 | #if CONFIG_CODEC == SWCODEC | ||
73 | #define MAX_THUMBNAIL_BUFSIZE 32768 | ||
74 | #endif | ||
75 | |||
55 | 76 | ||
56 | /***************** Data types *****************/ | 77 | /***************** Data types *****************/ |
57 | 78 | ||
@@ -172,12 +193,16 @@ static void load_voicefile(void) | |||
172 | if (((struct voicefile*)audiobuf)->table /* format check */ | 193 | if (((struct voicefile*)audiobuf)->table /* format check */ |
173 | == offsetof(struct voicefile, index)) | 194 | == offsetof(struct voicefile, index)) |
174 | { | 195 | { |
196 | #if CONFIG_CODEC == SWCODEC | ||
197 | /* SWCODEC: allocate permanent buffer */ | ||
198 | p_voicefile = (struct voicefile*)buffer_alloc(file_size); | ||
199 | #else | ||
200 | /* MASCODEC: now use audiobuf for voice then thumbnail */ | ||
175 | p_voicefile = (struct voicefile*)audiobuf; | 201 | p_voicefile = (struct voicefile*)audiobuf; |
176 | |||
177 | /* thumbnail buffer is the remaining space behind */ | ||
178 | p_thumbnail = audiobuf + file_size; | 202 | p_thumbnail = audiobuf + file_size; |
179 | p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */ | 203 | p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */ |
180 | size_for_thumbnail = audiobufend - p_thumbnail; | 204 | size_for_thumbnail = audiobufend - p_thumbnail; |
205 | #endif | ||
181 | } | 206 | } |
182 | else | 207 | else |
183 | goto load_err; | 208 | goto load_err; |
@@ -198,7 +223,7 @@ static void load_voicefile(void) | |||
198 | cpu_boost(true); | 223 | cpu_boost(true); |
199 | buf = (unsigned char *)(&p_voicefile->index) + | 224 | buf = (unsigned char *)(&p_voicefile->index) + |
200 | (p_voicefile->id1_max + p_voicefile->id2_max) * sizeof(struct clip_entry); | 225 | (p_voicefile->id1_max + p_voicefile->id2_max) * sizeof(struct clip_entry); |
201 | length = file_size - (buf - audiobuf); | 226 | length = file_size - (buf - (unsigned char *) p_voicefile); |
202 | 227 | ||
203 | for (i = 0; i < length; i++) | 228 | for (i = 0; i < length; i++) |
204 | { | 229 | { |
@@ -216,7 +241,7 @@ static void load_voicefile(void) | |||
216 | load_size = (p_voicefile->id1_max + p_voicefile->id2_max) | 241 | load_size = (p_voicefile->id1_max + p_voicefile->id2_max) |
217 | * sizeof(struct clip_entry); | 242 | * sizeof(struct clip_entry); |
218 | got_size = read(filehandle, | 243 | got_size = read(filehandle, |
219 | audiobuf + offsetof(struct voicefile, index), load_size); | 244 | (unsigned char *) p_voicefile + offsetof(struct voicefile, index), load_size); |
220 | if (got_size != load_size) /* read error */ | 245 | if (got_size != load_size) /* read error */ |
221 | goto load_err; | 246 | goto load_err; |
222 | #else | 247 | #else |
@@ -278,9 +303,9 @@ re_check: | |||
278 | curr_hd[1] = p_lastclip[2]; | 303 | curr_hd[1] = p_lastclip[2]; |
279 | curr_hd[2] = p_lastclip[3]; | 304 | curr_hd[2] = p_lastclip[3]; |
280 | } | 305 | } |
281 | else if (p_silence != NULL /* silence clip available */ | 306 | else if (p_silence != NULL /* silence clip available */ |
282 | && p_lastclip != p_silence /* previous clip wasn't silence */ | 307 | && p_lastclip != p_silence /* previous clip wasn't silence */ |
283 | && p_lastclip < p_thumbnail) /* ..and not a thumbnail */ | 308 | && p_lastclip != p_thumbnail) /* ..or thumbnail */ |
284 | { /* add silence clip when queue runs empty playing a voice clip */ | 309 | { /* add silence clip when queue runs empty playing a voice clip */ |
285 | queue[queue_write].buf = p_silence; | 310 | queue[queue_write].buf = p_silence; |
286 | queue[queue_write].len = silence_len; | 311 | queue[queue_write].len = silence_len; |
@@ -424,7 +449,7 @@ static unsigned char* get_clip(long id, long* p_size) | |||
424 | clipsize = p_voicefile->index[id].size; | 449 | clipsize = p_voicefile->index[id].size; |
425 | if (clipsize == 0) /* clip not included in voicefile */ | 450 | if (clipsize == 0) /* clip not included in voicefile */ |
426 | return NULL; | 451 | return NULL; |
427 | clipbuf = audiobuf + p_voicefile->index[id].offset; | 452 | clipbuf = (unsigned char *) p_voicefile + p_voicefile->index[id].offset; |
428 | 453 | ||
429 | #ifdef HAVE_MMC /* dynamic loading, on demand */ | 454 | #ifdef HAVE_MMC /* dynamic loading, on demand */ |
430 | if (!(clipsize & LOADED_MASK)) | 455 | if (!(clipsize & LOADED_MASK)) |
@@ -451,8 +476,17 @@ static void reset_state(void) | |||
451 | { | 476 | { |
452 | queue_write = queue_read = 0; /* reset the queue */ | 477 | queue_write = queue_read = 0; /* reset the queue */ |
453 | p_voicefile = NULL; /* indicate no voicefile (trashed) */ | 478 | p_voicefile = NULL; /* indicate no voicefile (trashed) */ |
454 | p_thumbnail = audiobuf; /* whole space for thumbnail */ | 479 | #if CONFIG_CODEC == SWCODEC |
480 | /* Allocate a dedicated thumbnail buffer */ | ||
455 | size_for_thumbnail = audiobufend - audiobuf; | 481 | size_for_thumbnail = audiobufend - audiobuf; |
482 | if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE) | ||
483 | size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE; | ||
484 | p_thumbnail = buffer_alloc(size_for_thumbnail); | ||
485 | #else | ||
486 | /* Just use the audiobuf, without allocating anything */ | ||
487 | p_thumbnail = audiobuf; | ||
488 | size_for_thumbnail = audiobufend - audiobuf; | ||
489 | #endif | ||
456 | p_silence = NULL; /* pause clip not accessible */ | 490 | p_silence = NULL; /* pause clip not accessible */ |
457 | } | 491 | } |
458 | 492 | ||
@@ -563,8 +597,10 @@ int talk_file(const char* filename, bool enqueue) | |||
563 | int size; | 597 | int size; |
564 | struct mp3entry info; | 598 | struct mp3entry info; |
565 | 599 | ||
600 | #if CONFIG_CODEC != SWCODEC | ||
566 | if (audio_status()) /* busy, buffer in use */ | 601 | if (audio_status()) /* busy, buffer in use */ |
567 | return -1; | 602 | return -1; |
603 | #endif | ||
568 | 604 | ||
569 | if (p_thumbnail == NULL || size_for_thumbnail <= 0) | 605 | if (p_thumbnail == NULL || size_for_thumbnail <= 0) |
570 | return -1; | 606 | return -1; |
@@ -587,7 +623,7 @@ int talk_file(const char* filename, bool enqueue) | |||
587 | 623 | ||
588 | /* ToDo: find audio, skip ID headers and trailers */ | 624 | /* ToDo: find audio, skip ID headers and trailers */ |
589 | 625 | ||
590 | if (size) | 626 | if (size != 0 && size != size_for_thumbnail) /* Don't play missing or truncated clips */ |
591 | { | 627 | { |
592 | #if CONFIG_CODEC != SWCODEC | 628 | #if CONFIG_CODEC != SWCODEC |
593 | bitswap(p_thumbnail, size); | 629 | bitswap(p_thumbnail, size); |