diff options
Diffstat (limited to 'firmware/mp3data.c')
-rw-r--r-- | firmware/mp3data.c | 133 |
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 */ | ||
535 | static const unsigned char xing_frame_header[] = { | ||
536 | 0xff, 0xe2, 0x90, 0x64, 0x86, 0x1f | ||
537 | }; | ||
538 | |||
539 | static const char cooltext[] = "Rockbox rocks"; | ||
540 | |||
541 | static void int2bytes(unsigned char *buf, int val) | 533 | static 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 | 597 | static const char cooltext[] = "Rockbox - rocks your box"; |
606 | MPEG frame standard. See the tables above. */ | 598 | |
607 | int create_xing_header(int fd, int startpos, int filesize, | 599 | int 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"); |