remove display-leftovers and remove the memory size question for iRiver
[kugel-rb.git] / firmware / mp3data.c
blob7c8c75833b3e88cd2263bc1174bd9371a9eac73d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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
22 * by David Härdeman. It has since been extended and enhanced pretty much by
23 * all sorts of friendly Rockbox people.
25 * A nice reference for MPEG header info:
26 * http://rockbox.haxx.se/docs/mpeghdr.html
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 #include "buffer.h"
39 #define DEBUG_VERBOSE
41 #define BYTES2INT(b1,b2,b3,b4) (((b1 & 0xFF) << (3*8)) | \
42 ((b2 & 0xFF) << (2*8)) | \
43 ((b3 & 0xFF) << (1*8)) | \
44 ((b4 & 0xFF) << (0*8)))
46 #define SYNC_MASK (0x7ff << 21)
47 #define VERSION_MASK (3 << 19)
48 #define LAYER_MASK (3 << 17)
49 #define PROTECTION_MASK (1 << 16)
50 #define BITRATE_MASK (0xf << 12)
51 #define SAMPLERATE_MASK (3 << 10)
52 #define PADDING_MASK (1 << 9)
53 #define PRIVATE_MASK (1 << 8)
54 #define CHANNELMODE_MASK (3 << 6)
55 #define MODE_EXT_MASK (3 << 4)
56 #define COPYRIGHT_MASK (1 << 3)
57 #define ORIGINAL_MASK (1 << 2)
58 #define EMPHASIS_MASK 3
60 /* Table of bitrates for MP3 files, all values in kilo.
61 * Indexed by version, layer and value of bit 15-12 in header.
63 const int bitrate_table[2][3][16] =
66 {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
67 {0,32,48,56, 64,80, 96, 112,128,160,192,224,256,320,384,0},
68 {0,32,40,48, 56,64, 80, 96, 112,128,160,192,224,256,320,0}
71 {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
72 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0},
73 {0, 8,16,24,32,40,48, 56, 64, 80, 96,112,128,144,160,0}
77 /* Table of samples per frame for MP3 files.
78 * Indexed by layer. Multiplied with 1000.
80 const int bs[3] = {384000, 1152000, 1152000};
82 /* Table of sample frequency for MP3 files.
83 * Indexed by version and layer.
86 const int freqtab[][4] =
88 {11025, 12000, 8000, 0}, /* MPEG version 2.5 */
89 {44100, 48000, 32000, 0}, /* MPEG Version 1 */
90 {22050, 24000, 16000, 0}, /* MPEG version 2 */
93 /* check if 'head' is a valid mp3 frame header */
94 static bool is_mp3frameheader(unsigned long head)
96 if ((head & SYNC_MASK) != (unsigned long)SYNC_MASK) /* bad sync? */
97 return false;
98 if ((head & VERSION_MASK) == (1 << 19)) /* bad version? */
99 return false;
100 if (!(head & LAYER_MASK)) /* no layer? */
101 return false;
102 if ((head & BITRATE_MASK) == BITRATE_MASK) /* bad bitrate? */
103 return false;
104 if (!(head & BITRATE_MASK)) /* no bitrate? */
105 return false;
106 if ((head & SAMPLERATE_MASK) == SAMPLERATE_MASK) /* bad sample rate? */
107 return false;
108 if (((head >> 19) & 1) == 1 &&
109 ((head >> 17) & 3) == 3 &&
110 ((head >> 16) & 1) == 1)
111 return false;
112 if ((head & 0xffff0000) == 0xfffe0000)
113 return false;
115 return true;
118 static bool mp3headerinfo(struct mp3info *info, unsigned long header)
120 int bittable = 0;
121 int bitindex;
122 int freqindex;
124 /* MPEG Audio Version */
125 switch(header & VERSION_MASK) {
126 case 0:
127 /* MPEG version 2.5 is not an official standard */
128 info->version = MPEG_VERSION2_5;
129 bittable = MPEG_VERSION2 - 1; /* use the V2 bit rate table */
130 break;
132 case (1 << 19):
133 return false;
135 case (2 << 19):
136 /* MPEG version 2 (ISO/IEC 13818-3) */
137 info->version = MPEG_VERSION2;
138 bittable = MPEG_VERSION2 - 1;
139 break;
141 case (3 << 19):
142 /* MPEG version 1 (ISO/IEC 11172-3) */
143 info->version = MPEG_VERSION1;
144 bittable = MPEG_VERSION1 - 1;
145 break;
148 switch(header & LAYER_MASK) {
149 case 0:
150 return false;
151 case (1 << 17):
152 info->layer = 2;
153 break;
154 case (2 << 17):
155 info->layer = 1;
156 break;
157 case (3 << 17):
158 info->layer = 0;
159 break;
162 info->protection = (header & PROTECTION_MASK)?true:false;
164 /* Bitrate */
165 bitindex = (header & 0xf000) >> 12;
166 info->bitrate = bitrate_table[bittable][info->layer][bitindex];
167 if(info->bitrate == 0)
168 return false;
170 /* Sampling frequency */
171 freqindex = (header & 0x0C00) >> 10;
172 info->frequency = freqtab[info->version][freqindex];
173 if(info->frequency == 0)
174 return false;
176 info->padding = (header & 0x0200)?1:0;
178 /* Calculate number of bytes, calculation depends on layer */
179 switch(info->layer) {
180 case 0:
181 info->frame_size = info->bitrate * 48000;
182 info->frame_size /=
183 freqtab[info->version][freqindex] << bittable;
184 break;
185 case 1:
186 case 2:
187 info->frame_size = info->bitrate * 144000;
188 info->frame_size /=
189 freqtab[info->version][freqindex] << bittable;
190 break;
191 default:
192 info->frame_size = 1;
195 info->frame_size += info->padding;
197 /* Calculate time per frame */
198 info->frame_time = bs[info->layer] /
199 (freqtab[info->version][freqindex] << bittable);
201 info->channel_mode = (header & 0xc0) >> 6;
202 info->mode_extension = (header & 0x30) >> 4;
203 info->emphasis = header & 3;
205 #ifdef DEBUG_VERBOSE
206 DEBUGF( "Header: %08x, Ver %d, lay %d, bitr %d, freq %d, "
207 "chmode %d, mode_ext %d, emph %d, bytes: %d time: %d\n",
208 header, info->version, info->layer, info->bitrate, info->frequency,
209 info->channel_mode, info->mode_extension,
210 info->emphasis, info->frame_size, info->frame_time);
211 #endif
212 return true;
215 static unsigned long __find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header, int(*getfunc)(int fd, unsigned char *c))
217 unsigned long header=0;
218 unsigned char tmp;
219 int i;
221 int pos = 0;
223 /* We remember the last header we found, to use as a template to see if
224 the header we find has the same frequency, layer etc */
225 last_header &= 0xffff0c00;
227 /* Fill up header with first 24 bits */
228 for(i = 0; i < 3; i++) {
229 header <<= 8;
230 if(!getfunc(fd, &tmp))
231 return 0;
232 header |= tmp;
233 pos++;
236 do {
237 header <<= 8;
238 if(!getfunc(fd, &tmp))
239 return 0;
240 header |= tmp;
241 pos++;
242 if(max_offset > 0 && pos > max_offset)
243 return 0;
244 } while(!is_mp3frameheader(header) ||
245 (last_header?((header & 0xffff0c00) != last_header):false));
247 *offset = pos - 4;
249 #if defined(DEBUG) || defined(SIMULATOR)
250 if(*offset)
251 DEBUGF("Warning: skipping %d bytes of garbage\n", *offset);
252 #endif
254 return header;
257 static int fileread(int fd, unsigned char *c)
259 return read(fd, c, 1);
262 unsigned long find_next_frame(int fd, int *offset, int max_offset, unsigned long last_header)
264 return __find_next_frame(fd, offset, max_offset, last_header, fileread);
267 static int fnf_read_index;
268 static int fnf_buf_len;
270 static int buf_getbyte(int fd, unsigned char *c)
272 if(fnf_read_index < fnf_buf_len)
274 *c = mp3buf[fnf_read_index++];
275 return 1;
277 else
279 fnf_buf_len = read(fd, mp3buf, mp3end - mp3buf);
280 if(fnf_buf_len < 0)
281 return -1;
283 fnf_read_index = 0;
285 if(fnf_buf_len > 0)
287 *c = mp3buf[fnf_read_index++];
288 return 1;
290 else
291 return 0;
293 return 0;
296 static int buf_seek(int fd, int len)
298 fnf_read_index += len;
299 if(fnf_read_index > fnf_buf_len)
301 len = fnf_read_index - fnf_buf_len;
303 fnf_buf_len = read(fd, mp3buf, mp3end - mp3buf);
304 if(fnf_buf_len < 0)
305 return -1;
307 fnf_read_index = 0;
308 fnf_read_index += len;
311 if(fnf_read_index > fnf_buf_len)
313 return -1;
315 else
316 return 0;
319 static void buf_init(void)
321 fnf_buf_len = 0;
322 fnf_read_index = 0;
325 unsigned long buf_find_next_frame(int fd, int *offset, int max_offset,
326 unsigned long last_header)
328 return __find_next_frame(fd, offset, max_offset, last_header, buf_getbyte);
331 static int mp3buflen;
332 static int mem_pos;
333 static int mem_cnt;
334 static int mem_maxlen;
336 static int mem_getbyte(int dummy, unsigned char *c)
338 dummy = dummy;
340 *c = mp3buf[mem_pos++];
341 if(mem_pos >= mp3buflen)
342 mem_pos = 0;
344 if(mem_cnt++ >= mem_maxlen)
345 return 0;
346 else
347 return 1;
350 unsigned long mem_find_next_frame(int startpos, int *offset, int max_offset,
351 unsigned long last_header)
353 mp3buflen = mp3end - mp3buf;
354 mem_pos = startpos;
355 mem_cnt = 0;
356 mem_maxlen = max_offset;
358 return __find_next_frame(0, offset, max_offset, last_header, mem_getbyte);
361 int get_mp3file_info(int fd, struct mp3info *info)
363 unsigned char frame[1800];
364 unsigned char *vbrheader;
365 unsigned long header;
366 int bytecount;
367 int num_offsets;
368 int frames_per_entry;
369 int i;
370 int offset;
371 int j;
372 int tmp;
374 header = find_next_frame(fd, &bytecount, 0x20000, 0);
375 /* Quit if we haven't found a valid header within 128K */
376 if(header == 0)
377 return -1;
379 memset(info, 0, sizeof(struct mp3info));
380 if(!mp3headerinfo(info, header))
381 return -2;
383 /* OK, we have found a frame. Let's see if it has a Xing header */
384 if(read(fd, frame, info->frame_size-4) < 0)
385 return -3;
387 /* calculate position of VBR header */
388 if ( info->version == MPEG_VERSION1 ) {
389 if (info->channel_mode == 3) /* mono */
390 vbrheader = frame + 17;
391 else
392 vbrheader = frame + 32;
394 else {
395 if (info->channel_mode == 3) /* mono */
396 vbrheader = frame + 9;
397 else
398 vbrheader = frame + 17;
401 if (!memcmp(vbrheader, "Xing", 4))
403 int i = 8; /* Where to start parsing info */
405 DEBUGF("Xing header\n");
407 /* Remember where in the file the Xing header is */
408 info->vbr_header_pos = lseek(fd, 0, SEEK_CUR) - info->frame_size;
410 /* We want to skip the Xing frame when playing the stream */
411 bytecount += info->frame_size;
413 /* Now get the next frame to find out the real info about
414 the mp3 stream */
415 header = find_next_frame(fd, &tmp, 0x20000, 0);
416 if(header == 0)
417 return -4;
419 if(!mp3headerinfo(info, header))
420 return -5;
422 /* Yes, it is a VBR file */
423 info->is_vbr = true;
424 info->is_xing_vbr = true;
426 if(vbrheader[7] & VBR_FRAMES_FLAG) /* Is the frame count there? */
428 info->frame_count = BYTES2INT(vbrheader[i], vbrheader[i+1],
429 vbrheader[i+2], vbrheader[i+3]);
430 info->file_time = info->frame_count * info->frame_time;
431 i += 4;
434 if(vbrheader[7] & VBR_BYTES_FLAG) /* Is byte count there? */
436 info->byte_count = BYTES2INT(vbrheader[i], vbrheader[i+1],
437 vbrheader[i+2], vbrheader[i+3]);
438 i += 4;
441 if(info->file_time && info->byte_count)
442 info->bitrate = info->byte_count * 8 / info->file_time;
443 else
444 info->bitrate = 0;
446 if(vbrheader[7] & VBR_TOC_FLAG) /* Is table-of-contents there? */
448 memcpy( info->toc, vbrheader+i, 100 );
452 if (!memcmp(vbrheader, "VBRI", 4))
454 DEBUGF("VBRI header\n");
456 /* We want to skip the VBRI frame when playing the stream */
457 bytecount += info->frame_size;
459 /* Now get the next frame to find out the real info about
460 the mp3 stream */
461 header = find_next_frame(fd, &tmp, 0x20000, 0);
462 if(header == 0)
463 return -6;
465 bytecount += tmp;
467 if(!mp3headerinfo(info, header))
468 return -7;
470 DEBUGF("%04x: %04x %04x ", 0, header >> 16, header & 0xffff);
471 for(i = 4;i < (int)sizeof(frame)-4;i+=2) {
472 if(i % 16 == 0) {
473 DEBUGF("\n%04x: ", i-4);
475 DEBUGF("%04x ", (frame[i-4] << 8) | frame[i-4+1]);
478 DEBUGF("\n");
480 /* Yes, it is a FhG VBR file */
481 info->is_vbr = true;
482 info->is_vbri_vbr = true;
483 info->has_toc = false; /* We don't parse the TOC (yet) */
485 info->byte_count = BYTES2INT(vbrheader[10], vbrheader[11],
486 vbrheader[12], vbrheader[13]);
487 info->frame_count = BYTES2INT(vbrheader[14], vbrheader[15],
488 vbrheader[16], vbrheader[17]);
490 info->file_time = info->frame_count * info->frame_time;
491 info->bitrate = info->byte_count * 8 / info->file_time;
493 /* We don't parse the TOC, since we don't yet know how to (FIXME) */
494 num_offsets = BYTES2INT(0, 0, vbrheader[18], vbrheader[19]);
495 frames_per_entry = BYTES2INT(0, 0, vbrheader[24], vbrheader[25]);
496 DEBUGF("Frame size (%dkpbs): %d bytes (0x%x)\n",
497 info->bitrate, info->frame_size, info->frame_size);
498 DEBUGF("Frame count: %x\n", info->frame_count);
499 DEBUGF("Byte count: %x\n", info->byte_count);
500 DEBUGF("Offsets: %d\n", num_offsets);
501 DEBUGF("Frames/entry: %d\n", frames_per_entry);
503 offset = 0;
505 for(i = 0;i < num_offsets;i++)
507 j = BYTES2INT(0, 0, vbrheader[26+i*2], vbrheader[27+i*2]);
508 offset += j;
509 DEBUGF("%03d: %x (%x)\n", i, offset - bytecount, j);
513 /* Is it a LAME Info frame? */
514 if (!memcmp(vbrheader, "Info", 4))
516 /* Make sure we skip this frame in playback */
517 bytecount += info->frame_size;
520 return bytecount;
523 static void int2bytes(unsigned char *buf, int val)
525 buf[0] = (val >> 24) & 0xff;
526 buf[1] = (val >> 16) & 0xff;
527 buf[2] = (val >> 8) & 0xff;
528 buf[3] = val & 0xff;
531 int count_mp3_frames(int fd, int startpos, int filesize,
532 void (*progressfunc)(int))
534 unsigned long header = 0;
535 struct mp3info info;
536 int num_frames;
537 int bytes;
538 int cnt;
539 int progress_chunk = filesize / 50; /* Max is 50%, in 1% increments */
540 int progress_cnt = 0;
541 bool is_vbr = false;
542 int last_bitrate = 0;
543 int header_template = 0;
545 if(lseek(fd, startpos, SEEK_SET) < 0)
546 return -1;
548 buf_init();
550 /* Find out the total number of frames */
551 num_frames = 0;
552 cnt = 0;
554 while((header = buf_find_next_frame(fd, &bytes, -1, header_template))) {
555 mp3headerinfo(&info, header);
557 if(!header_template)
558 header_template = header;
560 /* See if this really is a VBR file */
561 if(last_bitrate && info.bitrate != last_bitrate)
563 is_vbr = true;
565 last_bitrate = info.bitrate;
567 buf_seek(fd, info.frame_size-4);
568 num_frames++;
569 if(progressfunc)
571 cnt += bytes + info.frame_size;
572 if(cnt > progress_chunk)
574 progress_cnt++;
575 progressfunc(progress_cnt);
576 cnt = 0;
580 DEBUGF("Total number of frames: %d\n", num_frames);
582 if(is_vbr)
583 return num_frames;
584 else
586 DEBUGF("Not a VBR file\n");
587 return 0;
591 static const char cooltext[] = "Rockbox - rocks your box";
593 int create_xing_header(int fd, int startpos, int filesize,
594 unsigned char *buf, int num_frames,
595 unsigned long header_template,
596 void (*progressfunc)(int), bool generate_toc)
598 unsigned long header = 0;
599 struct mp3info info;
600 int pos, last_pos;
601 int i, j;
602 int bytes;
603 unsigned int filepos;
604 int x;
605 int index;
606 unsigned char toc[100];
607 unsigned long xing_header_template = 0;
609 DEBUGF("create_xing_header()\n");
611 if(header_template)
612 xing_header_template = header_template;
614 if(generate_toc)
616 lseek(fd, startpos, SEEK_SET);
617 buf_init();
619 /* Generate filepos table */
620 last_pos = 0;
621 filepos = 0;
622 header = 0;
623 x = 0;
624 for(i = 0;i < 100;i++) {
625 /* Calculate the absolute frame number for this seek point */
626 pos = i * num_frames / 100;
628 /* Advance from the last seek point to this one */
629 for(j = 0;j < pos - last_pos;j++)
631 header = buf_find_next_frame(fd, &bytes, -1, header_template);
632 filepos += bytes;
633 mp3headerinfo(&info, header);
634 buf_seek(fd, info.frame_size-4);
635 filepos += info.frame_size;
637 if(!header_template)
638 header_template = header;
641 /* Save a header for later use if header_template is empty.
642 We only save one header, and we want to save one in the
643 middle of the stream, just in case the first and the last
644 headers are corrupt. */
645 if(!xing_header_template && i == 1)
646 xing_header_template = header;
648 if(progressfunc)
650 progressfunc(50 + i/2);
653 /* Fill in the TOC entry */
654 /* each toc is a single byte indicating how many 256ths of the
655 * way through the file, is that percent of the way through the
656 * song. the easy method, filepos*256/filesize, chokes when
657 * the upper 8 bits of the file position are nonzero
658 * (i.e. files over 16mb in size).
660 if (filepos > 0xFFFFFF)
662 /* instead of multiplying filepos by 256, we divide
663 * filesize by 256.
665 toc[i] = filepos / (filesize >> 8);
667 else
669 toc[i] = filepos * 256 / filesize;
672 DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n",
673 i, pos, pos-last_pos, filepos, toc[i]);
675 last_pos = pos;
679 /* Clear the frame */
680 memset(buf, 0, 1500);
682 /* Use the template header and create a new one */
683 mp3headerinfo(&info, xing_header_template);
685 /* calculate position of VBR header */
686 if ( info.version == MPEG_VERSION1 ) {
687 if (info.channel_mode == 3) /* mono */
688 index = 21;
689 else
690 index = 36;
692 else {
693 if (info.channel_mode == 3) /* mono */
694 index = 13;
695 else
696 index = 21;
699 /* We ignore the Protection bit even if the rest of the stream is
700 protected. (fixme?) */
701 header = xing_header_template & ~(BITRATE_MASK | PROTECTION_MASK);
702 header |= 8 << 12; /* This gives us plenty of space, at least 192 bytes */
704 /* Write the header to the buffer */
705 int2bytes(buf, header);
707 /* Now get the length of the newly created frame */
708 mp3headerinfo(&info, header);
710 /* Create the Xing data */
711 buf[index] = 'X';
712 buf[index+1] = 'i';
713 buf[index+2] = 'n';
714 buf[index+3] = 'g';
715 int2bytes(&buf[index+4], ((num_frames?VBR_FRAMES_FLAG:0) |
716 (filesize?VBR_BYTES_FLAG:0) |
717 (generate_toc?VBR_TOC_FLAG:0)));
718 index = index+8;
719 if(num_frames)
721 int2bytes(&buf[index], num_frames);
722 index += 4;
725 if(filesize)
727 int2bytes(&buf[index], filesize - startpos);
728 index += 4;
731 /* Copy the TOC */
732 memcpy(buf + index, toc, 100);
734 /* And some extra cool info */
735 memcpy(buf + index + 100, cooltext, sizeof(cooltext));
737 #ifdef DEBUG
738 for(i = 0;i < info.frame_size;i++)
740 if(i && !(i % 16))
741 DEBUGF("\n");
743 DEBUGF("%02x ", buf[i]);
745 #endif
747 return info.frame_size;