summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-03-10 14:55:31 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-03-10 14:55:31 +0000
commita039091187f40d018b6353b8c13de7a01d3a6fe0 (patch)
tree08f7eb86e86e2c61f4d36f9c91731cb93252ba84 /firmware
parent22cbe938feb48895d7488449835d3ee577399057 (diff)
downloadrockbox-a039091187f40d018b6353b8c13de7a01d3a6fe0.tar.gz
rockbox-a039091187f40d018b6353b8c13de7a01d3a6fe0.zip
New ID3 and MP3 stream parser, plus not-yet-ready Xing header generation code
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3410 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/id3.h9
-rw-r--r--firmware/export/mp3data.h66
-rw-r--r--firmware/export/mpeg.h1
-rw-r--r--firmware/id3.c371
-rw-r--r--firmware/mp3data.c664
-rw-r--r--firmware/mpeg.c320
6 files changed, 1008 insertions, 423 deletions
diff --git a/firmware/export/id3.h b/firmware/export/id3.h
index 55ce002c2e..30be4bf883 100644
--- a/firmware/export/id3.h
+++ b/firmware/export/id3.h
@@ -39,15 +39,18 @@ struct mp3entry {
39 unsigned int first_frame_offset; /* Byte offset to first real MP3 frame. 39 unsigned int first_frame_offset; /* Byte offset to first real MP3 frame.
40 Used for skipping leading garbage to 40 Used for skipping leading garbage to
41 avoid gaps between tracks. */ 41 avoid gaps between tracks. */
42 unsigned int xing_header_pos;
42 unsigned int filesize; /* in bytes */ 43 unsigned int filesize; /* in bytes */
43 unsigned int length; /* song length */ 44 unsigned int length; /* song length */
44 unsigned int elapsed; /* ms played */ 45 unsigned int elapsed; /* ms played */
46
47 /* MP3 stream specific info */
45 long bpf; /* bytes per frame */ 48 long bpf; /* bytes per frame */
46 long tpf; /* time per frame */ 49 long tpf; /* time per frame */
47 50
48 /* Xing VBR fields */ 51 /* Xing VBR fields */
49 bool vbr; 52 bool vbr;
50 unsigned char vbrflags; 53 bool has_toc; /* True if there is a VBR header in the file */
51 unsigned char toc[100];/* table of contents */ 54 unsigned char toc[100];/* table of contents */
52 55
53 /* these following two fields are used for local buffering */ 56 /* these following two fields are used for local buffering */
@@ -59,10 +62,6 @@ struct mp3entry {
59 int index; /* playlist index */ 62 int index; /* playlist index */
60}; 63};
61 64
62#define VBR_FRAMES_FLAG 0x01
63#define VBR_BYTES_FLAG 0x02
64#define VBR_TOC_FLAG 0x04
65
66enum { 65enum {
67 ID3_VER_1_0 = 1, 66 ID3_VER_1_0 = 1,
68 ID3_VER_1_1, 67 ID3_VER_1_1,
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
new file mode 100644
index 0000000000..a1018ebaa2
--- /dev/null
+++ b/firmware/export/mp3data.h
@@ -0,0 +1,66 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _MP3DATA_H_
21#define _MP3DATA_H_
22
23#define MPEG_VERSION2_5 0
24#define MPEG_VERSION1 1
25#define MPEG_VERSION2 2
26
27struct mp3info {
28 /* Standard MP3 frame header fields */
29 int version;
30 int layer;
31 bool protection;
32 int bitrate;
33 int frequency;
34 int padding;
35 int channel_mode;
36 int mode_extension;
37 int emphasis;
38 int frame_size; /* Frame size in bytes */
39 int frame_time; /* Frame duration in milliseconds */
40
41 bool is_vbr; /* True if the file is VBR */
42 bool has_toc; /* True if there is a VBR header in the file */
43 bool is_xing_vbr; /* True if the VBR header is of Xing type */
44 bool is_vbri_vbr; /* True if the VBR header is of VBRI type */
45 unsigned char toc[100];
46 int frame_count; /* Number of frames in the file (if VBR) */
47 int byte_count; /* File size in bytes */
48 int file_time; /* Length of the whole file in milliseconds */
49 int xing_header_pos;
50};
51
52/* Xing header information */
53#define VBR_FRAMES_FLAG 0x01
54#define VBR_BYTES_FLAG 0x02
55#define VBR_TOC_FLAG 0x04
56
57
58unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header);
59int get_mp3file_info(int fd, struct mp3info *info);
60int count_mp3_frames(int fd, int startpos, int filesize,
61 void (*progressfunc)(int));
62int create_xing_header(int fd, int startpos, int filesize,
63 unsigned char *buf, int num_frames,
64 void (*progressfunc)(int));
65
66#endif
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index 6b44363f8f..9ce03daa7d 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -90,6 +90,7 @@ unsigned long mpeg_num_recorded_bytes(void);
90#endif 90#endif
91void mpeg_get_debugdata(struct mpeg_debug *dbgdata); 91void mpeg_get_debugdata(struct mpeg_debug *dbgdata);
92void mpeg_set_buffer_margin(int seconds); 92void mpeg_set_buffer_margin(int seconds);
93int mpeg_create_xing_header(char *filename, void (*progressfunc)(int));
93 94
94#define SOUND_VOLUME 0 95#define SOUND_VOLUME 0
95#define SOUND_BASS 1 96#define SOUND_BASS 1
diff --git a/firmware/id3.c b/firmware/id3.c
index 8e8a60eb71..6aeafc4749 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -22,9 +22,6 @@
22 * by David Härdeman. It has since been extended and enhanced pretty much by 22 * by David Härdeman. It has since been extended and enhanced pretty much by
23 * all sorts of friendly Rockbox people. 23 * all sorts of friendly Rockbox people.
24 * 24 *
25 * A nice reference for MPEG header info:
26 * http://rockbox.haxx.se/docs/mpeghdr.html
27 *
28 */ 25 */
29 26
30#include <stdio.h> 27#include <stdio.h>
@@ -37,6 +34,7 @@
37#include "atoi.h" 34#include "atoi.h"
38 35
39#include "id3.h" 36#include "id3.h"
37#include "mp3data.h"
40 38
41#define UNSYNC(b0,b1,b2,b3) (((b0 & 0x7F) << (3*7)) | \ 39#define UNSYNC(b0,b1,b2,b3) (((b0 & 0x7F) << (3*7)) | \
42 ((b1 & 0x7F) << (2*7)) | \ 40 ((b1 & 0x7F) << (2*7)) | \
@@ -48,38 +46,6 @@
48 ((b2 & 0xFF) << (1*8)) | \ 46 ((b2 & 0xFF) << (1*8)) | \
49 ((b3 & 0xFF) << (0*8))) 47 ((b3 & 0xFF) << (0*8)))
50 48
51/* Table of bitrates for MP3 files, all values in kilo.
52 * Indexed by version, layer and value of bit 15-12 in header.
53 */
54const int bitrate_table[2][3][16] =
55{
56 {
57 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
58 {0,32,48,56, 64,80, 96, 112,128,160,192,224,256,320,384,0},
59 {0,32,40,48, 56,64, 80, 96, 112,128,160,192,224,256,320,0}
60 },
61 {
62 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
63 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0},
64 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0}
65 }
66};
67
68/* Table of samples per frame for MP3 files.
69 * Indexed by layer. Multiplied with 1000.
70 */
71const int bs[4] = {0, 384000, 1152000, 1152000};
72
73/* Table of sample frequency for MP3 files.
74 * Indexed by version and layer.
75 */
76const int freqtab[][4] =
77{
78 {11025, 12000, 8000, 0}, /* MPEG version 2.5 */
79 {44100, 48000, 32000, 0}, /* MPEG Version 1 */
80 {22050, 24000, 16000, 0}, /* MPEG version 2 */
81};
82
83/* Checks to see if the passed in string is a 16-bit wide Unicode v2 49/* Checks to see if the passed in string is a 16-bit wide Unicode v2
84 string. If it is, we attempt to convert it to a 8-bit ASCII string 50 string. If it is, we attempt to convert it to a 8-bit ASCII string
85 (for valid 8-bit ASCII characters). If it's not unicode, we leave 51 (for valid 8-bit ASCII characters). If it's not unicode, we leave
@@ -168,6 +134,7 @@ static bool setid3v1title(int fd, struct mp3entry *entry)
168 if (strncmp(buffer, "TAG", 3)) 134 if (strncmp(buffer, "TAG", 3))
169 return false; 135 return false;
170 136
137 entry->id3v1len = 128;
171 entry->id3version = ID3_VER_1_0; 138 entry->id3version = ID3_VER_1_0;
172 139
173 for (i=0; i < (int)sizeof offsets; i++) { 140 for (i=0; i < (int)sizeof offsets; i++) {
@@ -239,6 +206,8 @@ static void setid3v2title(int fd, struct mp3entry *entry)
239 char *tracknum = NULL; 206 char *tracknum = NULL;
240 int bytesread = 0; 207 int bytesread = 0;
241 int buffersize = sizeof(entry->id3v2buf); 208 int buffersize = sizeof(entry->id3v2buf);
209 int flags;
210 int skip;
242 211
243 /* Bail out if the tag is shorter than 10 bytes */ 212 /* Bail out if the tag is shorter than 10 bytes */
244 if(entry->id3v2len < 10) 213 if(entry->id3v2len < 10)
@@ -275,17 +244,34 @@ static void setid3v2title(int fd, struct mp3entry *entry)
275 } 244 }
276 entry->id3version = version; 245 entry->id3version = version;
277 246
247 /* Skip the extended header if it is present */
248 if(version >= ID3_VER_2_4) {
249 if(header[5] & 0x40) {
250 if(4 != read(fd, header, 4))
251 return;
252
253 framelen = UNSYNC(header[0], header[1],
254 header[2], header[3]);
255
256 lseek(fd, framelen - 4, SEEK_CUR);
257 }
258 }
259
278 /* 260 /*
279 * We must have at least minframesize bytes left for the 261 * We must have at least minframesize bytes left for the
280 * remaining frames to be interesting 262 * remaining frames to be interesting
281 */ 263 */
282 while(size > minframesize) { 264 while(size > minframesize) {
265 flags = 0;
266
283 /* Read frame header and check length */ 267 /* Read frame header and check length */
284 if(version >= ID3_VER_2_3) { 268 if(version >= ID3_VER_2_3) {
285 if(10 != read(fd, header, 10)) 269 if(10 != read(fd, header, 10))
286 return; 270 return;
287 /* Adjust for the 10 bytes we read */ 271 /* Adjust for the 10 bytes we read */
288 size -= 10; 272 size -= 10;
273
274 flags = BYTES2INT(0, 0, header[8], header[9]);
289 275
290 if (version >= ID3_VER_2_4) { 276 if (version >= ID3_VER_2_4) {
291 framelen = UNSYNC(header[4], header[5], 277 framelen = UNSYNC(header[4], header[5],
@@ -311,6 +297,33 @@ static void setid3v2title(int fd, struct mp3entry *entry)
311 if(framelen == 0) 297 if(framelen == 0)
312 return; 298 return;
313 299
300 if(flags)
301 {
302 skip = 0;
303
304 if(flags & 0x0040) /* Grouping identity */
305 skip++;
306
307 if(flags & 0x000e) /* Compression, encryption or
308 unsynchronization */
309 {
310 /* Skip it using the total size in case
311 it was truncated */
312 size -= totframelen;
313 lseek(fd, totframelen, SEEK_CUR);
314 continue;
315 }
316
317 if(flags & 0x0001) /* Data length indicator */
318 skip += 4;
319
320 if(skip)
321 {
322 lseek(fd, skip, SEEK_CUR);
323 framelen -= skip;
324 }
325 }
326
314 /* If the frame is larger than the remaining buffer space we try 327 /* If the frame is larger than the remaining buffer space we try
315 to read as much as would fit in the buffer */ 328 to read as much as would fit in the buffer */
316 if(framelen >= buffersize - bufferpos) 329 if(framelen >= buffersize - bufferpos)
@@ -404,6 +417,7 @@ static int getid3v2len(int fd)
404 else 417 else
405 offset = UNSYNC(buf[0], buf[1], buf[2], buf[3]) + 10; 418 offset = UNSYNC(buf[0], buf[1], buf[2], buf[3]) + 10;
406 419
420 DEBUGF("ID3V2 Length: 0x%x\n", offset);
407 return offset; 421 return offset;
408} 422}
409 423
@@ -419,29 +433,6 @@ static int getfilesize(int fd)
419 return size; 433 return size;
420} 434}
421 435
422/* check if 'head' is a valid mp3 frame header */
423static bool mp3frameheader(unsigned long head)
424{
425 if ((head & 0xffe00000) != 0xffe00000) /* bad sync? */
426 return false;
427 if (!((head >> 17) & 3)) /* no layer? */
428 return false;
429 if (((head >> 12) & 0xf) == 0xf) /* bad bitrate? */
430 return false;
431 if (!((head >> 12) & 0xf)) /* no bitrate? */
432 return false;
433 if (((head >> 10) & 0x3) == 0x3) /* bad sample rate? */
434 return false;
435 if (((head >> 19) & 1) == 1 &&
436 ((head >> 17) & 3) == 3 &&
437 ((head >> 16) & 1) == 1)
438 return false;
439 if ((head & 0xffff0000) == 0xfffe0000)
440 return false;
441
442 return true;
443}
444
445/* 436/*
446 * Calculates the length (in milliseconds) of an MP3 file. 437 * Calculates the length (in milliseconds) of an MP3 file.
447 * 438 *
@@ -456,263 +447,48 @@ static bool mp3frameheader(unsigned long head)
456static int getsonglength(int fd, struct mp3entry *entry) 447static int getsonglength(int fd, struct mp3entry *entry)
457{ 448{
458 unsigned int filetime = 0; 449 unsigned int filetime = 0;
459 unsigned long header=0; 450 struct mp3info info;
460 unsigned char tmp;
461 unsigned char frame[156];
462 unsigned char* xing;
463
464 enum {
465 MPEG_VERSION2_5,
466 MPEG_VERSION1,
467 MPEG_VERSION2
468 } version;
469 int layer;
470 int bitindex;
471 int bitrate;
472 int freqindex;
473 int frequency;
474 int chmode;
475 int bytecount; 451 int bytecount;
476 int bytelimit; 452
477 int bittable; /* which bitrate table to use */
478 bool header_found = false;
479
480 long bpf;
481 long tpf;
482
483 /* Start searching after ID3v2 header */ 453 /* Start searching after ID3v2 header */
484 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET)) 454 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET))
485 return 0; 455 return 0;
486
487 /* Fill up header with first 24 bits */
488 for(version = 0; version < 3; version++) {
489 header <<= 8;
490 if(!read(fd, &tmp, 1))
491 return 0;
492 header |= tmp;
493 }
494
495 /* Loop trough file until we find a frame header */
496 bytecount = entry->id3v2len - 1;
497 bytelimit = entry->id3v2len + 0x20000;
498 restart:
499 do {
500 header <<= 8;
501 if(!read(fd, &tmp, 1))
502 return 0;
503 header |= tmp;
504 456
505 /* Quit if we haven't found a valid header within 128K */ 457 bytecount = get_mp3file_info(fd, &info);
506 bytecount++;
507 if(bytecount > bytelimit)
508 return 0;
509 } while(!mp3frameheader(header));
510
511 /*
512 * Some files are filled with garbage in the beginning,
513 * if the bitrate index of the header is binary 1111
514 * that is a good indicator
515 */
516 if((header & 0xF000) == 0xF000)
517 goto restart;
518
519 /* MPEG Audio Version */
520 switch((header & 0x180000) >> 19) {
521 case 0:
522 /* MPEG version 2.5 is not an official standard */
523 version = MPEG_VERSION2_5;
524 bittable = MPEG_VERSION2; /* use the V2 bit rate table */
525 break;
526 458
527 case 2: 459 DEBUGF("Space between ID3V2 tag and first audio frame: 0x%x bytes\n",
528 /* MPEG version 2 (ISO/IEC 13818-3) */ 460 bytecount);
529 version = MPEG_VERSION2;
530 bittable = MPEG_VERSION2;
531 break;
532 461
533 case 3: 462 if(bytecount < 0)
534 /* MPEG version 1 (ISO/IEC 11172-3) */
535 version = MPEG_VERSION1;
536 bittable = MPEG_VERSION1;
537 break;
538 default:
539 goto restart;
540 }
541
542 /* Layer */
543 switch((header & 0x060000) >> 17) {
544 case 1:
545 layer = 3;
546 break;
547 case 2:
548 layer = 2;
549 break;
550 case 3:
551 layer = 1;
552 break;
553 default:
554 goto restart;
555 }
556
557 /* Bitrate */
558 bitindex = (header & 0xF000) >> 12;
559 bitrate = bitrate_table[bittable-1][layer-1][bitindex];
560 if(bitrate == 0)
561 goto restart;
562
563 /* Sampling frequency */
564 freqindex = (header & 0x0C00) >> 10;
565 frequency = freqtab[version][freqindex];
566 if(frequency == 0)
567 goto restart;
568
569#ifdef DEBUG_VERBOSE
570 DEBUGF( "Version %i, lay %i, biti %i, bitr %i, freqi %i, freq %i, chmode %d\n",
571 version, layer, bitindex, bitrate, freqindex, frequency, chmode);
572#endif
573 entry->version = version;
574 entry->layer = layer;
575 entry->frequency = frequency;
576
577 /* Calculate bytes per frame, calculation depends on layer */
578 switch(layer) {
579 case 1:
580 bpf = bitrate_table[bittable - 1][layer - 1][bitindex];
581 bpf *= 48000;
582 bpf /= freqtab[version][freqindex] << (bittable - 1);
583 break;
584 case 2:
585 case 3:
586 bpf = bitrate_table[bittable - 1][layer - 1][bitindex];
587 bpf *= 144000;
588 bpf /= freqtab[version][freqindex] << (bittable - 1);
589 break;
590 default:
591 bpf = 1;
592 }
593
594 /* Calculate time per frame */
595 tpf = bs[layer] / (freqtab[version][freqindex] << (bittable - 1));
596
597 entry->bpf = bpf;
598 entry->tpf = tpf;
599
600 /* OK, we have found a frame. Let's see if it has a Xing header */
601 if(read(fd, frame, sizeof frame) < 0)
602 return -1; 463 return -1;
464
465 bytecount += entry->id3v2len;
603 466
604 /* Channel mode (stereo/mono) */ 467 entry->bitrate = info.bitrate;
605 chmode = (header & 0xc0) >> 6;
606
607 /* calculate position of Xing VBR header */
608 if ( version == 1 ) {
609 if ( chmode == 3 ) /* mono */
610 xing = frame + 17;
611 else
612 xing = frame + 32;
613 }
614 else {
615 if ( chmode == 3 ) /* mono */
616 xing = frame + 9;
617 else
618 xing = frame + 17;
619 }
620
621 if (xing[0] == 'X' &&
622 xing[1] == 'i' &&
623 xing[2] == 'n' &&
624 xing[3] == 'g')
625 {
626 int i = 8; /* Where to start parsing info */
627
628 /* Yes, it is a VBR file */
629 entry->vbr = true;
630 entry->vbrflags = xing[7];
631
632 if (entry->vbrflags & VBR_FRAMES_FLAG) /* Is the frame count there? */
633 {
634 int framecount = (xing[i] << 24) | (xing[i+1] << 16) |
635 (xing[i+2] << 8) | xing[i+3];
636
637 filetime = framecount * tpf;
638 i += 4;
639 }
640
641 if (entry->vbrflags & VBR_BYTES_FLAG) /* is byte count there? */
642 {
643 int bytecount = (xing[i] << 24) | (xing[i+1] << 16) |
644 (xing[i+2] << 8) | xing[i+3];
645
646 bitrate = bytecount * 8 / filetime;
647 i += 4;
648 }
649
650 if (entry->vbrflags & VBR_TOC_FLAG) /* is table-of-contents there? */
651 {
652 memcpy( entry->toc, xing+i, 100 );
653 }
654
655 /* Make sure we skip this frame in playback */
656 bytecount += bpf;
657
658 header_found = true;
659 }
660
661 if (xing[0] == 'V' &&
662 xing[1] == 'B' &&
663 xing[2] == 'R' &&
664 xing[3] == 'I')
665 {
666 int framecount;
667 int bytecount;
668
669 /* Yes, it is a FhG VBR file */
670 entry->vbr = true;
671 entry->vbrflags = 0;
672
673 bytecount = (xing[10] << 24) | (xing[11] << 16) |
674 (xing[12] << 8) | xing[13];
675
676 framecount = (xing[14] << 24) | (xing[15] << 16) |
677 (xing[16] << 8) | xing[17];
678
679 filetime = framecount * tpf;
680 bitrate = bytecount * 8 / filetime;
681
682 /* We don't parse the TOC, since we don't yet know how to (FIXME) */
683
684 /* Make sure we skip this frame in playback */
685 bytecount += bpf;
686
687 header_found = true;
688 }
689
690 /* Is it a LAME Info frame? */
691 if (xing[0] == 'I' &&
692 xing[1] == 'n' &&
693 xing[2] == 'f' &&
694 xing[3] == 'o')
695 {
696 /* Make sure we skip this frame in playback */
697 bytecount += bpf;
698
699 header_found = true;
700 }
701
702
703 entry->bitrate = bitrate;
704 468
705 /* If the file time hasn't been established, this may be a fixed 469 /* If the file time hasn't been established, this may be a fixed
706 rate MP3, so just use the default formula */ 470 rate MP3, so just use the default formula */
471
472 filetime = info.file_time;
473
707 if(filetime == 0) 474 if(filetime == 0)
708 { 475 {
709 /* 476 /*
710 * Now song length is 477 * Now song length is
711 * ((filesize)/(bytes per frame))*(time per frame) 478 * ((filesize)/(bytes per frame))*(time per frame)
712 */ 479 */
713 filetime = entry->filesize/bpf*tpf; 480 filetime = entry->filesize/info.frame_size*info.frame_time;
714 } 481 }
715 482
483 entry->tpf = info.frame_time;
484 entry->bpf = info.frame_size;
485
486 entry->vbr = info.is_vbr;
487 entry->has_toc = info.has_toc;
488 memcpy(entry->toc, info.toc, sizeof(info.toc));
489
490 entry->xing_header_pos = info.xing_header_pos;
491
716 /* Update the seek point for the first playable frame */ 492 /* Update the seek point for the first playable frame */
717 entry->first_frame_offset = bytecount; 493 entry->first_frame_offset = bytecount;
718 DEBUGF("First frame is at %x\n", entry->first_frame_offset); 494 DEBUGF("First frame is at %x\n", entry->first_frame_offset);
@@ -720,7 +496,6 @@ static int getsonglength(int fd, struct mp3entry *entry)
720 return filetime; 496 return filetime;
721} 497}
722 498
723
724/* 499/*
725 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc) 500 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc)
726 * about an MP3 file and updates it's entry accordingly. 501 * about an MP3 file and updates it's entry accordingly.
@@ -750,6 +525,10 @@ bool mp3info(struct mp3entry *entry, char *filename)
750 setid3v2title(fd, entry); 525 setid3v2title(fd, entry);
751 entry->length = getsonglength(fd, entry); 526 entry->length = getsonglength(fd, entry);
752 527
528 /* Subtract the meta information from the file size to get
529 the true size of the MP3 stream */
530 entry->filesize -= entry->first_frame_offset;
531
753 /* only seek to end of file if no id3v2 tags were found */ 532 /* only seek to end of file if no id3v2 tags were found */
754 if (!entry->id3v2len) { 533 if (!entry->id3v2len) {
755 if(!entry->title) 534 if(!entry->title)
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
new file mode 100644
index 0000000000..8d925041ce
--- /dev/null
+++ b/firmware/mp3data.c
@@ -0,0 +1,664 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Daniel Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/*
21 * Parts of this code has been stolen from the Ample project and was written
22 * by David Härdeman. It has since been extended and enhanced pretty much by
23 * all sorts of friendly Rockbox people.
24 *
25 * A nice reference for MPEG header info:
26 * http://rockbox.haxx.se/docs/mpeghdr.html
27 *
28 */
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <stdbool.h>
34#include "debug.h"
35#include "mp3data.h"
36#include "file.h"
37
38#define DEBUG_VERBOSE
39
40#define BYTES2INT(b1,b2,b3,b4) (((b1 & 0xFF) << (3*8)) | \
41 ((b2 & 0xFF) << (2*8)) | \
42 ((b3 & 0xFF) << (1*8)) | \
43 ((b4 & 0xFF) << (0*8)))
44
45#define SYNC_MASK (0x7ff << 21)
46#define VERSION_MASK (3 << 19)
47#define LAYER_MASK (3 << 17)
48#define PROTECTION_MASK (1 << 16)
49#define BITRATE_MASK (0xf << 12)
50#define SAMPLERATE_MASK (3 << 10)
51#define PADDING_MASK (1 << 9)
52#define PRIVATE_MASK (1 << 8)
53#define CHANNELMODE_MASK (3 << 6)
54#define MODE_EXT_MASK (3 << 4)
55#define COPYRIGHT_MASK (1 << 3)
56#define ORIGINAL_MASK (1 << 2)
57#define EMPHASIS_MASK 3
58
59/* Table of bitrates for MP3 files, all values in kilo.
60 * Indexed by version, layer and value of bit 15-12 in header.
61 */
62const int bitrate_table[2][3][16] =
63{
64 {
65 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
66 {0,32,48,56, 64,80, 96, 112,128,160,192,224,256,320,384,0},
67 {0,32,40,48, 56,64, 80, 96, 112,128,160,192,224,256,320,0}
68 },
69 {
70 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
71 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0},
72 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0}
73 }
74};
75
76/* Table of samples per frame for MP3 files.
77 * Indexed by layer. Multiplied with 1000.
78 */
79const int bs[3] = {384000, 1152000, 1152000};
80
81/* Table of sample frequency for MP3 files.
82 * Indexed by version and layer.
83 */
84
85const int freqtab[][4] =
86{
87 {11025, 12000, 8000, 0}, /* MPEG version 2.5 */
88 {44100, 48000, 32000, 0}, /* MPEG Version 1 */
89 {22050, 24000, 16000, 0}, /* MPEG version 2 */
90};
91
92/* check if 'head' is a valid mp3 frame header */
93static bool is_mp3frameheader(unsigned long head)
94{
95 if ((head & SYNC_MASK) != (unsigned long)SYNC_MASK) /* bad sync? */
96 return false;
97 if ((head & VERSION_MASK) == (1 << 19)) /* bad version? */
98 return false;
99 if (!(head & LAYER_MASK)) /* no layer? */
100 return false;
101 if ((head & BITRATE_MASK) == BITRATE_MASK) /* bad bitrate? */
102 return false;
103 if (!(head & BITRATE_MASK)) /* no bitrate? */
104 return false;
105 if ((head & SAMPLERATE_MASK) == SAMPLERATE_MASK) /* bad sample rate? */
106 return false;
107 if (((head >> 19) & 1) == 1 &&
108 ((head >> 17) & 3) == 3 &&
109 ((head >> 16) & 1) == 1)
110 return false;
111 if ((head & 0xffff0000) == 0xfffe0000)
112 return false;
113
114 return true;
115}
116
117static bool mp3headerinfo(struct mp3info *info, unsigned long header)
118{
119 int bittable = 0;
120 int bitindex;
121 int freqindex;
122
123 /* MPEG Audio Version */
124 switch(header & VERSION_MASK) {
125 case 0:
126 /* MPEG version 2.5 is not an official standard */
127 info->version = MPEG_VERSION2_5;
128 bittable = MPEG_VERSION2 - 1; /* use the V2 bit rate table */
129 break;
130
131 case (1 << 19):
132 return false;
133
134 case (2 << 19):
135 /* MPEG version 2 (ISO/IEC 13818-3) */
136 info->version = MPEG_VERSION2;
137 bittable = MPEG_VERSION2 - 1;
138 break;
139
140 case (3 << 19):
141 /* MPEG version 1 (ISO/IEC 11172-3) */
142 info->version = MPEG_VERSION1;
143 bittable = MPEG_VERSION1 - 1;
144 break;
145 }
146
147 switch(header & LAYER_MASK) {
148 case 0:
149 return false;
150 case (1 << 17):
151 info->layer = 2;
152 break;
153 case (2 << 17):
154 info->layer = 1;
155 break;
156 case (3 << 17):
157 info->layer = 0;
158 break;
159 }
160
161 info->protection = (header & PROTECTION_MASK)?true:false;
162
163 /* Bitrate */
164 bitindex = (header & 0xf000) >> 12;
165 info->bitrate = bitrate_table[bittable][info->layer][bitindex];
166 if(info->bitrate == 0)
167 return false;
168
169 /* Sampling frequency */
170 freqindex = (header & 0x0C00) >> 10;
171 info->frequency = freqtab[info->version][freqindex];
172 if(info->frequency == 0)
173 return false;
174
175 info->padding = (header & 0x0200)?1:0;
176
177 /* Calculate number of bytes, calculation depends on layer */
178 switch(info->layer) {
179 case 0:
180 info->frame_size = info->bitrate * 48000;
181 info->frame_size /=
182 freqtab[info->version][freqindex] << bittable;
183 break;
184 case 1:
185 case 2:
186 info->frame_size = info->bitrate * 144000;
187 info->frame_size /=
188 freqtab[info->version][freqindex] << bittable;
189 break;
190 default:
191 info->frame_size = 1;
192 }
193
194 info->frame_size += info->padding;
195
196 /* Calculate time per frame */
197 info->frame_time = bs[info->layer] /
198 (freqtab[info->version][freqindex] << bittable);
199
200 info->channel_mode = (header & 0xc0) >> 6;
201 info->mode_extension = (header & 0x30) >> 4;
202 info->emphasis = header & 3;
203
204#ifdef DEBUG_VERBOSE
205 DEBUGF( "Header: %08x, Ver %d, lay %d, bitr %d, freq %d, "
206 "chmode %d, mode_ext %d, emph %d, bytes: %d time: %d\n",
207 header, info->version, info->layer, info->bitrate, info->frequency,
208 info->channel_mode, info->mode_extension,
209 info->emphasis, info->frame_size, info->frame_time);
210#endif
211 return true;
212}
213
214unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header)
215{
216 unsigned long header=0;
217 unsigned char tmp;
218 int i;
219
220 int pos = 0;
221
222 /* We remember the last header we found, to use as a template to see if
223 the header we find has the same frequency, layer etc */
224 last_header &= 0xffff0c00;
225
226 /* Fill up header with first 24 bits */
227 for(i = 0; i < 3; i++) {
228 header <<= 8;
229 if(!read(fd, &tmp, 1))
230 return 0;
231 header |= tmp;
232 pos++;
233 }
234
235 do {
236 header <<= 8;
237 if(!read(fd, &tmp, 1))
238 return 0;
239 header |= tmp;
240 pos++;
241 if(max_offset > 0 && pos > max_offset)
242 return 0;
243 } while(!is_mp3frameheader(header) ||
244 (last_header?((header & 0xffff0c00) != last_header):false));
245
246 *offset = pos - 4;
247
248#ifdef DEBUG
249 if(*offset)
250 DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
251#endif
252
253 return header;
254}
255
256#ifdef SIMULATOR
257unsigned char mp3buf[0x100000];
258unsigned char mp3end[1];
259#else
260extern unsigned char mp3buf[];
261extern unsigned char mp3end[];
262#endif
263static int fnf_read_index;
264static int fnf_buf_len;
265
266static int fd;
267
268static int buf_getbyte(unsigned char *c)
269{
270 if(fnf_read_index < fnf_buf_len)
271 {
272 *c = mp3buf[fnf_read_index++];
273 return 1;
274 }
275 else
276 {
277 fnf_buf_len = read(fd, mp3buf, mp3end - mp3buf);
278 if(fnf_buf_len < 0)
279 return -1;
280
281 fnf_read_index = 0;
282
283 if(fnf_buf_len > 0)
284 {
285 *c = mp3buf[fnf_read_index++];
286 return 1;
287 }
288 else
289 return 0;
290 }
291 return 0;
292}
293
294static int buf_seek(int len)
295{
296 fnf_read_index += len;
297 if(fnf_read_index > fnf_buf_len)
298 {
299 len = fnf_read_index - fnf_buf_len;
300
301 fnf_buf_len = read(fd, mp3buf, mp3end - mp3buf);
302 if(fnf_buf_len < 0)
303 return -1;
304
305 fnf_read_index = 0;
306 fnf_read_index += len;
307 }
308
309 if(fnf_read_index > fnf_buf_len)
310 {
311 return -1;
312 }
313 else
314 return 0;
315}
316
317static void buf_init(void)
318{
319 fnf_buf_len = 0;
320 fnf_read_index = 0;
321}
322
323unsigned long buf_find_next_frame(int *offset, int max_offset,
324 unsigned long last_header)
325{
326 unsigned long header=0;
327 unsigned char tmp;
328 int i;
329
330 int pos = 0;
331
332 /* We remember the last header we found, to use as a template to see if
333 the header we find has the same frequency, layer etc */
334 last_header &= 0xffff0c00;
335
336 /* Fill up header with first 24 bits */
337 for(i = 0; i < 3; i++) {
338 header <<= 8;
339 if(!buf_getbyte(&tmp))
340 return 0;
341 header |= tmp;
342 pos++;
343 }
344
345 do {
346 header <<= 8;
347 if(!buf_getbyte(&tmp))
348 return 0;
349 header |= tmp;
350 pos++;
351 if(max_offset > 0 && pos > max_offset)
352 return 0;
353 } while(!is_mp3frameheader(header) ||
354 (last_header?((header & 0xffff0c00) != last_header):false));
355
356 *offset = pos - 4;
357
358#ifdef DEBUG
359 if(*offset)
360 DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
361#endif
362
363 return header;
364}
365
366int get_mp3file_info(int fd, struct mp3info *info)
367{
368 unsigned char frame[1024];
369 unsigned char *vbrheader;
370 unsigned long header;
371 int bytecount;
372 int num_offsets;
373 int frames_per_entry;
374 int i;
375 int offset;
376 int j;
377 int tmp;
378
379 header = find_next_frame(fd, &bytecount, 0x20000, 0);
380 /* Quit if we haven't found a valid header within 128K */
381 if(header == 0)
382 return -1;
383
384 memset(info, 0, sizeof(struct mp3info));
385 if(!mp3headerinfo(info, header))
386 return -2;
387
388 /* OK, we have found a frame. Let's see if it has a Xing header */
389 if(read(fd, frame, info->frame_size-4) < 0)
390 return -3;
391
392 /* calculate position of VBR header */
393 if ( info->version == MPEG_VERSION1 ) {
394 if (info->channel_mode == 3) /* mono */
395 vbrheader = frame + 17;
396 else
397 vbrheader = frame + 32;
398 }
399 else {
400 if (info->channel_mode == 3) /* mono */
401 vbrheader = frame + 9;
402 else
403 vbrheader = frame + 17;
404 }
405
406 if (vbrheader[0] == 'X' &&
407 vbrheader[1] == 'i' &&
408 vbrheader[2] == 'n' &&
409 vbrheader[3] == 'g')
410 {
411 int i = 8; /* Where to start parsing info */
412
413 DEBUGF("Xing header\n");
414
415 /* Remember where in the file the Xing header is */
416 info->xing_header_pos = lseek(fd, 0, SEEK_CUR) - info->frame_size;
417
418 /* We want to skip the Xing frame when playing the stream */
419 bytecount += info->frame_size;
420
421 /* Now get the next frame to find out the real info about
422 the mp3 stream */
423 header = find_next_frame(fd, &tmp, 0x20000, 0);
424 if(header == 0)
425 return -4;
426
427 if(!mp3headerinfo(info, header))
428 return -5;
429
430 /* Yes, it is a VBR file */
431 info->is_vbr = true;
432 info->is_xing_vbr = true;
433
434 if(vbrheader[7] & VBR_FRAMES_FLAG) /* Is the frame count there? */
435 {
436 info->frame_count = BYTES2INT(vbrheader[i], vbrheader[i+1],
437 vbrheader[i+2], vbrheader[i+3]);
438 info->file_time = info->frame_count * info->frame_time;
439 i += 4;
440 }
441
442 if(vbrheader[7] & VBR_BYTES_FLAG) /* Is byte count there? */
443 {
444 info->byte_count = BYTES2INT(vbrheader[i], vbrheader[i+1],
445 vbrheader[i+2], vbrheader[i+3]);
446 info->bitrate = info->byte_count * 8 / info->file_time;
447 i += 4;
448 }
449
450 if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */
451 {
452 memcpy( info->toc, vbrheader+i, 100 );
453 }
454 }
455
456 if (vbrheader[0] == 'V' &&
457 vbrheader[1] == 'B' &&
458 vbrheader[2] == 'R' &&
459 vbrheader[3] == 'I')
460 {
461 DEBUGF("VBRI header\n");
462
463 /* We want to skip the VBRI frame when playing the stream */
464 bytecount += info->frame_size;
465
466 /* Now get the next frame to find out the real info about
467 the mp3 stream */
468 header = find_next_frame(fd, &bytecount, 0x20000, 0);
469 if(header == 0)
470 return -6;
471
472 if(!mp3headerinfo(info, header))
473 return -7;
474
475 DEBUGF("%04x: %04x %04x ", 0, header >> 16, header & 0xffff);
476 for(i = 4;i < (int)sizeof(frame)-4;i+=2) {
477 if(i % 16 == 0) {
478 DEBUGF("\n%04x: ", i-4);
479 }
480 DEBUGF("%04x ", (frame[i-4] << 8) | frame[i-4+1]);
481 }
482
483 DEBUGF("\n");
484
485 /* Yes, it is a FhG VBR file */
486 info->is_vbr = true;
487 info->is_vbri_vbr = true;
488 info->has_toc = false; /* We don't parse the TOC (yet) */
489
490 info->byte_count = BYTES2INT(vbrheader[10], vbrheader[11],
491 vbrheader[12], vbrheader[13]);
492 info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15],
493 vbrheader[16], vbrheader[17]);
494
495 info->file_time = info->frame_count * info->frame_time;
496 info->bitrate = info->byte_count * 8 / info->file_time;
497
498 /* We don't parse the TOC, since we don't yet know how to (FIXME) */
499 num_offsets = BYTES2INT(0, 0, vbrheader[18], vbrheader[19]);
500 frames_per_entry = BYTES2INT(0, 0, vbrheader[24], vbrheader[25]);
501 DEBUGF("Frame size (%dkpbs): %d bytes (0x%x)\n",
502 info->bitrate, info->frame_size, info->frame_size);
503 DEBUGF("Frame count: %x\n", info->frame_count);
504 DEBUGF("Byte count: %x\n", info->byte_count);
505 DEBUGF("Offsets: %d\n", num_offsets);
506 DEBUGF("Frames/entry: %d\n", frames_per_entry);
507
508 offset = 0;
509
510 for(i = 0;i < num_offsets;i++)
511 {
512 j = BYTES2INT(0, 0, vbrheader[26+i*2], vbrheader[27+i*2]);
513 offset += j;
514 DEBUGF("%03d: %x (%x)\n", i, offset - bytecount, j);
515 }
516 }
517
518 /* Is it a LAME Info frame? */
519 if (vbrheader[0] == 'I' &&
520 vbrheader[1] == 'n' &&
521 vbrheader[2] == 'f' &&
522 vbrheader[3] == 'o')
523 {
524 /* Make sure we skip this frame in playback */
525 bytecount += info->frame_size;
526 }
527
528 return bytecount;
529}
530
531/* This is an MP3 header, 128kbit/s, 44.1kHz, with silence */
532static const unsigned char xing_frame_header[] = {
533 0xff, 0xfa, 0x90, 0x64, 0x86, 0x1f
534};
535
536static const char cooltext[] = "Rockbox rocks";
537
538static void int2bytes(unsigned char *buf, int val)
539{
540 buf[0] = (val >> 24) & 0xff;
541 buf[1] = (val >> 16) & 0xff;
542 buf[2] = (val >> 8) & 0xff;
543 buf[3] = val & 0xff;
544}
545
546int count_mp3_frames(int fd, int startpos, int filesize,
547 void (*progressfunc)(int))
548{
549 unsigned long header = 0;
550 struct mp3info info;
551 int num_frames;
552 int bytes;
553 int cnt;
554 int progress_chunk = filesize / 50; /* Max is 50%, in 1% increments */
555 int progress_cnt = 0;
556
557 if(lseek(fd, startpos, SEEK_SET) < 0)
558 return -1;
559
560 buf_init();
561
562 /* Find out the total number of frames */
563 num_frames = 0;
564 cnt = 0;
565
566 while((header = buf_find_next_frame(&bytes, -1, header))) {
567 mp3headerinfo(&info, header);
568 buf_seek(info.frame_size-4);
569 num_frames++;
570 if(progressfunc)
571 {
572 cnt += bytes + info.frame_size;
573 if(cnt > progress_chunk)
574 {
575 progress_cnt++;
576 progressfunc(progress_cnt);
577 cnt = 0;
578 }
579 }
580 }
581 DEBUGF("Total number of frames: %d\n", num_frames);
582
583 return num_frames;
584}
585
586int create_xing_header(int fd, int startpos, int filesize,
587 unsigned char *buf, int num_frames,
588 void (*progressfunc)(int))
589{
590 unsigned long header = 0;
591 struct mp3info info;
592 int pos, last_pos;
593 int i, j;
594 int bytes;
595 int filepos;
596 int tocentry;
597 int x;
598
599 DEBUGF("create_xing_header()\n");
600
601 /* Create the frame header */
602 memset(buf, 0, 417);
603 memcpy(buf, xing_frame_header, 6);
604
605 lseek(fd, startpos, SEEK_SET);
606 buf_init();
607
608 buf[36] = 'X';
609 buf[36+1] = 'i';
610 buf[36+2] = 'n';
611 buf[36+3] = 'g';
612 int2bytes(&buf[36+4], (VBR_FRAMES_FLAG | VBR_BYTES_FLAG | VBR_TOC_FLAG));
613 int2bytes(&buf[36+8], num_frames);
614 int2bytes(&buf[36+12], filesize - startpos);
615
616 /* Generate filepos table */
617 last_pos = 0;
618 filepos = 0;
619 header = 0;
620 x = 0;
621 for(i = 0;i < 100;i++) {
622 /* Calculate the absolute frame number for this seek point */
623 pos = i * num_frames / 100;
624
625 /* Advance from the last seek point to this one */
626 for(j = 0;j < pos - last_pos;j++)
627 {
628 DEBUGF("fpos: %x frame no: %x ", filepos, x++);
629 header = buf_find_next_frame(&bytes, -1, header);
630 mp3headerinfo(&info, header);
631 buf_seek(info.frame_size-4);
632 filepos += info.frame_size;
633 }
634
635 if(progressfunc)
636 {
637 progressfunc(50 + i/2);
638 }
639
640 tocentry = filepos * 256 / filesize;
641
642 DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n",
643 i, pos, pos-last_pos, filepos, tocentry);
644
645 /* Fill in the TOC entry */
646 buf[36+16+i] = tocentry;
647
648 last_pos = pos;
649 }
650
651 memcpy(buf+152, cooltext, sizeof(cooltext));
652
653#ifdef DEBUG
654 for(i = 0;i < 417;i++)
655 {
656 if(i && !(i % 16))
657 DEBUGF("\n");
658
659 DEBUGF("%02x ", buf[i]);
660 }
661#endif
662
663 return 0;
664}
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 9470e7d84b..92f11e1b84 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -26,6 +26,7 @@
26#include "string.h" 26#include "string.h"
27#include <kernel.h> 27#include <kernel.h>
28#include "thread.h" 28#include "thread.h"
29#include "mp3data.h"
29#ifndef SIMULATOR 30#ifndef SIMULATOR
30#include "i2c.h" 31#include "i2c.h"
31#include "mas.h" 32#include "mas.h"
@@ -302,7 +303,7 @@ static void remove_all_tags(void)
302static void set_elapsed(struct mp3entry* id3) 303static void set_elapsed(struct mp3entry* id3)
303{ 304{
304 if ( id3->vbr ) { 305 if ( id3->vbr ) {
305 if ( id3->vbrflags & VBR_TOC_FLAG ) { 306 if ( id3->has_toc ) {
306 /* calculate elapsed time using TOC */ 307 /* calculate elapsed time using TOC */
307 int i; 308 int i;
308 unsigned int remainder, plen, relpos, nextpos; 309 unsigned int remainder, plen, relpos, nextpos;
@@ -1482,7 +1483,7 @@ static void mpeg_thread(void)
1482 1483
1483 if (id3->vbr) 1484 if (id3->vbr)
1484 { 1485 {
1485 if (id3->vbrflags & VBR_TOC_FLAG) 1486 if (id3->has_toc)
1486 { 1487 {
1487 /* Use the TOC to find the new position */ 1488 /* Use the TOC to find the new position */
1488 unsigned int percent, remainder; 1489 unsigned int percent, remainder;
@@ -1528,10 +1529,10 @@ static void mpeg_thread(void)
1528 transition properly to the next song */ 1529 transition properly to the next song */
1529 newpos = id3->filesize - id3->id3v1len - 1; 1530 newpos = id3->filesize - id3->id3v1len - 1;
1530 } 1531 }
1531 else if (newpos < (int)id3->id3v2len) 1532 else if (newpos < (int)id3->first_frame_offset)
1532 { 1533 {
1533 /* skip past id3v2 tag */ 1534 /* skip past id3v2 tag and other leading garbage */
1534 newpos = id3->id3v2len; 1535 newpos = id3->first_frame_offset;
1535 } 1536 }
1536 1537
1537 if (mpeg_file >= 0) 1538 if (mpeg_file >= 0)
@@ -1720,7 +1721,7 @@ static void mpeg_thread(void)
1720 t2 = current_tick; 1721 t2 = current_tick;
1721 DEBUGF("time: %d\n", t2 - t1); 1722 DEBUGF("time: %d\n", t2 - t1);
1722 DEBUGF("R: %x\n", len); 1723 DEBUGF("R: %x\n", len);
1723 1724
1724 /* Now make sure that we don't feed the MAS with ID3V1 1725 /* Now make sure that we don't feed the MAS with ID3V1
1725 data */ 1726 data */
1726 if (len < amount_to_read) 1727 if (len < amount_to_read)
@@ -1734,19 +1735,19 @@ static void mpeg_thread(void)
1734 { 1735 {
1735 if(tagptr >= mp3buflen) 1736 if(tagptr >= mp3buflen)
1736 tagptr -= mp3buflen; 1737 tagptr -= mp3buflen;
1737 1738
1738 if(mp3buf[tagptr] != tag[i]) 1739 if(mp3buf[tagptr] != tag[i])
1739 taglen = 0; 1740 taglen = 0;
1740 1741
1741 tagptr++; 1742 tagptr++;
1742 } 1743 }
1743 1744
1744 if(taglen) 1745 if(taglen)
1745 { 1746 {
1746 /* Skip id3v1 tag */ 1747 /* Skip id3v1 tag */
1747 DEBUGF("Skipping ID3v1 tag\n"); 1748 DEBUGF("Skipping ID3v1 tag\n");
1748 len -= taglen; 1749 len -= taglen;
1749 1750
1750 /* The very rare case when the entire tag 1751 /* The very rare case when the entire tag
1751 wasn't read in this read() call must be 1752 wasn't read in this read() call must be
1752 taken care of */ 1753 taken care of */
@@ -1819,131 +1820,135 @@ static void mpeg_thread(void)
1819 } 1820 }
1820 else 1821 else
1821 { 1822 {
1822 /* This doesn't look neccessary... 1823 queue_wait(&mpeg_queue, &ev);
1823 yield(); 1824 switch(ev.id)
1824 if(!queue_empty(&mpeg_queue)) 1825 {
1825 {*/ 1826 case MPEG_RECORD:
1826 queue_wait(&mpeg_queue, &ev); 1827 DEBUGF("Recording...\n");
1827 switch(ev.id) 1828 reset_mp3_buffer();
1828 {
1829 case MPEG_RECORD:
1830 DEBUGF("Recording...\n");
1831 reset_mp3_buffer();
1832 start_recording();
1833 demand_irq_enable(true);
1834 mpeg_file = creat(recording_filename, O_WRONLY);
1835
1836 if(mpeg_file < 0)
1837 panicf("recfile: %d", mpeg_file);
1838
1839 close(mpeg_file);
1840 mpeg_file = -1;
1841 break;
1842
1843 case MPEG_STOP:
1844 DEBUGF("MPEG_STOP\n");
1845 demand_irq_enable(false);
1846 stop_recording();
1847
1848 /* Save the remaining data in the buffer */
1849 stop_pending = true;
1850 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1851 break;
1852 1829
1853 case MPEG_STOP_DONE: 1830 /* Advance the write pointer 4096+417 bytes to make
1854 DEBUGF("MPEG_STOP_DONE\n"); 1831 room for an ID3 tag plus a VBR header */
1832 mp3buf_write = 4096+417;
1833 memset(mp3buf, 0, 4096+417);
1855 1834
1856 if(mpeg_file >= 0) 1835 start_recording();
1857 close(mpeg_file); 1836 demand_irq_enable(true);
1858 mpeg_file = -1; 1837
1838 mpeg_file = creat(recording_filename, O_WRONLY);
1839
1840 if(mpeg_file < 0)
1841 panicf("recfile: %d", mpeg_file);
1859 1842
1843
1844 close(mpeg_file);
1845
1846 mpeg_file = -1;
1847 break;
1848
1849 case MPEG_STOP:
1850 DEBUGF("MPEG_STOP\n");
1851 demand_irq_enable(false);
1852 stop_recording();
1853
1854 /* Save the remaining data in the buffer */
1855 stop_pending = true;
1856 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1857 break;
1858
1859 case MPEG_STOP_DONE:
1860 DEBUGF("MPEG_STOP_DONE\n");
1861
1862 if(mpeg_file >= 0)
1863 close(mpeg_file);
1864 mpeg_file = -1;
1865
1860#ifdef DEBUG1 1866#ifdef DEBUG1
1867 {
1868 int i;
1869 for(i = 0;i < 512;i++)
1861 { 1870 {
1862 int i; 1871 DEBUGF("%d - %d us (%d bytes)\n",
1863 for(i = 0;i < 512;i++) 1872 timing_info[i*2],
1864 { 1873 (timing_info[i*2+1] & 0xffff) *
1865 DEBUGF("%d - %d us (%d bytes)\n", 1874 10000 / 13824,
1866 timing_info[i*2], 1875 timing_info[i*2+1] >> 16);
1867 (timing_info[i*2+1] & 0xffff) *
1868 10000 / 13824,
1869 timing_info[i*2+1] >> 16);
1870 }
1871 } 1876 }
1877 }
1872#endif 1878#endif
1873 mpeg_stop_done = true; 1879 mpeg_stop_done = true;
1874 break; 1880 break;
1875 1881
1876 case MPEG_SAVE_DATA: 1882 case MPEG_SAVE_DATA:
1877 amount_to_save = mp3buf_write - mp3buf_read; 1883 amount_to_save = mp3buf_write - mp3buf_read;
1878 1884
1879 /* If the result is negative, the write index has 1885 /* If the result is negative, the write index has
1880 wrapped */ 1886 wrapped */
1881 if(amount_to_save < 0) 1887 if(amount_to_save < 0)
1882 { 1888 {
1883 amount_to_save += mp3buflen; 1889 amount_to_save += mp3buflen;
1884 } 1890 }
1885 1891
1886 DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write); 1892 DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write);
1887 DEBUGF("ats: %x\n", amount_to_save); 1893 DEBUGF("ats: %x\n", amount_to_save);
1888 /* Save data only if the buffer is getting full, 1894 /* Save data only if the buffer is getting full,
1889 or if we should stop recording */ 1895 or if we should stop recording */
1890 if(amount_to_save) 1896 if(amount_to_save)
1897 {
1898 if(mp3buflen - amount_to_save < MPEG_LOW_WATER ||
1899 stop_pending)
1891 { 1900 {
1892 if(mp3buflen - amount_to_save < MPEG_LOW_WATER || 1901 int rc;
1893 stop_pending) 1902
1894 { 1903 /* Only save up to the end of the buffer */
1895 int rc; 1904 writelen = MIN(amount_to_save,
1896 1905 mp3buflen - mp3buf_read);
1897 /* Only save up to the end of the buffer */ 1906
1898 writelen = MIN(amount_to_save, 1907 DEBUGF("wrl: %x\n", writelen);
1899 mp3buflen - mp3buf_read); 1908 mpeg_file = open(recording_filename,
1900 1909 O_WRONLY| O_APPEND);
1901 DEBUGF("wrl: %x\n", writelen); 1910 if(mpeg_file < 0)
1902 mpeg_file = open(recording_filename, 1911 panicf("rec open: %d", mpeg_file);
1903 O_WRONLY| O_APPEND); 1912
1904 if(mpeg_file < 0) 1913 rc = write(mpeg_file, mp3buf + mp3buf_read,
1905 panicf("rec open: %d", mpeg_file); 1914 writelen);
1906 1915
1907 rc = write(mpeg_file, mp3buf + mp3buf_read, 1916 if(rc < 0)
1908 writelen); 1917 panicf("rec wrt: %d", rc);
1909 1918
1910 if(rc < 0) 1919 rc = close(mpeg_file);
1911 panicf("rec wrt: %d", rc); 1920 if(rc < 0)
1912 1921 panicf("rec cls: %d", rc);
1913 rc = close(mpeg_file); 1922
1914 if(rc < 0) 1923 mpeg_file = -1;
1915 panicf("rec cls: %d", rc); 1924 DEBUGF("rc: %x\n", rc);
1916 1925
1917 mpeg_file = -1; 1926 mp3buf_read += amount_to_save;
1918 DEBUGF("rc: %x\n", rc); 1927 if(mp3buf_read >= mp3buflen)
1919 1928 mp3buf_read = 0;
1920 mp3buf_read += amount_to_save; 1929
1921 if(mp3buf_read >= mp3buflen) 1930 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1922 mp3buf_read = 0;
1923
1924 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1925 }
1926 else
1927 {
1928 saving = false;
1929 }
1930 } 1931 }
1931 else 1932 else
1932 { 1933 {
1933 /* We have saved all data,
1934 time to stop for real */
1935 if(stop_pending)
1936 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1937 saving = false; 1934 saving = false;
1938 } 1935 }
1939 break; 1936 }
1940 1937 else
1941 case MPEG_INIT_PLAYBACK: 1938 {
1942 init_playback(); 1939 /* We have saved all data,
1943 init_playback_done = true; 1940 time to stop for real */
1944 break; 1941 if(stop_pending)
1945 } 1942 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1946 /*}*/ 1943 saving = false;
1944 }
1945 break;
1946
1947 case MPEG_INIT_PLAYBACK:
1948 init_playback();
1949 init_playback_done = true;
1950 break;
1951 }
1947 } 1952 }
1948#endif 1953#endif
1949 } 1954 }
@@ -2981,3 +2986,74 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness,
2981 dbg_cnt2us(0); 2986 dbg_cnt2us(0);
2982#endif 2987#endif
2983} 2988}
2989
2990int d_1;
2991int d_2;
2992
2993int mpeg_create_xing_header(char *filename, void (*progressfunc)(int))
2994{
2995 struct mp3entry entry;
2996 char xingbuf[417];
2997 int fd;
2998 int rc;
2999 int flen;
3000 int num_frames;
3001 int fpos;
3002
3003 if(progressfunc)
3004 progressfunc(0);
3005
3006 rc = mp3info(&entry, filename);
3007 if(rc < 0)
3008 return rc * 10 - 1;
3009
3010 fd = open(filename, O_RDWR);
3011 if(fd < 0)
3012 return fd * 10 - 2;
3013
3014 flen = lseek(fd, 0, SEEK_END);
3015
3016 d_1 = entry.first_frame_offset;
3017 d_2 = entry.filesize;
3018
3019 if(progressfunc)
3020 progressfunc(0);
3021
3022 num_frames = count_mp3_frames(fd, entry.first_frame_offset,
3023 flen,
3024 progressfunc);
3025
3026 create_xing_header(fd, entry.first_frame_offset,
3027 flen, xingbuf, num_frames, progressfunc);
3028
3029 /* Try to fit the Xing header first in the stream. Replace the existing
3030 Xing header if there is one, else see if there is room between the
3031 ID3 tag and the first MP3 frame. */
3032 if(entry.xing_header_pos)
3033 {
3034 /* Reuse existing Xing header */
3035 fpos = entry.xing_header_pos;
3036 }
3037 else
3038 {
3039 /* Any room between ID3 tag and first MP3 frame? */
3040 if(entry.first_frame_offset - entry.id3v2len > 417)
3041 {
3042 fpos = entry.first_frame_offset - 417;
3043 }
3044 else
3045 {
3046 close(fd);
3047 return -3;
3048 }
3049 }
3050
3051 lseek(fd, fpos, SEEK_SET);
3052 write(fd, xingbuf, 417);
3053 close(fd);
3054
3055 if(progressfunc)
3056 progressfunc(100);
3057
3058 return 0;
3059}