summaryrefslogtreecommitdiff
path: root/firmware/mp3data.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/mp3data.c')
-rw-r--r--firmware/mp3data.c133
1 files changed, 71 insertions, 62 deletions
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 415d3bf3d1..1cbf8e54ee 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -530,14 +530,6 @@ int get_mp3file_info(int fd, struct mp3info *info)
530 return bytecount; 530 return bytecount;
531} 531}
532 532
533/* This is an MP3 header, 128kbit/s, with silence
534 MPEG version and sample frequency are not set */
535static const unsigned char xing_frame_header[] = {
536 0xff, 0xe2, 0x90, 0x64, 0x86, 0x1f
537};
538
539static const char cooltext[] = "Rockbox rocks";
540
541static void int2bytes(unsigned char *buf, int val) 533static void int2bytes(unsigned char *buf, int val)
542{ 534{
543 buf[0] = (val >> 24) & 0xff; 535 buf[0] = (val >> 24) & 0xff;
@@ -602,55 +594,30 @@ int count_mp3_frames(int fd, int startpos, int filesize,
602 } 594 }
603} 595}
604 596
605/* Note: mpeg_version and sample_rate are 2-bit values, as specified by the 597static const char cooltext[] = "Rockbox - rocks your box";
606 MPEG frame standard. See the tables above. */ 598
607int create_xing_header(int fd, int startpos, int filesize, 599int create_xing_header(int fd, int startpos, int filesize,
608 unsigned char *buf, int num_frames, 600 unsigned char *buf, int num_frames,
609 int mpeg_version, int sample_rate, 601 unsigned long header_template,
610 void (*progressfunc)(int), bool generate_toc) 602 void (*progressfunc)(int), bool generate_toc)
611{ 603{
612 unsigned long header = 0; 604 unsigned long header = 0;
613 unsigned long saved_header = 0;
614 struct mp3info info; 605 struct mp3info info;
615 int pos, last_pos; 606 int pos, last_pos;
616 int i, j; 607 int i, j;
617 int bytes; 608 int bytes;
618 int filepos; 609 int filepos;
619 int tocentry;
620 int x; 610 int x;
621 int index; 611 int index;
612 unsigned char toc[100];
622 613
623 DEBUGF("create_xing_header()\n"); 614 DEBUGF("create_xing_header()\n");
624 615
625 /* Create the frame header */
626 memset(buf, 0, 1500);
627 memcpy(buf, xing_frame_header, 6);
628
629 lseek(fd, startpos, SEEK_SET);
630 buf_init();
631
632 buf[36] = 'X';
633 buf[36+1] = 'i';
634 buf[36+2] = 'n';
635 buf[36+3] = 'g';
636 int2bytes(&buf[36+4], ((num_frames?VBR_FRAMES_FLAG:0) |
637 (filesize?VBR_BYTES_FLAG:0) |
638 (generate_toc?VBR_TOC_FLAG:0)));
639 index = 36+8;
640 if(num_frames)
641 {
642 int2bytes(&buf[index], num_frames);
643 index += 4;
644 }
645
646 if(filesize)
647 {
648 int2bytes(&buf[index], filesize - startpos);
649 index += 4;
650 }
651
652 if(generate_toc) 616 if(generate_toc)
653 { 617 {
618 lseek(fd, startpos, SEEK_SET);
619 buf_init();
620
654 /* Generate filepos table */ 621 /* Generate filepos table */
655 last_pos = 0; 622 last_pos = 0;
656 filepos = 0; 623 filepos = 0;
@@ -670,48 +637,90 @@ int create_xing_header(int fd, int startpos, int filesize,
670 filepos += info.frame_size; 637 filepos += info.frame_size;
671 } 638 }
672 639
673 /* Save one header for later use */ 640 /* Save a header for later use. Yes, we may be passed a header
641 template in the header_template argument, but since we are
642 reading headers from the stream anyway, we might as well
643 use the ones we find. However, we only save one header, and
644 we want to save one in te middle of the stream, just in case
645 the first and the last headers are corrupt. */
674 if(i == 1) 646 if(i == 1)
675 saved_header = header; 647 header_template = header;
676 648
677 if(progressfunc) 649 if(progressfunc)
678 { 650 {
679 progressfunc(50 + i/2); 651 progressfunc(50 + i/2);
680 } 652 }
681 653
682 tocentry = filepos * 256 / filesize; 654 /* Fill in the TOC entry */
655 toc[i] = filepos * 256 / filesize;
683 656
684 DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n", 657 DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n",
685 i, pos, pos-last_pos, filepos, tocentry); 658 i, pos, pos-last_pos, filepos, toc[i]);
686
687 /* Fill in the TOC entry */
688 buf[index + i] = tocentry;
689 659
690 last_pos = pos; 660 last_pos = pos;
691 } 661 }
662 }
663
664 /* Clear the frame */
665 memset(buf, 0, 1500);
692 666
693 /* Copy the MPEG version and sample rate from the mpeg stream into 667 /* Use the template header and create a new one */
694 the Xing header */ 668 mp3headerinfo(&info, header_template);
695 saved_header &= (VERSION_MASK | SAMPLERATE_MASK); 669
670 /* calculate position of VBR header */
671 if ( info.version == MPEG_VERSION1 ) {
672 if (info.channel_mode == 3) /* mono */
673 index = 21;
674 else
675 index = 36;
676 }
677 else {
678 if (info.channel_mode == 3) /* mono */
679 index = 13;
680 else
681 index = 21;
682 }
683
684 /* We ignore the Protection bit even if the rest of the stream is
685 protected. (fixme?) */
686 header = header_template & ~(BITRATE_MASK | PROTECTION_MASK);
687 header |= 8 << 12; /* This gives us plenty of space, at least 192 bytes */
688
689 /* Write the header to the buffer */
690 int2bytes(buf, header);
696 691
697 buf[1] |= (saved_header >> 16) & 0xff; 692 /* Now get the length of the newly created frame */
698 buf[2] |= (saved_header >> 8) & 0xff; 693 mp3headerinfo(&info, header);
694
695 /* Create the Xing data */
696 buf[index] = 'X';
697 buf[index+1] = 'i';
698 buf[index+2] = 'n';
699 buf[index+3] = 'g';
700 int2bytes(&buf[index+4], ((num_frames?VBR_FRAMES_FLAG:0) |
701 (filesize?VBR_BYTES_FLAG:0) |
702 (generate_toc?VBR_TOC_FLAG:0)));
703 index = index+8;
704 if(num_frames)
705 {
706 int2bytes(&buf[index], num_frames);
707 index += 4;
699 } 708 }
700 else 709
710 if(filesize)
701 { 711 {
702 /* Fill in the MPEG version and sample rate into the Xing header */ 712 int2bytes(&buf[index], filesize - startpos);
703 buf[1] |= mpeg_version << 3; 713 index += 4;
704 buf[2] |= sample_rate << 2;
705 } 714 }
706 715
716 /* Copy the TOC */
717 memcpy(buf + index, toc, 100);
718
719 /* And some extra cool info */
707 memcpy(buf + index + 100, cooltext, sizeof(cooltext)); 720 memcpy(buf + index + 100, cooltext, sizeof(cooltext));
708 721
709 /* Now get the length of the newly created frame */
710 header = BYTES2INT(buf[0], buf[1], buf[2], buf[3]);
711 mp3headerinfo(&info, header);
712
713#ifdef DEBUG 722#ifdef DEBUG
714 for(i = 0;i < 417;i++) 723 for(i = 0;i < info.framesize;i++)
715 { 724 {
716 if(i && !(i % 16)) 725 if(i && !(i % 16))
717 DEBUGF("\n"); 726 DEBUGF("\n");