diff options
author | Thomas Martitz <kugel@rockbox.org> | 2011-08-14 15:13:00 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2011-08-14 15:13:00 +0000 |
commit | d1322b71595336740eb5e18e5deed056ddb71c7a (patch) | |
tree | 812db6a9c2e9d78405ec0ed38465fd88dc5be748 | |
parent | 9b9bd73dfb212d4192fccc5fc5e269fc6499139c (diff) | |
download | rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.tar.gz rockbox-d1322b71595336740eb5e18e5deed056ddb71c7a.zip |
GSoC/Buflib: Replace all direct accesses to audiobuf with buffer API functions.
Namely, introduce buffer_get_buffer() and buffer_release_buffer().
buffer_get_buffer() aquires all available and grabs a lock, attempting to
call buffer_alloc() or buffer_get_buffer() while this lock is locked will cause
a panicf() (doesn't actually happen, but is for debugging purpose).
buffer_release_buffer() unlocks that lock and can additionally increment the
audiobuf buffer to make an allocation. Pass 0 to only unlock if buffer was
used temporarily only.
buffer_available() is a replacement function to query audiobuflen, i.e. what's
left in the buffer.
Buffer init is moved up in the init chain and handles ipodvideo64mb internally.
Further changes happened to mp3data.c and talk.c as to not call the above API
functions, but get the buffer from callers. The caller is the audio system
which has the buffer lock while mp3data.c and talk mess with the buffer.
mpeg.c now implements some buffer related functions of playback.h, especially
audio_get_buffer(), allowing to reduce #ifdef hell a tiny bit.
audiobuf and audiobufend are local to buffer.c now.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30308 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/filetree.c | 1 | ||||
-rw-r--r-- | apps/main.c | 11 | ||||
-rw-r--r-- | apps/menus/main_menu.c | 4 | ||||
-rw-r--r-- | apps/misc.c | 3 | ||||
-rw-r--r-- | apps/mp3data.c | 41 | ||||
-rw-r--r-- | apps/mp3data.h | 30 | ||||
-rw-r--r-- | apps/mpeg.c | 89 | ||||
-rw-r--r-- | apps/playback.c | 45 | ||||
-rw-r--r-- | apps/playback.h | 1 | ||||
-rw-r--r-- | apps/playlist.c | 18 | ||||
-rw-r--r-- | apps/playlist_viewer.c | 3 | ||||
-rw-r--r-- | apps/plugin.c | 8 | ||||
-rw-r--r-- | apps/plugin.h | 8 | ||||
-rw-r--r-- | apps/plugins/vbrfix.c | 5 | ||||
-rw-r--r-- | apps/recorder/pcm_record.c | 2 | ||||
-rw-r--r-- | apps/tagcache.c | 8 | ||||
-rw-r--r-- | apps/talk.c | 111 | ||||
-rw-r--r-- | apps/talk.h | 1 | ||||
-rw-r--r-- | firmware/buffer.c | 75 | ||||
-rw-r--r-- | firmware/common/dircache.c | 22 | ||||
-rw-r--r-- | firmware/export/audio.h | 6 | ||||
-rw-r--r-- | firmware/include/buffer.h | 18 | ||||
-rw-r--r-- | firmware/include/dircache.h | 3 | ||||
-rw-r--r-- | firmware/rolo.c | 28 |
24 files changed, 350 insertions, 191 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) | |||
337 | static void init(void) | 337 | static 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__ |
312 | static int fnf_read_index; | 312 | static int fnf_read_index; |
313 | static int fnf_buf_len; | 313 | static int fnf_buf_len; |
314 | static unsigned char *fnf_buf; | ||
314 | 315 | ||
315 | static int buf_getbyte(int fd, unsigned char *c) | 316 | static 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 | ||
364 | static void buf_init(void) | 365 | static 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 | ||
375 | static int audiobuflen; | 377 | static size_t mem_buflen; |
376 | static int mem_pos; | 378 | static unsigned char* mem_buf; |
379 | static size_t mem_pos; | ||
377 | static int mem_cnt; | 380 | static int mem_cnt; |
378 | static int mem_maxlen; | 381 | static 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) | |||
394 | unsigned long mem_find_next_frame(int startpos, | 397 | unsigned 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 | ||
623 | int count_mp3_frames(int fd, int startpos, int filesize, | 628 | int 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"; | |||
687 | int create_xing_header(int fd, long startpos, long filesize, | 693 | int 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 | |||
29 | struct mp3info { | 31 | struct 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); |
64 | unsigned long mem_find_next_frame(int startpos, | 66 | unsigned 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); | ||
68 | int get_mp3file_info(int fd, | 71 | int get_mp3file_info(int fd, |
69 | struct mp3info *info); | 72 | struct mp3info *info); |
70 | int count_mp3_frames(int fd, | 73 | |
71 | int startpos, | 74 | int 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); |
74 | int create_xing_header(int fd, | 77 | |
75 | long startpos, | 78 | int 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 | ||
84 | extern unsigned long bytes2int(unsigned long b0, | 84 | extern 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; | |||
144 | static bool playing = false; /* We are playing an MP3 stream */ | 145 | static bool playing = false; /* We are playing an MP3 stream */ |
145 | static bool is_playing = false; /* We are (attempting to) playing MP3 files */ | 146 | static bool is_playing = false; /* We are (attempting to) playing MP3 files */ |
146 | static bool paused; /* playback is paused */ | 147 | static bool paused; /* playback is paused */ |
148 | static char* mpeg_audiobuf; /* the audio buffer */ | ||
149 | static long audiobuflen; /* length of the audio buffer */ | ||
147 | 150 | ||
148 | #ifdef SIMULATOR | 151 | #ifdef SIMULATOR |
149 | static char mpeg_stack[DEFAULT_STACK_SIZE]; | 152 | static char mpeg_stack[DEFAULT_STACK_SIZE]; |
150 | static struct mp3entry taginfo; | 153 | static struct mp3entry taginfo; |
151 | |||
152 | #else /* !SIMULATOR */ | 154 | #else /* !SIMULATOR */ |
153 | static struct event_queue mpeg_queue SHAREDBSS_ATTR; | 155 | static struct event_queue mpeg_queue SHAREDBSS_ATTR; |
154 | static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; | 156 | static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; |
155 | 157 | ||
156 | static int audiobuflen; | ||
157 | static int audiobuf_write; | 158 | static int audiobuf_write; |
158 | static int audiobuf_swapwrite; | 159 | static int audiobuf_swapwrite; |
159 | static int audiobuf_read; | 160 | static long audiobuf_read; |
160 | 161 | ||
161 | static int mpeg_file; | 162 | static 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 | |||
495 | unsigned 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. */ |
495 | static void generate_unbuffer_events(void) | 508 | static 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 | ||
2664 | static 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 | |||
2648 | void audio_play(long offset) | 2677 | void 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 | ||
2742 | void 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 | |||
2711 | void audio_pause(void) | 2750 | void 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 */ |
3442 | unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size) | 3452 | unsigned 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 */ |
3501 | unsigned char * audio_get_recording_buffer(size_t *buffer_size) | 3513 | unsigned 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); | |||
75 | long audio_filebufused(void); | 75 | long audio_filebufused(void); |
76 | void audio_pre_ff_rewind(void); | 76 | void audio_pre_ff_rewind(void); |
77 | void audio_skip(int direction); | 77 | void audio_skip(int direction); |
78 | void audio_hard_stop(void); /* Stops audio from serving playback */ | ||
79 | 78 | ||
80 | void audio_set_cuesheet(int enable); | 79 | void 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 | */ |
980 | void* plugin_get_audio_buffer(size_t *buffer_size) | 980 | void* 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. */ |
108 | static char *tempbuf; /* Allocated when needed. */ | 108 | static char *tempbuf; /* Allocated when needed. */ |
109 | static long tempbufidx; /* Current location in buffer. */ | 109 | static long tempbufidx; /* Current location in buffer. */ |
110 | static long tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */ | 110 | static size_t tempbuf_size; /* Buffer size (TEMPBUF_SIZE). */ |
111 | static long tempbuf_left; /* Buffer space left. */ | 111 | static long tempbuf_left; /* Buffer space left. */ |
112 | static long tempbuf_pos; | 112 | static 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 | ||
131 | static char* voicebuf; /* root pointer to our buffer */ | ||
131 | static unsigned char* p_thumbnail = NULL; /* buffer for thumbnails */ | 132 | static 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. */ |
133 | static volatile int thumbnail_buf_used SHAREDBSS_ATTR; /* length of data in | 134 | static 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 */ |
284 | static void load_voicefile(bool probe) | 285 | static 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 | ||
384 | load_err: | 403 | load_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() */ | 604 | static void alloc_thumbnail_buf(void) |
586 | static 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() */ | ||
623 | static 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 */ |
706 | int talk_get_bufsize(void) | 735 | int 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 */ | ||
742 | size_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); | |||
80 | bool talk_voice_required(void); /* returns true if voice codec required */ | 80 | bool talk_voice_required(void); /* returns true if voice codec required */ |
81 | #endif | 81 | #endif |
82 | int talk_get_bufsize(void); /* get the loaded voice file size */ | 82 | int talk_get_bufsize(void); /* get the loaded voice file size */ |
83 | size_t talkbuf_init(char* bufstart); | ||
83 | void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ | 84 | void talk_buffer_steal(void); /* claim the mp3 buffer e.g. for play/record */ |
84 | bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ | 85 | bool is_voice_queued(void); /* Are there more voice clips to be spoken? */ |
85 | int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ | 86 | int talk_id(int32_t id, bool enqueue); /* play a voice ID from voicefont */ |
diff --git a/firmware/buffer.c b/firmware/buffer.c index c317cec924..2168087bd9 100644 --- a/firmware/buffer.c +++ b/firmware/buffer.c | |||
@@ -19,19 +19,33 @@ | |||
19 | * | 19 | * |
20 | ****************************************************************************/ | 20 | ****************************************************************************/ |
21 | #include <stdio.h> | 21 | #include <stdio.h> |
22 | #include <stdint.h> | ||
23 | #include "system.h" | ||
22 | #include "buffer.h" | 24 | #include "buffer.h" |
23 | #include "panic.h" | 25 | #include "panic.h" |
24 | #include "logf.h" | 26 | #include "logf.h" |
25 | 27 | ||
26 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 28 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) |
27 | unsigned char audiobuffer[(MEMORYSIZE*1024-256)*1024]; | ||
28 | unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer); | ||
29 | #else | 29 | #else |
30 | #endif | ||
31 | |||
32 | /* defined in linker script */ | ||
33 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
34 | #if defined(IPOD_VIDEO) | ||
35 | extern unsigned char *audiobufend_lds[]; | ||
36 | unsigned char *audiobufend; | ||
37 | #else /* !IPOD_VIDEO */ | ||
38 | extern unsigned char audiobufend[]; | ||
39 | #endif | ||
30 | /* defined in linker script */ | 40 | /* defined in linker script */ |
31 | extern unsigned char audiobuffer[]; | 41 | extern unsigned char audiobuffer[]; |
42 | #else /* PLATFORM_HOSTED */ | ||
43 | unsigned char audiobuffer[(MEMORYSIZE*1024-256)*1024]; | ||
44 | unsigned char *audiobufend = audiobuffer + sizeof(audiobuffer); | ||
45 | extern unsigned char *audiobufend; | ||
32 | #endif | 46 | #endif |
33 | 47 | ||
34 | unsigned char *audiobuf; | 48 | static unsigned char *audiobuf; |
35 | 49 | ||
36 | #ifdef BUFFER_ALLOC_DEBUG | 50 | #ifdef BUFFER_ALLOC_DEBUG |
37 | static unsigned char *audiobuf_orig_start; | 51 | static unsigned char *audiobuf_orig_start; |
@@ -54,13 +68,68 @@ void buffer_init(void) | |||
54 | { | 68 | { |
55 | /* 32-bit aligned */ | 69 | /* 32-bit aligned */ |
56 | audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); | 70 | audiobuf = (void *)(((unsigned long)audiobuffer + 3) & ~3); |
71 | |||
72 | #if defined(IPOD_VIDEO) | ||
73 | audiobufend=(unsigned char *)audiobufend_lds; | ||
74 | if(MEMORYSIZE==64 && probed_ramsize!=64) | ||
75 | { | ||
76 | audiobufend -= (32<<20); | ||
77 | } | ||
78 | #endif | ||
79 | |||
57 | #ifdef BUFFER_ALLOC_DEBUG | 80 | #ifdef BUFFER_ALLOC_DEBUG |
58 | audiobuf_orig_start = audiobuf; | 81 | audiobuf_orig_start = audiobuf; |
59 | #endif /* BUFFER_ALLOC_DEBUG */ | 82 | #endif /* BUFFER_ALLOC_DEBUG */ |
60 | } | 83 | } |
61 | 84 | ||
85 | /* protect concurrent access */ | ||
86 | static volatile int lock; | ||
87 | |||
88 | /* | ||
89 | * Give the entire buffer, return the size in size. | ||
90 | * The caller needs to make sure audiobuf is not otherwise used | ||
91 | * | ||
92 | * Note that this does not modify the buffer position (buffer_release_buffer() | ||
93 | * does), so call this if you want to aquire temporary memory | ||
94 | **/ | ||
95 | #define _ALIGN (sizeof(char*)) | ||
96 | void *buffer_get_buffer(size_t *size) | ||
97 | { | ||
98 | if (lock) | ||
99 | panicf("concurrent audiobuf access"); | ||
100 | lock = 1; | ||
101 | audiobuf = ALIGN_UP(audiobuf, sizeof(intptr_t)); | ||
102 | *size = (audiobufend - audiobuf); | ||
103 | return audiobuf; | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * Release the buffer gotten with buffer_get_buffer | ||
108 | * | ||
109 | * size should have the amount of bytes (from the front) that caller keeps for | ||
110 | * its own, 0 if the entire buffer is to be released | ||
111 | * | ||
112 | * safe to be called with size=0 even if the buffer wasn't claimed before | ||
113 | **/ | ||
114 | void buffer_release_buffer(size_t size) | ||
115 | { | ||
116 | audiobuf += size; | ||
117 | /* ensure alignment */ | ||
118 | audiobuf = ALIGN_UP(audiobuf, sizeof(intptr_t)); | ||
119 | lock = 0; | ||
120 | } | ||
121 | |||
122 | /* | ||
123 | * Query how much free space the buffer has */ | ||
124 | size_t buffer_available(void) | ||
125 | { | ||
126 | return audiobufend - audiobuf; | ||
127 | } | ||
128 | |||
62 | void *buffer_alloc(size_t size) | 129 | void *buffer_alloc(size_t size) |
63 | { | 130 | { |
131 | if (lock) /* it's not save to call this here */ | ||
132 | panicf("buffer_alloc(): exclusive buffer owner"); | ||
64 | void *retval; | 133 | void *retval; |
65 | #ifdef BUFFER_ALLOC_DEBUG | 134 | #ifdef BUFFER_ALLOC_DEBUG |
66 | struct buffer_start_marker *start; | 135 | struct buffer_start_marker *start; |
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c index 08fe5098f5..d114a6ac62 100644 --- a/firmware/common/dircache.c +++ b/firmware/common/dircache.c | |||
@@ -862,22 +862,26 @@ int dircache_build(int last_size) | |||
862 | * and their corresponding d_name from the end | 862 | * and their corresponding d_name from the end |
863 | * after generation the buffer will be compacted with DIRCACHE_RESERVE | 863 | * after generation the buffer will be compacted with DIRCACHE_RESERVE |
864 | * free bytes inbetween */ | 864 | * free bytes inbetween */ |
865 | audiobuf = ALIGN_UP(audiobuf, sizeof(struct dircache_entry)); | 865 | size_t got_size; |
866 | dircache_root = (struct dircache_entry*)audiobuf; | 866 | char* buf = buffer_get_buffer(&got_size); |
867 | d_names_start = d_names_end = audiobufend - 1; | 867 | ALIGN_BUFFER(buf, got_size, sizeof(struct dircache_entry)); |
868 | d_names_start = d_names_end = (char*)dircache_root + got_size - 1; | ||
868 | dircache_size = 0; | 869 | dircache_size = 0; |
869 | generate_dot_d_names(); | 870 | generate_dot_d_names(); |
870 | 871 | ||
871 | /* Start a non-transparent rebuild. */ | 872 | /* Start a non-transparent rebuild. */ |
872 | int res = dircache_do_rebuild(); | 873 | int res = dircache_do_rebuild(); |
873 | if (res < 0) | 874 | if (res < 0) |
874 | return res; | 875 | goto fail; |
875 | 876 | ||
876 | /* now compact the dircache buffer */ | 877 | /* now compact the dircache buffer */ |
877 | char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE); | 878 | char* dst = ((char*)&dircache_root[entry_count] + DIRCACHE_RESERVE); |
878 | ptrdiff_t offset = d_names_start - dst; | 879 | ptrdiff_t offset = d_names_start - dst; |
879 | if (offset <= 0) /* something went wrong */ | 880 | if (offset <= 0) /* something went wrong */ |
880 | return -1; | 881 | { |
882 | res = -1; | ||
883 | goto fail; | ||
884 | } | ||
881 | 885 | ||
882 | /* memmove d_names down, there's a possibility of overlap | 886 | /* memmove d_names down, there's a possibility of overlap |
883 | * equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */ | 887 | * equivaent to dircache_size - entry_count*sizeof(struct dircache_entry) */ |
@@ -896,15 +900,19 @@ int dircache_build(int last_size) | |||
896 | /* equivalent to dircache_size + DIRCACHE_RESERVE */ | 900 | /* equivalent to dircache_size + DIRCACHE_RESERVE */ |
897 | allocated_size = (d_names_end - (char*)dircache_root); | 901 | allocated_size = (d_names_end - (char*)dircache_root); |
898 | reserve_used = 0; | 902 | reserve_used = 0; |
899 | audiobuf += allocated_size; | ||
900 | 903 | ||
904 | buffer_release_buffer(allocated_size); | ||
905 | return res; | ||
906 | fail: | ||
907 | dircache_disable(); | ||
908 | buffer_release_buffer(0); | ||
901 | return res; | 909 | return res; |
902 | } | 910 | } |
903 | 911 | ||
904 | /** | 912 | /** |
905 | * Steal the allocated dircache buffer and disable dircache. | 913 | * Steal the allocated dircache buffer and disable dircache. |
906 | */ | 914 | */ |
907 | void* dircache_steal_buffer(long *size) | 915 | void* dircache_steal_buffer(size_t *size) |
908 | { | 916 | { |
909 | dircache_disable(); | 917 | dircache_disable(); |
910 | if (dircache_size == 0) | 918 | if (dircache_size == 0) |
diff --git a/firmware/export/audio.h b/firmware/export/audio.h index 910791c7fd..6757bf143b 100644 --- a/firmware/export/audio.h +++ b/firmware/export/audio.h | |||
@@ -51,6 +51,8 @@ | |||
51 | void audio_init(void) INIT_ATTR; | 51 | void audio_init(void) INIT_ATTR; |
52 | void audio_play(long offset); | 52 | void audio_play(long offset); |
53 | void audio_stop(void); | 53 | void audio_stop(void); |
54 | /* Stops audio from serving playback and frees resources*/ | ||
55 | void audio_hard_stop(void); | ||
54 | void audio_pause(void); | 56 | void audio_pause(void); |
55 | void audio_resume(void); | 57 | void audio_resume(void); |
56 | void audio_next(void); | 58 | void audio_next(void); |
@@ -68,11 +70,11 @@ void audio_error_clear(void); | |||
68 | int audio_get_file_pos(void); | 70 | int audio_get_file_pos(void); |
69 | void audio_beep(int duration); | 71 | void audio_beep(int duration); |
70 | 72 | ||
71 | #if CONFIG_CODEC == SWCODEC | ||
72 | /* Required call when audio buffer is required for some other purpose */ | 73 | /* Required call when audio buffer is required for some other purpose */ |
74 | /* implemented in apps but called from firmware(!) */ | ||
73 | unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size); | 75 | unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size); |
74 | /* only implemented in playback.c, but called from firmware */ | ||
75 | 76 | ||
77 | #if CONFIG_CODEC == SWCODEC | ||
76 | void audio_next_dir(void); | 78 | void audio_next_dir(void); |
77 | void audio_prev_dir(void); | 79 | void audio_prev_dir(void); |
78 | 80 | ||
diff --git a/firmware/include/buffer.h b/firmware/include/buffer.h index 18f53f0000..bdf91bcb3f 100644 --- a/firmware/include/buffer.h +++ b/firmware/include/buffer.h | |||
@@ -22,21 +22,13 @@ | |||
22 | #define BUFFER_H | 22 | #define BUFFER_H |
23 | 23 | ||
24 | #include "config.h" | 24 | #include "config.h" |
25 | /* defined in linker script */ | ||
26 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
27 | #if defined(IPOD_VIDEO) | ||
28 | extern unsigned char *audiobufend_lds[]; | ||
29 | unsigned char *audiobufend; | ||
30 | #else | ||
31 | extern unsigned char audiobufend[]; | ||
32 | #endif | ||
33 | #else | ||
34 | extern unsigned char *audiobufend; | ||
35 | #endif | ||
36 | |||
37 | extern unsigned char *audiobuf; | ||
38 | 25 | ||
39 | void buffer_init(void) INIT_ATTR; | 26 | void buffer_init(void) INIT_ATTR; |
27 | |||
28 | void* buffer_get_buffer(size_t *size); | ||
29 | void buffer_release_buffer(size_t size); | ||
30 | size_t buffer_available(void); | ||
31 | |||
40 | void *buffer_alloc(size_t size); | 32 | void *buffer_alloc(size_t size); |
41 | 33 | ||
42 | #ifdef BUFFER_ALLOC_DEBUG | 34 | #ifdef BUFFER_ALLOC_DEBUG |
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h index 0ac937df84..6beeeb6c23 100644 --- a/firmware/include/dircache.h +++ b/firmware/include/dircache.h | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "config.h" | 24 | #include "config.h" |
25 | #include "dir_uncached.h" | 25 | #include "dir_uncached.h" |
26 | #include <string.h> /* size_t */ | ||
26 | 27 | ||
27 | #ifdef HAVE_DIRCACHE | 28 | #ifdef HAVE_DIRCACHE |
28 | 29 | ||
@@ -65,7 +66,7 @@ void dircache_init(void) INIT_ATTR; | |||
65 | int dircache_load(void); | 66 | int dircache_load(void); |
66 | int dircache_save(void); | 67 | int dircache_save(void); |
67 | int dircache_build(int last_size); | 68 | int dircache_build(int last_size); |
68 | void* dircache_steal_buffer(long *size); | 69 | void* dircache_steal_buffer(size_t *size); |
69 | bool dircache_is_enabled(void); | 70 | bool dircache_is_enabled(void); |
70 | bool dircache_is_initializing(void); | 71 | bool dircache_is_initializing(void); |
71 | void dircache_set_appflag(long mask); | 72 | void dircache_set_appflag(long mask); |
diff --git a/firmware/rolo.c b/firmware/rolo.c index 078a4e9827..9b6f4fec4a 100644 --- a/firmware/rolo.c +++ b/firmware/rolo.c | |||
@@ -99,6 +99,7 @@ void rolo_restart_cop(void) | |||
99 | 99 | ||
100 | static void rolo_error(const char *text) | 100 | static void rolo_error(const char *text) |
101 | { | 101 | { |
102 | buffer_release_buffer(0); | ||
102 | lcd_clear_display(); | 103 | lcd_clear_display(); |
103 | lcd_puts(0, 0, "ROLO error:"); | 104 | lcd_puts(0, 0, "ROLO error:"); |
104 | lcd_puts_scroll(0, 1, text); | 105 | lcd_puts_scroll(0, 1, text); |
@@ -213,6 +214,8 @@ int rolo_load(const char* filename) | |||
213 | unsigned short checksum,file_checksum; | 214 | unsigned short checksum,file_checksum; |
214 | #endif | 215 | #endif |
215 | unsigned char* ramstart = (void*)&loadaddress; | 216 | unsigned char* ramstart = (void*)&loadaddress; |
217 | unsigned char* filebuf; | ||
218 | size_t filebuf_size; | ||
216 | 219 | ||
217 | lcd_clear_display(); | 220 | lcd_clear_display(); |
218 | lcd_puts(0, 0, "ROLO..."); | 221 | lcd_puts(0, 0, "ROLO..."); |
@@ -235,6 +238,10 @@ int rolo_load(const char* filename) | |||
235 | 238 | ||
236 | length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA; | 239 | length = filesize(fd) - FIRMWARE_OFFSET_FILE_DATA; |
237 | 240 | ||
241 | /* get the system buffer. release only in case of error, otherwise | ||
242 | * we don't return anyway */ | ||
243 | filebuf = buffer_get_buffer(&filebuf_size); | ||
244 | |||
238 | #if CONFIG_CPU != SH7034 | 245 | #if CONFIG_CPU != SH7034 |
239 | /* Read and save checksum */ | 246 | /* Read and save checksum */ |
240 | lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET); | 247 | lseek(fd, FIRMWARE_OFFSET_FILE_CRC, SEEK_SET); |
@@ -260,7 +267,14 @@ int rolo_load(const char* filename) | |||
260 | 267 | ||
261 | lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); | 268 | lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); |
262 | 269 | ||
263 | if (read(fd, audiobuf, length) != length) { | 270 | /* this shouldn't happen, but well */ |
271 | if ((long)filebuf_size < length) | ||
272 | { | ||
273 | rolo_error("File too big"); | ||
274 | return -1; | ||
275 | } | ||
276 | |||
277 | if (read(fd, filebuf, length) != length) { | ||
264 | rolo_error("Error Reading File"); | 278 | rolo_error("Error Reading File"); |
265 | return -1; | 279 | return -1; |
266 | } | 280 | } |
@@ -268,12 +282,12 @@ int rolo_load(const char* filename) | |||
268 | #ifdef MI4_FORMAT | 282 | #ifdef MI4_FORMAT |
269 | /* Check CRC32 to see if we have a valid file */ | 283 | /* Check CRC32 to see if we have a valid file */ |
270 | chksum_crc32gentab(); | 284 | chksum_crc32gentab(); |
271 | checksum = chksum_crc32 (audiobuf, length); | 285 | checksum = chksum_crc32 (filebuf, length); |
272 | #else | 286 | #else |
273 | checksum = MODEL_NUMBER; | 287 | checksum = MODEL_NUMBER; |
274 | 288 | ||
275 | for(i = 0;i < length;i++) { | 289 | for(i = 0;i < length;i++) { |
276 | checksum += audiobuf[i]; | 290 | checksum += filebuf[i]; |
277 | } | 291 | } |
278 | #endif | 292 | #endif |
279 | 293 | ||
@@ -329,12 +343,12 @@ int rolo_load(const char* filename) | |||
329 | lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); | 343 | lseek(fd, FIRMWARE_OFFSET_FILE_DATA, SEEK_SET); |
330 | 344 | ||
331 | /* verify that file can be read and descrambled */ | 345 | /* verify that file can be read and descrambled */ |
332 | if ((audiobuf + (2*length)+4) >= audiobufend) { | 346 | if ((size_t)((2*length)+4) >= filebuf_size) { |
333 | rolo_error("Not enough room to load file"); | 347 | rolo_error("Not enough room to load file"); |
334 | return -1; | 348 | return -1; |
335 | } | 349 | } |
336 | 350 | ||
337 | if (read(fd, &audiobuf[length], length) != (int)length) { | 351 | if (read(fd, &filebuf[length], length) != (int)length) { |
338 | rolo_error("Error Reading File"); | 352 | rolo_error("Error Reading File"); |
339 | return -1; | 353 | return -1; |
340 | } | 354 | } |
@@ -342,7 +356,7 @@ int rolo_load(const char* filename) | |||
342 | lcd_puts(0, 1, "Descramble"); | 356 | lcd_puts(0, 1, "Descramble"); |
343 | lcd_update(); | 357 | lcd_update(); |
344 | 358 | ||
345 | checksum = descramble(audiobuf + length, audiobuf, length); | 359 | checksum = descramble(filebuf + length, filebuf, length); |
346 | 360 | ||
347 | /* Verify checksum against file header */ | 361 | /* Verify checksum against file header */ |
348 | if (checksum != file_checksum) { | 362 | if (checksum != file_checksum) { |
@@ -374,7 +388,7 @@ int rolo_load(const char* filename) | |||
374 | PAIOR = 0x0FA0; | 388 | PAIOR = 0x0FA0; |
375 | #endif | 389 | #endif |
376 | #endif | 390 | #endif |
377 | rolo_restart(audiobuf, ramstart, length); | 391 | rolo_restart(filebuf, ramstart, length); |
378 | 392 | ||
379 | return 0; /* this is never reached */ | 393 | return 0; /* this is never reached */ |
380 | (void)checksum; (void)file_checksum; | 394 | (void)checksum; (void)file_checksum; |