summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/filetree.c1
-rw-r--r--apps/main.c11
-rw-r--r--apps/menus/main_menu.c4
-rw-r--r--apps/misc.c3
-rw-r--r--apps/mp3data.c41
-rw-r--r--apps/mp3data.h30
-rw-r--r--apps/mpeg.c89
-rw-r--r--apps/playback.c45
-rw-r--r--apps/playback.h1
-rw-r--r--apps/playlist.c18
-rw-r--r--apps/playlist_viewer.c3
-rw-r--r--apps/plugin.c8
-rw-r--r--apps/plugin.h8
-rw-r--r--apps/plugins/vbrfix.c5
-rw-r--r--apps/recorder/pcm_record.c2
-rw-r--r--apps/tagcache.c8
-rw-r--r--apps/talk.c111
-rw-r--r--apps/talk.h1
18 files changed, 231 insertions, 158 deletions
diff --git a/apps/filetree.c b/apps/filetree.c
index a7c989fc5e..1aee80b6b2 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -600,6 +600,7 @@ int ft_enter(struct tree_context* c)
600 /* firmware file */ 600 /* firmware file */
601 case FILE_ATTR_MOD: 601 case FILE_ATTR_MOD:
602 splash(0, ID2P(LANG_WAIT)); 602 splash(0, ID2P(LANG_WAIT));
603 audio_hard_stop();
603 rolo_load(buf); 604 rolo_load(buf);
604 break; 605 break;
605#endif 606#endif
diff --git a/apps/main.c b/apps/main.c
index 0b566b5c01..9cb724562c 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -337,11 +337,11 @@ static void init_tagcache(void)
337static void init(void) 337static void init(void)
338{ 338{
339 system_init(); 339 system_init();
340 buffer_init();
340 kernel_init(); 341 kernel_init();
341#ifdef APPLICATION 342#ifdef APPLICATION
342 paths_init(); 343 paths_init();
343#endif 344#endif
344 buffer_init();
345 enable_irq(); 345 enable_irq();
346 lcd_init(); 346 lcd_init();
347#ifdef HAVE_REMOTE_LCD 347#ifdef HAVE_REMOTE_LCD
@@ -428,13 +428,7 @@ static void init(void)
428#endif 428#endif
429 429
430 system_init(); 430 system_init();
431#if defined(IPOD_VIDEO) 431 buffer_init();
432 audiobufend=(unsigned char *)audiobufend_lds;
433 if(MEMORYSIZE==64 && probed_ramsize!=64)
434 {
435 audiobufend -= (32<<20);
436 }
437#endif
438 kernel_init(); 432 kernel_init();
439 433
440#ifdef HAVE_ADJUSTABLE_CPU_FREQ 434#ifdef HAVE_ADJUSTABLE_CPU_FREQ
@@ -445,7 +439,6 @@ static void init(void)
445 cpu_boost(true); 439 cpu_boost(true);
446#endif 440#endif
447 441
448 buffer_init();
449 442
450 settings_reset(); 443 settings_reset();
451 444
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 6ee7ba4156..c5758d1274 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -182,7 +182,7 @@ static const char* info_getname(int selected_item, void *data,
182 182
183 case INFO_BUFFER: /* buffer */ 183 case INFO_BUFFER: /* buffer */
184 { 184 {
185 long kib = (audiobufend - audiobuf) / 1024; /* to KiB */ 185 long kib = buffer_available() / 1024; /* to KiB */
186 output_dyn_value(s1, sizeof(s1), kib, kbyte_units, true); 186 output_dyn_value(s1, sizeof(s1), kib, kbyte_units, true);
187 snprintf(buffer, buffer_len, "%s %s", str(LANG_BUFFER_STAT), s1); 187 snprintf(buffer, buffer_len, "%s %s", str(LANG_BUFFER_STAT), s1);
188 } 188 }
@@ -272,7 +272,7 @@ static int info_speak_item(int selected_item, void * data)
272 case INFO_BUFFER: /* buffer */ 272 case INFO_BUFFER: /* buffer */
273 { 273 {
274 talk_id(LANG_BUFFER_STAT, false); 274 talk_id(LANG_BUFFER_STAT, false);
275 long kib = (audiobufend - audiobuf) / 1024; /* to KiB */ 275 long kib = buffer_available() / 1024; /* to KiB */
276 output_dyn_value(NULL, 0, kib, kbyte_units, true); 276 output_dyn_value(NULL, 0, kib, kbyte_units, true);
277 break; 277 break;
278 } 278 }
diff --git a/apps/misc.c b/apps/misc.c
index fef55d5e2e..d74fe73205 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -766,7 +766,10 @@ void check_bootfile(bool do_rolo)
766 static const struct text_message message={ lines, 2 }; 766 static const struct text_message message={ lines, 2 };
767 button_clear_queue(); /* Empty the keyboard buffer */ 767 button_clear_queue(); /* Empty the keyboard buffer */
768 if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES) 768 if(gui_syncyesno_run(&message, NULL, NULL) == YESNO_YES)
769 {
770 audio_hard_stop();
769 rolo_load(BOOTDIR "/" BOOTFILE); 771 rolo_load(BOOTDIR "/" BOOTFILE);
772 }
770 } 773 }
771 } 774 }
772 wrtdate = info.wrtdate; 775 wrtdate = info.wrtdate;
diff --git a/apps/mp3data.c b/apps/mp3data.c
index 9fed727609..53f13f4f64 100644
--- a/apps/mp3data.c
+++ b/apps/mp3data.c
@@ -311,17 +311,18 @@ unsigned long find_next_frame(int fd,
311#ifndef __PCTOOL__ 311#ifndef __PCTOOL__
312static int fnf_read_index; 312static int fnf_read_index;
313static int fnf_buf_len; 313static int fnf_buf_len;
314static unsigned char *fnf_buf;
314 315
315static int buf_getbyte(int fd, unsigned char *c) 316static int buf_getbyte(int fd, unsigned char *c)
316{ 317{
317 if(fnf_read_index < fnf_buf_len) 318 if(fnf_read_index < fnf_buf_len)
318 { 319 {
319 *c = audiobuf[fnf_read_index++]; 320 *c = fnf_buf[fnf_read_index++];
320 return 1; 321 return 1;
321 } 322 }
322 else 323 else
323 { 324 {
324 fnf_buf_len = read(fd, audiobuf, audiobufend - audiobuf); 325 fnf_buf_len = read(fd, fnf_buf, fnf_buf_len);
325 if(fnf_buf_len < 0) 326 if(fnf_buf_len < 0)
326 return -1; 327 return -1;
327 328
@@ -329,7 +330,7 @@ static int buf_getbyte(int fd, unsigned char *c)
329 330
330 if(fnf_buf_len > 0) 331 if(fnf_buf_len > 0)
331 { 332 {
332 *c = audiobuf[fnf_read_index++]; 333 *c = fnf_buf[fnf_read_index++];
333 return 1; 334 return 1;
334 } 335 }
335 else 336 else
@@ -345,7 +346,7 @@ static int buf_seek(int fd, int len)
345 { 346 {
346 len = fnf_read_index - fnf_buf_len; 347 len = fnf_read_index - fnf_buf_len;
347 348
348 fnf_buf_len = read(fd, audiobuf, audiobufend - audiobuf); 349 fnf_buf_len = read(fd, fnf_buf, fnf_buf_len);
349 if(fnf_buf_len < 0) 350 if(fnf_buf_len < 0)
350 return -1; 351 return -1;
351 352
@@ -361,9 +362,10 @@ static int buf_seek(int fd, int len)
361 return 0; 362 return 0;
362} 363}
363 364
364static void buf_init(void) 365static void buf_init(unsigned char* buf, size_t buflen)
365{ 366{
366 fnf_buf_len = 0; 367 fnf_buf = buf;
368 fnf_buf_len = buflen;
367 fnf_read_index = 0; 369 fnf_read_index = 0;
368} 370}
369 371
@@ -372,8 +374,9 @@ static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset)
372 return __find_next_frame(fd, offset, max_offset, 0, buf_getbyte, true); 374 return __find_next_frame(fd, offset, max_offset, 0, buf_getbyte, true);
373} 375}
374 376
375static int audiobuflen; 377static size_t mem_buflen;
376static int mem_pos; 378static unsigned char* mem_buf;
379static size_t mem_pos;
377static int mem_cnt; 380static int mem_cnt;
378static int mem_maxlen; 381static int mem_maxlen;
379 382
@@ -381,8 +384,8 @@ static int mem_getbyte(int dummy, unsigned char *c)
381{ 384{
382 dummy = dummy; 385 dummy = dummy;
383 386
384 *c = audiobuf[mem_pos++]; 387 *c = mem_buf[mem_pos++];
385 if(mem_pos >= audiobuflen) 388 if(mem_pos >= mem_buflen)
386 mem_pos = 0; 389 mem_pos = 0;
387 390
388 if(mem_cnt++ >= mem_maxlen) 391 if(mem_cnt++ >= mem_maxlen)
@@ -394,9 +397,11 @@ static int mem_getbyte(int dummy, unsigned char *c)
394unsigned long mem_find_next_frame(int startpos, 397unsigned long mem_find_next_frame(int startpos,
395 long *offset, 398 long *offset,
396 long max_offset, 399 long max_offset,
397 unsigned long reference_header) 400 unsigned long reference_header,
401 unsigned char* buf, size_t buflen)
398{ 402{
399 audiobuflen = audiobufend - audiobuf; 403 mem_buf = buf;
404 mem_buflen = buflen;
400 mem_pos = startpos; 405 mem_pos = startpos;
401 mem_cnt = 0; 406 mem_cnt = 0;
402 mem_maxlen = max_offset; 407 mem_maxlen = max_offset;
@@ -620,8 +625,9 @@ static void long2bytes(unsigned char *buf, long val)
620 buf[3] = val & 0xff; 625 buf[3] = val & 0xff;
621} 626}
622 627
623int count_mp3_frames(int fd, int startpos, int filesize, 628int count_mp3_frames(int fd, int startpos, int filesize,
624 void (*progressfunc)(int)) 629 void (*progressfunc)(int),
630 unsigned char* buf, size_t buflen)
625{ 631{
626 unsigned long header = 0; 632 unsigned long header = 0;
627 struct mp3info info; 633 struct mp3info info;
@@ -637,7 +643,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
637 if(lseek(fd, startpos, SEEK_SET) < 0) 643 if(lseek(fd, startpos, SEEK_SET) < 0)
638 return -1; 644 return -1;
639 645
640 buf_init(); 646 buf_init(buf, buflen);
641 647
642 /* Find out the total number of frames */ 648 /* Find out the total number of frames */
643 num_frames = 0; 649 num_frames = 0;
@@ -687,7 +693,8 @@ static const char cooltext[] = "Rockbox - rocks your box";
687int create_xing_header(int fd, long startpos, long filesize, 693int create_xing_header(int fd, long startpos, long filesize,
688 unsigned char *buf, unsigned long num_frames, 694 unsigned char *buf, unsigned long num_frames,
689 unsigned long rec_time, unsigned long header_template, 695 unsigned long rec_time, unsigned long header_template,
690 void (*progressfunc)(int), bool generate_toc) 696 void (*progressfunc)(int), bool generate_toc,
697 unsigned char *tempbuf, size_t tempbuflen )
691{ 698{
692 struct mp3info info; 699 struct mp3info info;
693 unsigned char toc[100]; 700 unsigned char toc[100];
@@ -705,7 +712,7 @@ int create_xing_header(int fd, long startpos, long filesize,
705 if(generate_toc) 712 if(generate_toc)
706 { 713 {
707 lseek(fd, startpos, SEEK_SET); 714 lseek(fd, startpos, SEEK_SET);
708 buf_init(); 715 buf_init(tempbuf, tempbuflen);
709 716
710 /* Generate filepos table */ 717 /* Generate filepos table */
711 last_pos = 0; 718 last_pos = 0;
diff --git a/apps/mp3data.h b/apps/mp3data.h
index edda352aab..762c2f4583 100644
--- a/apps/mp3data.h
+++ b/apps/mp3data.h
@@ -26,6 +26,8 @@
26#define MPEG_VERSION2 1 26#define MPEG_VERSION2 1
27#define MPEG_VERSION2_5 2 27#define MPEG_VERSION2_5 2
28 28
29#include <string.h> /* size_t */
30
29struct mp3info { 31struct mp3info {
30 /* Standard MP3 frame header fields */ 32 /* Standard MP3 frame header fields */
31 int version; 33 int version;
@@ -63,23 +65,21 @@ unsigned long find_next_frame(int fd,
63 unsigned long reference_header); 65 unsigned long reference_header);
64unsigned long mem_find_next_frame(int startpos, 66unsigned long mem_find_next_frame(int startpos,
65 long *offset, 67 long *offset,
66 long max_offset, 68 long max_offset,
67 unsigned long reference_header); 69 unsigned long reference_header,
70 unsigned char* buf, size_t buflen);
68int get_mp3file_info(int fd, 71int get_mp3file_info(int fd,
69 struct mp3info *info); 72 struct mp3info *info);
70int count_mp3_frames(int fd, 73
71 int startpos, 74int count_mp3_frames(int fd, int startpos, int filesize,
72 int filesize, 75 void (*progressfunc)(int),
73 void (*progressfunc)(int)); 76 unsigned char* buf, size_t buflen);
74int create_xing_header(int fd, 77
75 long startpos, 78int create_xing_header(int fd, long startpos, long filesize,
76 long filesize, 79 unsigned char *buf, unsigned long num_frames,
77 unsigned char *buf, 80 unsigned long rec_time, unsigned long header_template,
78 unsigned long num_frames, 81 void (*progressfunc)(int), bool generate_toc,
79 unsigned long rec_time, 82 unsigned char *tempbuf, size_t tempbuflen );
80 unsigned long header_template,
81 void (*progressfunc)(int),
82 bool generate_toc);
83 83
84extern unsigned long bytes2int(unsigned long b0, 84extern unsigned long bytes2int(unsigned long b0,
85 unsigned long b1, 85 unsigned long b1,
diff --git a/apps/mpeg.c b/apps/mpeg.c
index b11445f947..a0182ad8d2 100644
--- a/apps/mpeg.c
+++ b/apps/mpeg.c
@@ -37,6 +37,7 @@
37#include "mp3data.h" 37#include "mp3data.h"
38#include "buffer.h" 38#include "buffer.h"
39#include "mp3_playback.h" 39#include "mp3_playback.h"
40#include "talk.h"
40#include "sound.h" 41#include "sound.h"
41#include "bitswap.h" 42#include "bitswap.h"
42#include "appevents.h" 43#include "appevents.h"
@@ -144,19 +145,19 @@ static unsigned int mpeg_errno;
144static bool playing = false; /* We are playing an MP3 stream */ 145static bool playing = false; /* We are playing an MP3 stream */
145static bool is_playing = false; /* We are (attempting to) playing MP3 files */ 146static bool is_playing = false; /* We are (attempting to) playing MP3 files */
146static bool paused; /* playback is paused */ 147static bool paused; /* playback is paused */
148static char* mpeg_audiobuf; /* the audio buffer */
149static long audiobuflen; /* length of the audio buffer */
147 150
148#ifdef SIMULATOR 151#ifdef SIMULATOR
149static char mpeg_stack[DEFAULT_STACK_SIZE]; 152static char mpeg_stack[DEFAULT_STACK_SIZE];
150static struct mp3entry taginfo; 153static struct mp3entry taginfo;
151
152#else /* !SIMULATOR */ 154#else /* !SIMULATOR */
153static struct event_queue mpeg_queue SHAREDBSS_ATTR; 155static struct event_queue mpeg_queue SHAREDBSS_ATTR;
154static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; 156static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
155 157
156static int audiobuflen;
157static int audiobuf_write; 158static int audiobuf_write;
158static int audiobuf_swapwrite; 159static int audiobuf_swapwrite;
159static int audiobuf_read; 160static long audiobuf_read;
160 161
161static int mpeg_file; 162static int mpeg_file;
162 163
@@ -490,6 +491,18 @@ unsigned long mpeg_get_last_header(void)
490#endif /* !SIMULATOR */ 491#endif /* !SIMULATOR */
491} 492}
492 493
494
495unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
496{
497 (void)talk_buf; /* always grab the voice buffer for now */
498
499 audio_hard_stop();
500 if (buffer_size) /* special case for talk_init() */
501 return buffer_get_buffer(buffer_size);
502 return NULL;
503}
504
505
493#ifndef SIMULATOR 506#ifndef SIMULATOR
494/* Send callback events to notify about removing old tracks. */ 507/* Send callback events to notify about removing old tracks. */
495static void generate_unbuffer_events(void) 508static void generate_unbuffer_events(void)
@@ -708,7 +721,7 @@ void rec_tick(void)
708 721
709 xor_b(0x08, &PADRH); /* Set PR inactive */ 722 xor_b(0x08, &PADRH); /* Set PR inactive */
710 723
711 audiobuf[audiobuf_write++] = data; 724 mpeg_audiobuf[audiobuf_write++] = data;
712 725
713 if (audiobuf_write >= audiobuflen) 726 if (audiobuf_write >= audiobuflen)
714 audiobuf_write = 0; 727 audiobuf_write = 0;
@@ -825,7 +838,7 @@ static void transfer_end(unsigned char** ppbuf, size_t* psize)
825 } 838 }
826 839
827 *psize = last_dma_chunk_size & 0xffff; 840 *psize = last_dma_chunk_size & 0xffff;
828 *ppbuf = audiobuf + audiobuf_read; 841 *ppbuf = mpeg_audiobuf + audiobuf_read;
829 track = get_trackdata(0); 842 track = get_trackdata(0);
830 if(track) 843 if(track)
831 track->id3.offset += last_dma_chunk_size; 844 track->id3.offset += last_dma_chunk_size;
@@ -1128,7 +1141,7 @@ static void start_playback_if_ready(void)
1128 playing = true; 1141 playing = true;
1129 1142
1130 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); 1143 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1131 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); 1144 mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
1132 dma_underrun = false; 1145 dma_underrun = false;
1133 1146
1134 if (!paused) 1147 if (!paused)
@@ -1173,7 +1186,7 @@ static bool swap_one_chunk(void)
1173 amount_to_swap = MIN(audiobuf_write - audiobuf_swapwrite, 1186 amount_to_swap = MIN(audiobuf_write - audiobuf_swapwrite,
1174 amount_to_swap); 1187 amount_to_swap);
1175 1188
1176 bitswap(audiobuf + audiobuf_swapwrite, amount_to_swap); 1189 bitswap(mpeg_audiobuf + audiobuf_swapwrite, amount_to_swap);
1177 1190
1178 audiobuf_swapwrite += amount_to_swap; 1191 audiobuf_swapwrite += amount_to_swap;
1179 if(audiobuf_swapwrite >= audiobuflen) 1192 if(audiobuf_swapwrite >= audiobuflen)
@@ -1341,7 +1354,7 @@ static void mpeg_thread(void)
1341 track_change(); 1354 track_change();
1342 audiobuf_read = get_trackdata(0)->mempos; 1355 audiobuf_read = get_trackdata(0)->mempos;
1343 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); 1356 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1344 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); 1357 mp3_play_data(mpeg_audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
1345 dma_underrun = false; 1358 dma_underrun = false;
1346 last_dma_tick = current_tick; 1359 last_dma_tick = current_tick;
1347 1360
@@ -1501,7 +1514,7 @@ static void mpeg_thread(void)
1501 /* resume will start at new position */ 1514 /* resume will start at new position */
1502 last_dma_chunk_size = 1515 last_dma_chunk_size =
1503 MIN(0x2000, get_unplayed_space_current_song()); 1516 MIN(0x2000, get_unplayed_space_current_song());
1504 mp3_play_data(audiobuf + audiobuf_read, 1517 mp3_play_data(mpeg_audiobuf + audiobuf_read,
1505 last_dma_chunk_size, transfer_end); 1518 last_dma_chunk_size, transfer_end);
1506 dma_underrun = false; 1519 dma_underrun = false;
1507 } 1520 }
@@ -1632,7 +1645,7 @@ static void mpeg_thread(void)
1632 { 1645 {
1633 DEBUGF("R\n"); 1646 DEBUGF("R\n");
1634 t1 = current_tick; 1647 t1 = current_tick;
1635 len = read(mpeg_file, audiobuf + audiobuf_write, 1648 len = read(mpeg_file, mpeg_audiobuf + audiobuf_write,
1636 amount_to_read); 1649 amount_to_read);
1637 if(len > 0) 1650 if(len > 0)
1638 { 1651 {
@@ -1659,7 +1672,7 @@ static void mpeg_thread(void)
1659 if(tagptr >= audiobuflen) 1672 if(tagptr >= audiobuflen)
1660 tagptr -= audiobuflen; 1673 tagptr -= audiobuflen;
1661 1674
1662 if(audiobuf[tagptr] != tag[i]) 1675 if(mpeg_audiobuf[tagptr] != tag[i])
1663 { 1676 {
1664 taglen = 0; 1677 taglen = 0;
1665 break; 1678 break;
@@ -1773,19 +1786,20 @@ static void mpeg_thread(void)
1773 startpos = prerecord_buffer[startpos].mempos; 1786 startpos = prerecord_buffer[startpos].mempos;
1774 1787
1775 DEBUGF("Start looking at address %x (%x)\n", 1788 DEBUGF("Start looking at address %x (%x)\n",
1776 audiobuf+startpos, startpos); 1789 mpeg_audiobuf+startpos, startpos);
1777 1790
1778 saved_header = mpeg_get_last_header(); 1791 saved_header = mpeg_get_last_header();
1779 1792
1780 mem_find_next_frame(startpos, &offset, 1800, 1793 mem_find_next_frame(startpos, &offset, 1800,
1781 saved_header); 1794 saved_header, mpeg_audiobuf,
1795 audiobuflen);
1782 1796
1783 audiobuf_read = startpos + offset; 1797 audiobuf_read = startpos + offset;
1784 if(audiobuf_read >= audiobuflen) 1798 if(audiobuf_read >= audiobuflen)
1785 audiobuf_read -= audiobuflen; 1799 audiobuf_read -= audiobuflen;
1786 1800
1787 DEBUGF("New audiobuf_read address: %x (%x)\n", 1801 DEBUGF("New audiobuf_read address: %x (%x)\n",
1788 audiobuf+audiobuf_read, audiobuf_read); 1802 mpeg_audiobuf+audiobuf_read, audiobuf_read);
1789 1803
1790 level = disable_irq_save(); 1804 level = disable_irq_save();
1791 num_rec_bytes = get_unsaved_space(); 1805 num_rec_bytes = get_unsaved_space();
@@ -1894,7 +1908,8 @@ static void mpeg_thread(void)
1894 save_endpos += audiobuflen; 1908 save_endpos += audiobuflen;
1895 1909
1896 rc = mem_find_next_frame(save_endpos, &offset, 1800, 1910 rc = mem_find_next_frame(save_endpos, &offset, 1800,
1897 saved_header); 1911 saved_header, mpeg_audiobuf,
1912 audiobuflen);
1898 if (!rc) /* No header found, save whole buffer */ 1913 if (!rc) /* No header found, save whole buffer */
1899 offset = 1800; 1914 offset = 1800;
1900 1915
@@ -1936,7 +1951,7 @@ static void mpeg_thread(void)
1936#elif MEMORYSIZE == 8 1951#elif MEMORYSIZE == 8
1937 amount_to_save = MIN(0x100000, amount_to_save); 1952 amount_to_save = MIN(0x100000, amount_to_save);
1938#endif 1953#endif
1939 rc = write(mpeg_file, audiobuf + audiobuf_read, 1954 rc = write(mpeg_file, mpeg_audiobuf + audiobuf_read,
1940 amount_to_save); 1955 amount_to_save);
1941 if (rc < 0) 1956 if (rc < 0)
1942 { 1957 {
@@ -2256,21 +2271,21 @@ static void prepend_header(void)
2256 if(audiobuf_read < 0) 2271 if(audiobuf_read < 0)
2257 { 2272 {
2258 /* Clear the bottom half */ 2273 /* Clear the bottom half */
2259 memset(audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE); 2274 memset(mpeg_audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE);
2260 2275
2261 /* And the top half */ 2276 /* And the top half */
2262 audiobuf_read += audiobuflen; 2277 audiobuf_read += audiobuflen;
2263 memset(audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read); 2278 memset(mpeg_audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read);
2264 } 2279 }
2265 else 2280 else
2266 { 2281 {
2267 memset(audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE); 2282 memset(mpeg_audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE);
2268 } 2283 }
2269 /* Copy the empty ID3 header */ 2284 /* Copy the empty ID3 header */
2270 startpos = audiobuf_read; 2285 startpos = audiobuf_read;
2271 for(i = 0; i < sizeof(empty_id3_header); i++) 2286 for(i = 0; i < sizeof(empty_id3_header); i++)
2272 { 2287 {
2273 audiobuf[startpos++] = empty_id3_header[i]; 2288 mpeg_audiobuf[startpos++] = empty_id3_header[i];
2274 if(startpos == audiobuflen) 2289 if(startpos == audiobuflen)
2275 startpos = 0; 2290 startpos = 0;
2276 } 2291 }
@@ -2297,7 +2312,8 @@ static void update_header(void)
2297 /* saved_header is saved right before stopping the MAS */ 2312 /* saved_header is saved right before stopping the MAS */
2298 framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer, 2313 framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer,
2299 frames, last_rec_time * (1000/HZ), 2314 frames, last_rec_time * (1000/HZ),
2300 saved_header, NULL, false); 2315 saved_header, NULL, false,
2316 mpeg_audiobuf, audiobuflen);
2301 2317
2302 lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET); 2318 lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET);
2303 write(fd, xing_buffer, framelen); 2319 write(fd, xing_buffer, framelen);
@@ -2645,8 +2661,22 @@ void audio_set_recording_options(struct audio_recording_options *options)
2645#endif /* SIMULATOR */ 2661#endif /* SIMULATOR */
2646#endif /* CONFIG_CODEC == MAS3587F */ 2662#endif /* CONFIG_CODEC == MAS3587F */
2647 2663
2664static void audio_reset_buffer(void)
2665{
2666 size_t bufsize; /* dont break strict-aliasing */
2667 talk_buffer_steal(); /* will use the mp3 buffer */
2668
2669 /* release buffer on behalf of any audio_get_buffer() caller,
2670 * non-fatal if there was none */
2671 buffer_release_buffer(0);
2672 /* re-aquire */
2673 mpeg_audiobuf = buffer_get_buffer(&bufsize);
2674 audiobuflen = bufsize;
2675}
2676
2648void audio_play(long offset) 2677void audio_play(long offset)
2649{ 2678{
2679 audio_reset_buffer();
2650#ifdef SIMULATOR 2680#ifdef SIMULATOR
2651 char name_buf[MAX_PATH+1]; 2681 char name_buf[MAX_PATH+1];
2652 const char* trackname; 2682 const char* trackname;
@@ -2676,7 +2706,6 @@ void audio_play(long offset)
2676 } while(1); 2706 } while(1);
2677#else /* !SIMULATOR */ 2707#else /* !SIMULATOR */
2678 is_playing = true; 2708 is_playing = true;
2679
2680 queue_post(&mpeg_queue, MPEG_PLAY, offset); 2709 queue_post(&mpeg_queue, MPEG_PLAY, offset);
2681#endif /* !SIMULATOR */ 2710#endif /* !SIMULATOR */
2682 2711
@@ -2700,6 +2729,8 @@ void audio_stop(void)
2700 is_playing = false; 2729 is_playing = false;
2701 playing = false; 2730 playing = false;
2702#endif /* SIMULATOR */ 2731#endif /* SIMULATOR */
2732 /* give voice our entire buffer */
2733 talkbuf_init(mpeg_audiobuf);
2703} 2734}
2704 2735
2705/* dummy */ 2736/* dummy */
@@ -2708,6 +2739,14 @@ void audio_stop_recording(void)
2708 audio_stop(); 2739 audio_stop();
2709} 2740}
2710 2741
2742void audio_hard_stop(void)
2743{
2744 audio_stop();
2745 /* tell voice we obtain the buffer before freeing */
2746 talk_buffer_steal();
2747 buffer_release_buffer(0);
2748}
2749
2711void audio_pause(void) 2750void audio_pause(void)
2712{ 2751{
2713#ifndef SIMULATOR 2752#ifndef SIMULATOR
@@ -2864,8 +2903,12 @@ void audio_init(void)
2864 if (global_settings.cuesheet) 2903 if (global_settings.cuesheet)
2865 curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet)); 2904 curr_cuesheet = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2866 2905
2906 size_t bufsize; /* don't break strict-aliasing */
2907 mpeg_audiobuf = buffer_get_buffer(&bufsize);
2908 audiobuflen = bufsize;
2909 /* give voice buffer until we start to play */
2910 talkbuf_init(mpeg_audiobuf);
2867#ifndef SIMULATOR 2911#ifndef SIMULATOR
2868 audiobuflen = audiobufend - audiobuf;
2869 queue_init(&mpeg_queue, true); 2912 queue_init(&mpeg_queue, true);
2870#endif /* !SIMULATOR */ 2913#endif /* !SIMULATOR */
2871 create_thread(mpeg_thread, mpeg_stack, 2914 create_thread(mpeg_thread, mpeg_stack,
diff --git a/apps/playback.c b/apps/playback.c
index fe9bd579d4..3f6ee71ad7 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -744,16 +744,25 @@ static void audio_reset_buffer(void)
744 /* see audio_get_recording_buffer if this is modified */ 744 /* see audio_get_recording_buffer if this is modified */
745 logf("%s()", __func__); 745 logf("%s()", __func__);
746 746
747 /* release the buffer on behalf of any caller of audio_get_buffer() */
748 buffer_release_buffer(0);
749
747 /* If the setup of anything allocated before the file buffer is 750 /* If the setup of anything allocated before the file buffer is
748 changed, do check the adjustments after the buffer_alloc call 751 changed, do check the adjustments after the buffer_alloc call
749 as it will likely be affected and need sliding over */ 752 as it will likely be affected and need sliding over */
750 753
751 /* Initially set up file buffer as all space available */ 754 /* Initially set up file buffer as all space available */
752 unsigned char *filebuf = audiobuf + talk_get_bufsize(); 755 size_t filebuflen, allocsize;
753 size_t filebuflen = audiobufend - filebuf; 756 unsigned char *filebuf = buffer_get_buffer(&filebuflen);
754 size_t allocsize;
755 757
756 ALIGN_BUFFER(filebuf, filebuflen, sizeof (intptr_t)); 758 /* Subtract whatever voice needs */
759 allocsize = talkbuf_init(filebuf);
760 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
761 if (allocsize > filebuflen)
762 goto bufpanic;
763
764 filebuf += allocsize;
765 filebuflen -= allocsize;
757 766
758 if (talk_voice_required()) 767 if (talk_voice_required())
759 { 768 {
@@ -3335,6 +3344,7 @@ void audio_hard_stop(void)
3335#ifdef PLAYBACK_VOICE 3344#ifdef PLAYBACK_VOICE
3336 voice_stop(); 3345 voice_stop();
3337#endif 3346#endif
3347 buffer_release_buffer(0);
3338} 3348}
3339 3349
3340/* Resume playback if paused */ 3350/* Resume playback if paused */
@@ -3441,7 +3451,7 @@ void audio_flush_and_reload_tracks(void)
3441 voicing */ 3451 voicing */
3442unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) 3452unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3443{ 3453{
3444 unsigned char *buf, *end; 3454 unsigned char *buf;
3445 3455
3446 if (audio_is_initialized) 3456 if (audio_is_initialized)
3447 { 3457 {
@@ -3461,7 +3471,7 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3461 || !talk_voice_required()) 3471 || !talk_voice_required())
3462 { 3472 {
3463 logf("get buffer: talk, audio"); 3473 logf("get buffer: talk, audio");
3464 /* Ok to use everything from audiobuf to audiobufend - voice is loaded, 3474 /* Ok to use everything from audiobuf - voice is loaded,
3465 the talk buffer is not needed because voice isn't being used, or 3475 the talk buffer is not needed because voice isn't being used, or
3466 could be AUDIOBUF_STATE_TRASHED already. If state is 3476 could be AUDIOBUF_STATE_TRASHED already. If state is
3467 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't 3477 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
@@ -3474,9 +3484,7 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3474 talk_buffer_steal(); 3484 talk_buffer_steal();
3475 buffer_state = AUDIOBUF_STATE_TRASHED; 3485 buffer_state = AUDIOBUF_STATE_TRASHED;
3476 } 3486 }
3477 3487 buf = buffer_get_buffer(buffer_size);
3478 buf = audiobuf;
3479 end = audiobufend;
3480 } 3488 }
3481 else 3489 else
3482 { 3490 {
@@ -3485,14 +3493,18 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3485 /* Skip talk buffer and move pcm buffer to end to maximize available 3493 /* Skip talk buffer and move pcm buffer to end to maximize available
3486 contiguous memory - no audio running means voice will not need the 3494 contiguous memory - no audio running means voice will not need the
3487 swap space */ 3495 swap space */
3496 size_t siz, talkbuf_size;
3488 logf("get buffer: audio"); 3497 logf("get buffer: audio");
3489 buf = audiobuf + talk_get_bufsize(); 3498 /* call buffer_get_buffer() to make use of the locking mechanism */
3490 end = audiobufend - voicebuf_init(audiobufend); 3499 buf = buffer_get_buffer(&siz);
3500 buf += talkbuf_size = talkbuf_init(buf);
3501 siz -= talkbuf_size;
3502 siz -= voicebuf_init(buf + siz);
3503 *buffer_size = siz;
3504
3491 buffer_state = AUDIOBUF_STATE_VOICED_ONLY; 3505 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
3492 } 3506 }
3493 3507
3494 *buffer_size = end - buf;
3495
3496 return buf; 3508 return buf;
3497} 3509}
3498 3510
@@ -3500,14 +3512,11 @@ unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3500/* Stop audio, voice and obtain all available buffer space */ 3512/* Stop audio, voice and obtain all available buffer space */
3501unsigned char * audio_get_recording_buffer(size_t *buffer_size) 3513unsigned char * audio_get_recording_buffer(size_t *buffer_size)
3502{ 3514{
3503 audio_hard_stop();
3504 talk_buffer_steal(); 3515 talk_buffer_steal();
3516 audio_hard_stop();
3505 3517
3506 unsigned char *end = audiobufend;
3507 buffer_state = AUDIOBUF_STATE_TRASHED; 3518 buffer_state = AUDIOBUF_STATE_TRASHED;
3508 *buffer_size = end - audiobuf; 3519 return buffer_get_buffer(buffer_size);
3509
3510 return (unsigned char *)audiobuf;
3511} 3520}
3512#endif /* HAVE_RECORDING */ 3521#endif /* HAVE_RECORDING */
3513 3522
diff --git a/apps/playback.h b/apps/playback.h
index ea8718089f..793055f98c 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -75,7 +75,6 @@ int audio_track_count(void);
75long audio_filebufused(void); 75long audio_filebufused(void);
76void audio_pre_ff_rewind(void); 76void audio_pre_ff_rewind(void);
77void audio_skip(int direction); 77void audio_skip(int direction);
78void audio_hard_stop(void); /* Stops audio from serving playback */
79 78
80void audio_set_cuesheet(int enable); 79void audio_set_cuesheet(int enable);
81#ifdef HAVE_CROSSFADE 80#ifdef HAVE_CROSSFADE
diff --git a/apps/playlist.c b/apps/playlist.c
index 564cd03d90..8334260242 100644
--- a/apps/playlist.c
+++ b/apps/playlist.c
@@ -533,13 +533,7 @@ static int add_indices_to_playlist(struct playlist_info* playlist,
533 { 533 {
534 /* use mp3 buffer for maximum load speed */ 534 /* use mp3 buffer for maximum load speed */
535 audio_stop(); 535 audio_stop();
536#if CONFIG_CODEC != SWCODEC 536 buffer = audio_get_buffer(false, &buflen);
537 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
538 buflen = (audiobufend - audiobuf);
539 buffer = (char *)audiobuf;
540#else
541 buffer = (char *)audio_get_buffer(false, &buflen);
542#endif
543 } 537 }
544 538
545 store_index = true; 539 store_index = true;
@@ -2018,13 +2012,7 @@ int playlist_resume(void)
2018 bool sorted = true; 2012 bool sorted = true;
2019 2013
2020 /* use mp3 buffer for maximum load speed */ 2014 /* use mp3 buffer for maximum load speed */
2021#if CONFIG_CODEC != SWCODEC
2022 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
2023 buflen = (audiobufend - audiobuf);
2024 buffer = (char *)audiobuf;
2025#else
2026 buffer = (char *)audio_get_buffer(false, &buflen); 2015 buffer = (char *)audio_get_buffer(false, &buflen);
2027#endif
2028 2016
2029 empty_playlist(playlist, true); 2017 empty_playlist(playlist, true);
2030 2018
@@ -2449,10 +2437,6 @@ void playlist_start(int start_index, int offset)
2449 2437
2450 playlist->index = start_index; 2438 playlist->index = start_index;
2451 2439
2452#if CONFIG_CODEC != SWCODEC
2453 talk_buffer_steal(); /* will use the mp3 buffer */
2454#endif
2455
2456 playlist->started = true; 2440 playlist->started = true;
2457 sync_control(playlist, false); 2441 sync_control(playlist, false);
2458 audio_play(offset); 2442 audio_play(offset);
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c
index 803fba9765..43c0c0142e 100644
--- a/apps/playlist_viewer.c
+++ b/apps/playlist_viewer.c
@@ -493,9 +493,6 @@ static int onplay_menu(int index)
493 if (current_track->display_index!=viewer.num_tracks || 493 if (current_track->display_index!=viewer.num_tracks ||
494 global_settings.repeat_mode == REPEAT_ALL) 494 global_settings.repeat_mode == REPEAT_ALL)
495 { 495 {
496#if CONFIG_CODEC != SWCODEC
497 talk_buffer_steal(); /* will use the mp3 buffer */
498#endif
499 audio_play(0); 496 audio_play(0);
500 viewer.current_playing_track = -1; 497 viewer.current_playing_track = -1;
501 } 498 }
diff --git a/apps/plugin.c b/apps/plugin.c
index 50fbb37012..32b77ad287 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -979,14 +979,8 @@ void* plugin_get_buffer(size_t *buffer_size)
979 */ 979 */
980void* plugin_get_audio_buffer(size_t *buffer_size) 980void* plugin_get_audio_buffer(size_t *buffer_size)
981{ 981{
982#if CONFIG_CODEC == SWCODEC
983 return audio_get_buffer(true, buffer_size);
984#else
985 audio_stop(); 982 audio_stop();
986 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ 983 return audio_get_buffer(true, buffer_size);
987 *buffer_size = audiobufend - audiobuf;
988 return audiobuf;
989#endif
990} 984}
991 985
992/* The plugin wants to stay resident after leaving its main function, e.g. 986/* The plugin wants to stay resident after leaving its main function, e.g.
diff --git a/apps/plugin.h b/apps/plugin.h
index a53df90d67..e2a5771b5c 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -828,12 +828,14 @@ struct plugin_api {
828#endif /* CONFIG_CODEC == SWCODEC */ 828#endif /* CONFIG_CODEC == SWCODEC */
829 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname); 829 bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
830 bool (*mp3info)(struct mp3entry *entry, const char *filename); 830 bool (*mp3info)(struct mp3entry *entry, const char *filename);
831 int (*count_mp3_frames)(int fd, int startpos, int filesize, 831 int (*count_mp3_frames)(int fd, int startpos, int filesize,
832 void (*progressfunc)(int)); 832 void (*progressfunc)(int),
833 unsigned char* buf, size_t buflen);
833 int (*create_xing_header)(int fd, long startpos, long filesize, 834 int (*create_xing_header)(int fd, long startpos, long filesize,
834 unsigned char *buf, unsigned long num_frames, 835 unsigned char *buf, unsigned long num_frames,
835 unsigned long rec_time, unsigned long header_template, 836 unsigned long rec_time, unsigned long header_template,
836 void (*progressfunc)(int), bool generate_toc); 837 void (*progressfunc)(int), bool generate_toc,
838 unsigned char* tempbuf, size_t tempbuf_len);
837 unsigned long (*find_next_frame)(int fd, long *offset, 839 unsigned long (*find_next_frame)(int fd, long *offset,
838 long max_offset, unsigned long reference_header); 840 long max_offset, unsigned long reference_header);
839 841
diff --git a/apps/plugins/vbrfix.c b/apps/plugins/vbrfix.c
index 98ca15b6a8..af7b817002 100644
--- a/apps/plugins/vbrfix.c
+++ b/apps/plugins/vbrfix.c
@@ -157,14 +157,15 @@ static bool vbr_fix(const char *selected_file)
157 xingupdate(0); 157 xingupdate(0);
158 158
159 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset, 159 num_frames = rb->count_mp3_frames(fd, entry.first_frame_offset,
160 flen, xingupdate); 160 flen, xingupdate, audiobuf, audiobuflen);
161 161
162 if(num_frames) { 162 if(num_frames) {
163 /* Note: We don't need to pass a template header because it will be 163 /* Note: We don't need to pass a template header because it will be
164 taken from the mpeg stream */ 164 taken from the mpeg stream */
165 framelen = rb->create_xing_header(fd, entry.first_frame_offset, 165 framelen = rb->create_xing_header(fd, entry.first_frame_offset,
166 flen, xingbuf, num_frames, 0, 166 flen, xingbuf, num_frames, 0,
167 0, xingupdate, true); 167 0, xingupdate, true,
168 audiobuf, audiobuflen);
168 169
169 /* Try to fit the Xing header first in the stream. Replace the existing 170 /* Try to fit the Xing header first in the stream. Replace the existing
170 VBR header if there is one, else see if there is room between the 171 VBR header if there is one, else see if there is room between the
diff --git a/apps/recorder/pcm_record.c b/apps/recorder/pcm_record.c
index 8a832e409c..407a7e5f49 100644
--- a/apps/recorder/pcm_record.c
+++ b/apps/recorder/pcm_record.c
@@ -1643,14 +1643,12 @@ void enc_set_parameters(struct enc_parameters *params)
1643 logf("fnq files:%ld", fnq_size / MAX_PATH); 1643 logf("fnq files:%ld", fnq_size / MAX_PATH);
1644 1644
1645#if defined(DEBUG) 1645#if defined(DEBUG)
1646 logf("ab :%08lX", (uintptr_t)audiobuf);
1647 logf("pcm:%08lX", (uintptr_t)pcm_buffer); 1646 logf("pcm:%08lX", (uintptr_t)pcm_buffer);
1648 logf("enc:%08lX", (uintptr_t)enc_buffer); 1647 logf("enc:%08lX", (uintptr_t)enc_buffer);
1649 logf("res:%08lX", (uintptr_t)params->reserve_buffer); 1648 logf("res:%08lX", (uintptr_t)params->reserve_buffer);
1650 logf("wip:%08lX", (uintptr_t)wrap_id_p); 1649 logf("wip:%08lX", (uintptr_t)wrap_id_p);
1651 logf("fnq:%08lX", (uintptr_t)fn_queue); 1650 logf("fnq:%08lX", (uintptr_t)fn_queue);
1652 logf("end:%08lX", (uintptr_t)fn_queue + fnq_size); 1651 logf("end:%08lX", (uintptr_t)fn_queue + fnq_size);
1653 logf("abe:%08lX", (uintptr_t)audiobufend);
1654#endif 1652#endif
1655 1653
1656 /* init all chunk headers and reset indexes */ 1654 /* init all chunk headers and reset indexes */
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 6aa7709c00..0a491c58b5 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -107,7 +107,7 @@ static char curpath[TAG_MAXLEN+32];
107/* Used when removing duplicates. */ 107/* Used when removing duplicates. */
108static char *tempbuf; /* Allocated when needed. */ 108static char *tempbuf; /* Allocated when needed. */
109static long tempbufidx; /* Current location in buffer. */ 109static long tempbufidx; /* Current location in buffer. */
110static long tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */ 110static size_t tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */
111static long tempbuf_left; /* Buffer space left. */ 111static long tempbuf_left; /* Buffer space left. */
112static long tempbuf_pos; 112static long tempbuf_pos;
113 113
@@ -3089,9 +3089,7 @@ static void allocate_tempbuf(void)
3089 tempbuf_size = 32*1024*1024; 3089 tempbuf_size = 32*1024*1024;
3090 tempbuf = malloc(tempbuf_size); 3090 tempbuf = malloc(tempbuf_size);
3091#else 3091#else
3092 tempbuf = (char *)(((long)audiobuf & ~0x03) + 0x04); 3092 buffer_get_buffer(&tempbuf_size);
3093 tempbuf_size = (long)audiobufend - (long)audiobuf - 4;
3094 audiobuf += tempbuf_size;
3095#endif 3093#endif
3096} 3094}
3097 3095
@@ -3103,7 +3101,7 @@ static void free_tempbuf(void)
3103#ifdef __PCTOOL__ 3101#ifdef __PCTOOL__
3104 free(tempbuf); 3102 free(tempbuf);
3105#else 3103#else
3106 audiobuf -= tempbuf_size; 3104 buffer_release_buffer(0);
3107#endif 3105#endif
3108 tempbuf = NULL; 3106 tempbuf = NULL;
3109 tempbuf_size = 0; 3107 tempbuf_size = 0;
diff --git a/apps/talk.c b/apps/talk.c
index 8c0f1f3a07..9fd6fb06ec 100644
--- a/apps/talk.c
+++ b/apps/talk.c
@@ -49,7 +49,7 @@
49 49
50 MASCODEC | MASCODEC | SWCODEC 50 MASCODEC | MASCODEC | SWCODEC
51 (playing) | (stopped) | 51 (playing) | (stopped) |
52 audiobuf-----------+-----------+------------ 52 voicebuf-----------+-----------+------------
53 audio | voice | thumbnail 53 audio | voice | thumbnail
54 |-----------|------------ 54 |-----------|------------
55 | thumbnail | voice 55 | thumbnail | voice
@@ -57,7 +57,7 @@
57 | | filebuf 57 | | filebuf
58 | |------------ 58 | |------------
59 | | audio 59 | | audio
60 audiobufend----------+-----------+------------ 60 voicebufend----------+-----------+------------
61 61
62 SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */ 62 SWCODEC allocates dedicated buffers, MASCODEC reuses audiobuf. */
63 63
@@ -128,6 +128,7 @@ static uint8_t clip_age[QUEUE_SIZE];
128#endif 128#endif
129#endif 129#endif
130 130
131static char* voicebuf; /* root pointer to our buffer */
131static unsigned char* p_thumbnail = NULL; /* buffer for thumbnails */ 132static unsigned char* p_thumbnail = NULL; /* buffer for thumbnails */
132/* Multiple thumbnails can be loaded back-to-back in this buffer. */ 133/* Multiple thumbnails can be loaded back-to-back in this buffer. */
133static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in 134static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in
@@ -281,12 +282,18 @@ static unsigned char* get_clip(long id, long* p_size)
281 282
282 283
283/* load the voice file into the mp3 buffer */ 284/* load the voice file into the mp3 buffer */
284static void load_voicefile(bool probe) 285static void load_voicefile(bool probe, char* buf, size_t bufsize)
285{ 286{
286 int load_size; 287 union voicebuf {
288 unsigned char* buf;
289 struct voicefile* file;
290 };
291 union voicebuf voicebuf;
292
293 int load_size, alloc_size;
287 int got_size; 294 int got_size;
288#ifndef TALK_PARTIAL_LOAD 295#ifndef TALK_PARTIAL_LOAD
289 int file_size; 296 size_t file_size;
290#endif 297#endif
291#ifdef ROCKBOX_LITTLE_ENDIAN 298#ifdef ROCKBOX_LITTLE_ENDIAN
292 int i; 299 int i;
@@ -297,37 +304,43 @@ static void load_voicefile(bool probe)
297 if (filehandle < 0) /* failed to open */ 304 if (filehandle < 0) /* failed to open */
298 goto load_err; 305 goto load_err;
299 306
307 voicebuf.buf = buf;
308 if (!voicebuf.buf)
309 goto load_err;
310
300#ifndef TALK_PARTIAL_LOAD 311#ifndef TALK_PARTIAL_LOAD
301 file_size = filesize(filehandle); 312 file_size = filesize(filehandle);
302 if (file_size > audiobufend - audiobuf) /* won't fit? */ 313 if (file_size > bufsize) /* won't fit? */
303 goto load_err; 314 goto load_err;
304#endif 315#endif
305 316
306#if defined(TALK_PROGRESSIVE_LOAD) || defined(TALK_PARTIAL_LOAD) 317#if defined(TALK_PROGRESSIVE_LOAD) || defined(TALK_PARTIAL_LOAD)
307 /* load only the header for now */ 318 /* load only the header for now */
308 load_size = offsetof(struct voicefile, index); 319 load_size = sizeof(struct voicefile);
309#else /* load the full file */ 320#else /* load the full file */
310 load_size = file_size; 321 load_size = file_size;
311#endif 322#endif
312 323
313#ifdef TALK_PARTIAL_LOAD 324#ifdef TALK_PARTIAL_LOAD
314 if (load_size > audiobufend - audiobuf) /* won't fit? */ 325 if (load_size > bufsize) /* won't fit? */
315 goto load_err; 326 goto load_err;
316#endif 327#endif
317 328
318 got_size = read(filehandle, audiobuf, load_size); 329 got_size = read(filehandle, voicebuf.buf, load_size);
319 if (got_size != load_size /* failure */) 330 if (got_size != load_size /* failure */)
320 goto load_err; 331 goto load_err;
321 332
333 alloc_size = load_size;
334
322#ifdef ROCKBOX_LITTLE_ENDIAN 335#ifdef ROCKBOX_LITTLE_ENDIAN
323 logf("Byte swapping voice file"); 336 logf("Byte swapping voice file");
324 structec_convert(audiobuf, "lllll", 1, true); 337 structec_convert(voicebuf.buf, "lllll", 1, true);
325#endif 338#endif
326 339
327 if (((struct voicefile*)audiobuf)->table /* format check */ 340 /* format check */
328 == offsetof(struct voicefile, index)) 341 if (voicebuf.file->table == sizeof(struct voicefile))
329 { 342 {
330 p_voicefile = (struct voicefile*)audiobuf; 343 p_voicefile = voicebuf.file;
331 344
332 if (p_voicefile->version != VOICE_VERSION || 345 if (p_voicefile->version != VOICE_VERSION ||
333 p_voicefile->target_id != TARGET_ID) 346 p_voicefile->target_id != TARGET_ID)
@@ -337,9 +350,9 @@ static void load_voicefile(bool probe)
337 } 350 }
338#if CONFIG_CODEC != SWCODEC 351#if CONFIG_CODEC != SWCODEC
339 /* MASCODEC: now use audiobuf for voice then thumbnail */ 352 /* MASCODEC: now use audiobuf for voice then thumbnail */
340 p_thumbnail = audiobuf + file_size; 353 p_thumbnail = voicebuf.buf + file_size;
341 p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */ 354 p_thumbnail += (long)p_thumbnail % 2; /* 16-bit align */
342 size_for_thumbnail = audiobufend - p_thumbnail; 355 size_for_thumbnail = voicebuf.buf + bufsize - p_thumbnail;
343#endif 356#endif
344 } 357 }
345 else 358 else
@@ -351,14 +364,15 @@ static void load_voicefile(bool probe)
351 * sizeof(struct clip_entry); 364 * sizeof(struct clip_entry);
352 365
353#ifdef TALK_PARTIAL_LOAD 366#ifdef TALK_PARTIAL_LOAD
354 if (load_size > audiobufend - audiobuf) /* won't fit? */ 367 if (load_size > bufsize) /* won't fit? */
355 goto load_err; 368 goto load_err;
356#endif 369#endif
357 370
358 got_size = read(filehandle, 371 got_size = read(filehandle, &p_voicefile->index[0], load_size);
359 (unsigned char *) p_voicefile + offsetof(struct voicefile, index), load_size);
360 if (got_size != load_size) /* read error */ 372 if (got_size != load_size) /* read error */
361 goto load_err; 373 goto load_err;
374
375 alloc_size += load_size;
362#else 376#else
363 close(filehandle); 377 close(filehandle);
364 filehandle = -1; 378 filehandle = -1;
@@ -379,6 +393,11 @@ static void load_voicefile(bool probe)
379 p_silence = get_clip(VOICE_PAUSE, &silence_len); 393 p_silence = get_clip(VOICE_PAUSE, &silence_len);
380 } 394 }
381 395
396#ifdef TALK_PARTIAL_LOAD
397 alloc_size += silence_len + QUEUE_SIZE;
398#endif
399 if ((size_t)alloc_size > bufsize)
400 goto load_err;
382 return; 401 return;
383 402
384load_err: 403load_err:
@@ -582,24 +601,31 @@ static void queue_clip(unsigned char* buf, long size, bool enqueue)
582} 601}
583 602
584 603
585/* common code for talk_init() and talk_buffer_steal() */ 604static void alloc_thumbnail_buf(void)
586static void reset_state(void)
587{ 605{
588 queue_write = queue_read = 0; /* reset the queue */
589 p_voicefile = NULL; /* indicate no voicefile (trashed) */
590#if CONFIG_CODEC == SWCODEC 606#if CONFIG_CODEC == SWCODEC
591 /* Allocate a dedicated thumbnail buffer - once */ 607 /* Allocate a dedicated thumbnail buffer - once */
592 if (p_thumbnail == NULL) 608 if (p_thumbnail == NULL)
593 { 609 {
594 size_for_thumbnail = audiobufend - audiobuf; 610 size_for_thumbnail = buffer_available();
595 if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE) 611 if (size_for_thumbnail > MAX_THUMBNAIL_BUFSIZE)
596 size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE; 612 size_for_thumbnail = MAX_THUMBNAIL_BUFSIZE;
597 p_thumbnail = buffer_alloc(size_for_thumbnail); 613 p_thumbnail = buffer_alloc(size_for_thumbnail);
598 } 614 }
599#else 615#else
600 /* Just use the audiobuf, without allocating anything */ 616 /* use the audio buffer now, need to release before loading a voice */
601 p_thumbnail = audiobuf; 617 p_thumbnail = voicebuf;
602 size_for_thumbnail = audiobufend - audiobuf; 618#endif
619 thumbnail_buf_used = 0;
620}
621
622/* common code for talk_init() and talk_buffer_steal() */
623static void reset_state(void)
624{
625 queue_write = queue_read = 0; /* reset the queue */
626 p_voicefile = NULL; /* indicate no voicefile (trashed) */
627#if CONFIG_CODEC != SWCODEC
628 p_thumbnail = NULL; /* don't leak buffer_alloc() for swcodec */
603#endif 629#endif
604 630
605#ifdef TALK_PARTIAL_LOAD 631#ifdef TALK_PARTIAL_LOAD
@@ -608,8 +634,8 @@ static void reset_state(void)
608 buffered_id[i] = -1; 634 buffered_id[i] = -1;
609#endif 635#endif
610 636
611 thumbnail_buf_used = 0;
612 p_silence = NULL; /* pause clip not accessible */ 637 p_silence = NULL; /* pause clip not accessible */
638 voicebuf = NULL;
613} 639}
614 640
615 641
@@ -655,12 +681,11 @@ void talk_init(void)
655#endif 681#endif
656 reset_state(); /* use this for most of our inits */ 682 reset_state(); /* use this for most of our inits */
657 683
658 /* test if we can open and if it fits in the audiobuffer */
659 size_t audiobufsz = audiobufend - audiobuf;
660
661#ifdef TALK_PARTIAL_LOAD 684#ifdef TALK_PARTIAL_LOAD
685 size_t bufsize;
686 char* buf = plugin_get_buffer(&bufsize);
662 /* we won't load the full file, we only need the index */ 687 /* we won't load the full file, we only need the index */
663 load_voicefile(true); 688 load_voicefile(true, buf, bufsize);
664 if (!p_voicefile) 689 if (!p_voicefile)
665 return; 690 return;
666 691
@@ -681,6 +706,9 @@ void talk_init(void)
681 p_voicefile = NULL; /* Don't pretend we can load talk clips just yet */ 706 p_voicefile = NULL; /* Don't pretend we can load talk clips just yet */
682#endif 707#endif
683 708
709
710 /* test if we can open and if it fits in the audiobuffer */
711 size_t audiobufsz = buffer_available();
684 if (voicefile_size <= audiobufsz) { 712 if (voicefile_size <= audiobufsz) {
685 has_voicefile = true; 713 has_voicefile = true;
686 } else { 714 } else {
@@ -688,6 +716,7 @@ void talk_init(void)
688 voicefile_size = 0; 716 voicefile_size = 0;
689 } 717 }
690 718
719 alloc_thumbnail_buf();
691 close(filehandle); /* close again, this was just to detect presence */ 720 close(filehandle); /* close again, this was just to detect presence */
692 filehandle = -1; 721 filehandle = -1;
693} 722}
@@ -703,8 +732,22 @@ bool talk_voice_required(void)
703#endif 732#endif
704 733
705/* return size of voice file */ 734/* return size of voice file */
706int talk_get_bufsize(void) 735int talk_get_buffer(void)
736{
737 return voicefile_size;
738}
739
740/* Sets the buffer for the voicefile and returns how many bytes of this
741 * buffer we will use for the voicefile */
742size_t talkbuf_init(char *bufstart)
707{ 743{
744 bool changed = voicebuf != bufstart;
745
746 if (bufstart)
747 voicebuf = bufstart;
748 if (changed) /* must reload voice file */
749 reset_state();
750
708 return voicefile_size; 751 return voicefile_size;
709} 752}
710 753
@@ -741,7 +784,7 @@ int talk_id(int32_t id, bool enqueue)
741#endif 784#endif
742 785
743 if (p_voicefile == NULL && has_voicefile) 786 if (p_voicefile == NULL && has_voicefile)
744 load_voicefile(false); /* reload needed */ 787 load_voicefile(false, voicebuf, voicefile_size); /* reload needed */
745 788
746 if (p_voicefile == NULL) /* still no voices? */ 789 if (p_voicefile == NULL) /* still no voices? */
747 return -1; 790 return -1;
@@ -819,7 +862,7 @@ static int _talk_file(const char* filename,
819#endif 862#endif
820 863
821 if (p_thumbnail == NULL || size_for_thumbnail <= 0) 864 if (p_thumbnail == NULL || size_for_thumbnail <= 0)
822 return -1; 865 alloc_thumbnail_buf();
823 866
824#if CONFIG_CODEC != SWCODEC 867#if CONFIG_CODEC != SWCODEC
825 if(mp3info(&info, filename)) /* use this to find real start */ 868 if(mp3info(&info, filename)) /* use this to find real start */
diff --git a/apps/talk.h b/apps/talk.h
index a2a9f44e4e..e1702147c7 100644
--- a/apps/talk.h
+++ b/apps/talk.h
@@ -80,6 +80,7 @@ void talk_init(void);
80bool talk_voice_required(void); /* returns true if voice codec required */ 80bool talk_voice_required(void); /* returns true if voice codec required */
81#endif 81#endif
82int talk_get_bufsize(void); /* get the loaded voice file size */ 82int talk_get_bufsize(void); /* get the loaded voice file size */
83size_t talkbuf_init(char* bufstart);
83void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ 84void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */
84bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ 85bool is_voice_queued(void); /* Are there more voice clips to be spoken? */
85int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ 86int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */