1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by Daniel Stenberg
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 * Parts of this code has been stolen from the Ample project and was written
36 /* Some utility macros used in getsonglength() */
37 #define BYTE0(x) ((x >> 24) & 0xFF)
38 #define BYTE1(x) ((x >> 16) & 0xFF)
39 #define BYTE2(x) ((x >> 8) & 0xFF)
40 #define BYTE3(x) ((x >> 0) & 0xFF)
42 #define UNSYNC(b1,b2,b3,b4) (((b1 & 0x7F) << (3*7)) | \
43 ((b2 & 0x7F) << (2*7)) | \
44 ((b3 & 0x7F) << (1*7)) | \
45 ((b4 & 0x7F) << (0*7)))
47 #define HASID3V2(entry) entry->id3v2len > 0
48 #define HASID3V1(entry) entry->id3v1len > 0
50 /* Table of bitrates for MP3 files, all values in kilo.
51 * Indexed by version, layer and value of bit 15-12 in header.
53 const int bitrate_table
[2][3][16] =
56 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
57 {0,32,48,56, 64,80, 96, 112,128,160,192,224,256,320,384,0},
58 {0,32,40,48, 56,64, 80, 96, 112,128,160,192,224,256,320,0}
61 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
62 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0},
63 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0}
67 /* Table of samples per frame for MP3 files.
68 * Indexed by layer. Multiplied with 1000.
70 const int bs
[4] = {0, 384000, 1152000, 1152000};
72 /* Table of sample frequency for MP3 files.
73 * Indexed by version and layer.
75 const int freqtab
[2][4] =
77 {44100, 48000, 32000, 0},
78 {22050, 24000, 16000, 0},
82 * Removes trailing spaces from a string.
84 * Arguments: buffer - the string to process
89 stripspaces(char *buffer
)
92 while(*(buffer
+ i
) != '\0')
96 if(*(buffer
+ i
) == ' ')
98 else if(*(buffer
+ i
) == '\0')
106 * Sets the title of an MP3 entry based on its ID3v1 tag.
108 * Arguments: file - the MP3 file to scen for a ID3v1 tag
109 * entry - the entry to set the title in
111 * Returns: true if a title was found and created, else false
113 static bool setid3v1title(int fd
, struct mp3entry
*entry
)
116 int offsets
[3] = {-95,-65,-125};
120 if(-1 == lseek(fd
, offsets
[i
], SEEK_END
))
124 read(fd
, buffer
, 30);
130 strcpy(entry
->id3v1buf
[0], buffer
);
131 entry
->artist
= entry
->id3v1buf
[0];
134 strcpy(entry
->id3v1buf
[1], buffer
);
135 entry
->album
= entry
->id3v1buf
[1];
138 strcpy(entry
->id3v1buf
[2], buffer
);
139 entry
->title
= entry
->id3v1buf
[2];
150 * Sets the title of an MP3 entry based on its ID3v2 tag.
152 * Arguments: file - the MP3 file to scen for a ID3v2 tag
153 * entry - the entry to set the title in
155 * Returns: true if a title was found and created, else false
157 static void setid3v2title(int fd
, struct mp3entry
*entry
)
159 unsigned int minframesize
;
161 unsigned int readsize
= 0, headerlen
;
165 char *tracknum
= NULL
;
167 unsigned short int version
;
168 int titlen
=0, artistn
=0, albumn
=0, tracknumn
=0;
169 char *buffer
= entry
->id3v2buf
;
171 /* 10 = headerlength */
172 if(entry
->id3v2len
< 10)
176 lseek(fd
, 0, SEEK_SET
);
177 if(10 != read(fd
, header
, 10))
180 version
= (unsigned short int)header
[3];
182 /* Read all frames in the tag */
183 size
= entry
->id3v2len
- 10;
185 if(size
>= (int)sizeof(entry
->id3v2buf
))
186 size
= sizeof(entry
->id3v2buf
)-1;
188 if(size
!= read(fd
, buffer
, size
))
191 *(buffer
+ size
) = '\0';
193 /* Set minimun frame size according to ID3v2 version */
200 * We must have at least minframesize bytes left for the
201 * remaining frames to be interesting
203 while(size
- readsize
> minframesize
) {
205 /* Read frame header and check length */
207 memcpy(header
, (buffer
+ readsize
), 10);
209 headerlen
= UNSYNC(header
[4], header
[5],
210 header
[6], header
[7]);
212 memcpy(header
, (buffer
+ readsize
), 6);
214 headerlen
= (header
[3] << 16) +
221 /* Check for certain frame headers */
222 if(!strncmp(header
, "TPE1", strlen("TPE1")) ||
223 !strncmp(header
, "TP1", strlen("TP1"))) {
226 if(headerlen
> (size
- readsize
))
227 headerlen
= (size
- readsize
);
228 artist
= buffer
+ readsize
;
230 readsize
+= headerlen
;
232 else if(!strncmp(header
, "TIT2", strlen("TIT2")) ||
233 !strncmp(header
, "TT2", strlen("TT2"))) {
236 if(headerlen
> (size
- readsize
))
237 headerlen
= (size
- readsize
);
238 title
= buffer
+ readsize
;
240 readsize
+= headerlen
;
242 else if(!strncmp(header
, "TALB", strlen("TALB"))) {
245 if(headerlen
> (size
- readsize
))
246 headerlen
= (size
- readsize
);
247 album
= buffer
+ readsize
;
249 readsize
+= headerlen
;
251 else if(!strncmp(header
, "TRCK", strlen("TRCK"))) {
254 if(headerlen
> (size
- readsize
))
255 headerlen
= (size
- readsize
);
256 tracknum
= buffer
+ readsize
;
257 tracknumn
= headerlen
;
258 readsize
+= headerlen
;
260 readsize
+= headerlen
;
265 entry
->artist
= artist
;
270 entry
->title
= title
;
275 entry
->album
= album
;
280 tracknum
[tracknumn
] = 0;
281 entry
->tracknum
= atoi(tracknum
);
286 * Calculates the size of the ID3v2 tag.
288 * Arguments: file - the file to search for a tag.
290 * Returns: the size of the tag or 0 if none was found
292 static int getid3v2len(int fd
)
297 /* Make sure file has a ID3 tag */
298 if((-1 == lseek(fd
, 0, SEEK_SET
)) ||
299 (read(fd
, buf
, 6) != 6) ||
300 (strncmp(buf
, "ID3", strlen("ID3")) != 0))
303 /* Now check what the ID3v2 size field says */
304 else if(read(fd
, buf
, 4) != 4)
307 offset
= UNSYNC(buf
[0], buf
[1], buf
[2], buf
[3]) + 10;
312 static int getfilesize(int fd
)
316 /* seek to the end of it */
317 size
= lseek(fd
, 0, SEEK_END
);
319 return 0; /* unknown */
325 * Calculates the size of the ID3v1 tag.
327 * Arguments: file - the file to search for a tag.
329 * Returns: the size of the tag or 0 if none was found
331 static int getid3v1len(int fd
)
336 /* Check if we find "TAG" 128 bytes from EOF */
337 if((lseek(fd
, -128, SEEK_END
) == -1) ||
338 (read(fd
, buf
, 3) != 3) ||
339 (strncmp(buf
, "TAG", 3) != 0))
347 /* check if 'head' is a valid mp3 frame header */
348 static bool mp3frameheader(unsigned long head
)
350 if ((head
& 0xffe00000) != 0xffe00000) /* bad sync? */
352 if (!((head
>> 17) & 3)) /* no layer? */
354 if (((head
>> 12) & 0xf) == 0xf) /* bad bitrate? */
356 if (!((head
>> 12) & 0xf)) /* no bitrate? */
358 if (((head
>> 10) & 0x3) == 0x3) /* bad sample rate? */
360 if (((head
>> 19) & 1) == 1 &&
361 ((head
>> 17) & 3) == 3 &&
362 ((head
>> 16) & 1) == 1)
364 if ((head
& 0xffff0000) == 0xfffe0000)
371 * Calculates the length (in milliseconds) of an MP3 file. Currently this code
372 * doesn't care about VBR (Variable BitRate) files since it would have to scan
373 * through the entire file but this should become a config option in the
376 * Modified to only use integers.
378 * Arguments: file - the file to calculate the length upon
379 * entry - the entry to update with the length
381 * Returns: the song length in milliseconds,
382 * -1 means that it couldn't be calculated
384 static int getsonglength(int fd
, struct mp3entry
*entry
)
386 unsigned int filetime
= 0;
387 unsigned long header
=0;
389 unsigned char frame
[64];
404 /* Start searching after ID3v2 header */
405 if(-1 == lseek(fd
, entry
->id3v2len
, SEEK_SET
))
408 /* Fill up header with first 24 bits */
409 for(version
= 0; version
< 3; version
++) {
411 if(!read(fd
, &tmp
, 1))
416 /* Loop trough file until we find a frame header */
421 if(!read(fd
, &tmp
, 1))
425 /* Quit if we haven't found a valid header within 128K */
427 if(bytecount
> 0x20000)
429 } while(!mp3frameheader(header
));
432 * Some files are filled with garbage in the beginning,
433 * if the bitrate index of the header is binary 1111
434 * that is a good indicator
436 if((header
& 0xF000) == 0xF000)
441 "We found %x-%x-%x-%x and checksync %i and test %x\n",
442 BYTE0(header
), BYTE1(header
), BYTE2(header
), BYTE3(header
),
443 CHECKSYNC(header
), (header
& 0xF000) == 0xF000);
445 /* MPEG Audio Version */
446 switch((header
& 0x180000) >> 19) {
458 switch((header
& 0x060000) >> 17) {
473 bitindex
= (header
& 0xF000) >> 12;
474 bitrate
= bitrate_table
[version
-1][layer
-1][bitindex
];
478 /* Sampling frequency */
479 freqindex
= (header
& 0x0C00) >> 10;
480 frequency
= freqtab
[version
-1][freqindex
];
485 DEBUGF( "Version %i, lay %i, biti %i, bitr %i, freqi %i, freq %i, chmode %d\n",
486 version
, layer
, bitindex
, bitrate
, freqindex
, frequency
, chmode
);
488 entry
->version
= version
;
489 entry
->layer
= layer
;
490 entry
->frequency
= frequency
;
492 /* Calculate bytes per frame, calculation depends on layer */
495 bpf
= bitrate_table
[version
- 1][layer
- 1][bitindex
];
497 bpf
/= freqtab
[version
-1][freqindex
] << (version
- 1);
501 bpf
= bitrate_table
[version
- 1][layer
- 1][bitindex
];
503 bpf
/= freqtab
[version
-1][freqindex
] << (version
- 1);
509 /* Calculate time per frame */
510 tpf
= bs
[layer
] / (freqtab
[version
-1][freqindex
] << (version
- 1));
512 /* OK, we have found a frame. Let's see if it has a Xing header */
513 if(read(fd
, frame
, sizeof frame
) < 0)
516 /* Channel mode (stereo/mono) */
517 chmode
= (header
& 0xc0) >> 6;
519 /* calculate position of Xing VBR header */
520 if ( version
== 1 ) {
521 if ( chmode
== 3 ) /* mono */
527 if ( chmode
== 3 ) /* mono */
533 if (xing
[0] == 'X' &&
538 /* Yes, it is a VBR file */
541 if (xing
[7] & 0x01) /* Is the frame count there? */
543 int framecount
= (xing
[8] << 24) | (xing
[9] << 16) |
544 (xing
[10] << 8) | xing
[11];
546 filetime
= framecount
* tpf
;
548 if (xing
[7] & 0x02) /* is byte count there? */
550 int bytecount
= (xing
[12] << 24) | (xing
[13] << 16) |
551 (xing
[14] << 8) | xing
[15];
553 bitrate
= bytecount
* 8 / filetime
;
555 /* We don't care about the TOC just yet. Maybe another time. */
558 entry
->bitrate
= bitrate
;
560 /* If the file time hasn't been established, this may be a fixed
561 rate MP3, so just use the default formula */
566 * ((filesize)/(bytes per frame))*(time per frame)
568 filetime
= entry
->filesize
/bpf
*tpf
;
576 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc)
577 * about an MP3 file and updates it's entry accordingly.
579 * Arguments: entry - the entry to check and update with the new information
583 bool mp3info(struct mp3entry
*entry
, char *filename
)
586 fd
= open(filename
, O_RDONLY
);
590 memset(entry
, 0, sizeof(struct mp3entry
));
592 strncpy(entry
->path
, filename
, sizeof(entry
->path
));
595 entry
->filesize
= getfilesize(fd
);
596 entry
->id3v2len
= getid3v2len(fd
);
599 /* Ignore the tag if it is too big */
600 if(entry
->id3v2len
> sizeof(entry
->id3v2buf
))
604 setid3v2title(fd
, entry
);
605 entry
->length
= getsonglength(fd
, entry
);
607 entry
->id3v1len
= getid3v1len(fd
);
608 if(HASID3V1(entry
) && !entry
->title
)
609 setid3v1title(fd
, entry
);
616 #ifdef DEBUG_STANDALONE
618 char *secs2str(int ms
)
620 static char buffer
[32];
623 snprintf(buffer
, sizeof(buffer
), "%d:%02d.%d", secs
/60, secs
%60, ms
/100);
627 int main(int argc
, char **argv
)
630 for(i
=1; i
<argc
; i
++) {
632 if(mp3info(&mp3
, argv
[i
])) {
633 printf("Failed to get %s\n", argv
[i
]);
637 printf("****** File: %s\n"
641 " Length: %s / %d s\n"
645 mp3
.title
?mp3
.title
:"<blank>",
646 mp3
.artist
?mp3
.artist
:"<blank>",
647 mp3
.album
?mp3
.album
:"<blank>",
648 secs2str(mp3
.length
),
659 /* -----------------------------------------------------------------
661 * eval: (load-file "rockbox-mode.el")