diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/export/mp3data.h | 1 | ||||
-rw-r--r-- | firmware/mp3data.c | 41 | ||||
-rw-r--r-- | firmware/mpeg.c | 43 |
3 files changed, 53 insertions, 32 deletions
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h index 54a6899a78..d180935aa4 100644 --- a/firmware/export/mp3data.h +++ b/firmware/export/mp3data.h | |||
@@ -61,6 +61,7 @@ int count_mp3_frames(int fd, int startpos, int filesize, | |||
61 | void (*progressfunc)(int)); | 61 | void (*progressfunc)(int)); |
62 | int create_xing_header(int fd, int startpos, int filesize, | 62 | int create_xing_header(int fd, int startpos, int filesize, |
63 | unsigned char *buf, int num_frames, | 63 | unsigned char *buf, int num_frames, |
64 | int mpeg_version, int sample_rate, | ||
64 | void (*progressfunc)(int), bool generate_toc); | 65 | void (*progressfunc)(int), bool generate_toc); |
65 | 66 | ||
66 | #endif | 67 | #endif |
diff --git a/firmware/mp3data.c b/firmware/mp3data.c index 28f2cb27f3..98dff50442 100644 --- a/firmware/mp3data.c +++ b/firmware/mp3data.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include "mp3data.h" | 35 | #include "mp3data.h" |
36 | #include "file.h" | 36 | #include "file.h" |
37 | 37 | ||
38 | #undef DEBUG_VERBOSE | 38 | #define DEBUG_VERBOSE |
39 | 39 | ||
40 | #define BYTES2INT(b1,b2,b3,b4) (((b1 & 0xFF) << (3*8)) | \ | 40 | #define BYTES2INT(b1,b2,b3,b4) (((b1 & 0xFF) << (3*8)) | \ |
41 | ((b2 & 0xFF) << (2*8)) | \ | 41 | ((b2 & 0xFF) << (2*8)) | \ |
@@ -530,9 +530,10 @@ 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, 44.1kHz, with silence */ | 533 | /* This is an MP3 header, 128kbit/s, with silence |
534 | MPEG version and sample frequency are not set */ | ||
534 | static const unsigned char xing_frame_header[] = { | 535 | static const unsigned char xing_frame_header[] = { |
535 | 0xff, 0xfa, 0x90, 0x64, 0x86, 0x1f | 536 | 0xff, 0xe2, 0x90, 0x64, 0x86, 0x1f |
536 | }; | 537 | }; |
537 | 538 | ||
538 | static const char cooltext[] = "Rockbox rocks"; | 539 | static const char cooltext[] = "Rockbox rocks"; |
@@ -601,11 +602,15 @@ int count_mp3_frames(int fd, int startpos, int filesize, | |||
601 | } | 602 | } |
602 | } | 603 | } |
603 | 604 | ||
605 | /* Note: mpeg_version and sample_rate are 2-bit values, as specified by the | ||
606 | MPEG frame standard. See the tables above. */ | ||
604 | int create_xing_header(int fd, int startpos, int filesize, | 607 | int create_xing_header(int fd, int startpos, int filesize, |
605 | unsigned char *buf, int num_frames, | 608 | unsigned char *buf, int num_frames, |
609 | int mpeg_version, int sample_rate, | ||
606 | void (*progressfunc)(int), bool generate_toc) | 610 | void (*progressfunc)(int), bool generate_toc) |
607 | { | 611 | { |
608 | unsigned long header = 0; | 612 | unsigned long header = 0; |
613 | unsigned long saved_header; | ||
609 | struct mp3info info; | 614 | struct mp3info info; |
610 | int pos, last_pos; | 615 | int pos, last_pos; |
611 | int i, j; | 616 | int i, j; |
@@ -618,9 +623,9 @@ int create_xing_header(int fd, int startpos, int filesize, | |||
618 | DEBUGF("create_xing_header()\n"); | 623 | DEBUGF("create_xing_header()\n"); |
619 | 624 | ||
620 | /* Create the frame header */ | 625 | /* Create the frame header */ |
621 | memset(buf, 0, 417); | 626 | memset(buf, 0, 1500); |
622 | memcpy(buf, xing_frame_header, 6); | 627 | memcpy(buf, xing_frame_header, 6); |
623 | 628 | ||
624 | lseek(fd, startpos, SEEK_SET); | 629 | lseek(fd, startpos, SEEK_SET); |
625 | buf_init(); | 630 | buf_init(); |
626 | 631 | ||
@@ -664,6 +669,10 @@ int create_xing_header(int fd, int startpos, int filesize, | |||
664 | buf_seek(fd, info.frame_size-4); | 669 | buf_seek(fd, info.frame_size-4); |
665 | filepos += info.frame_size; | 670 | filepos += info.frame_size; |
666 | } | 671 | } |
672 | |||
673 | /* Save one header for later use */ | ||
674 | if(i == 1) | ||
675 | saved_header = header; | ||
667 | 676 | ||
668 | if(progressfunc) | 677 | if(progressfunc) |
669 | { | 678 | { |
@@ -684,6 +693,26 @@ int create_xing_header(int fd, int startpos, int filesize, | |||
684 | 693 | ||
685 | memcpy(buf + index + 100, cooltext, sizeof(cooltext)); | 694 | memcpy(buf + index + 100, cooltext, sizeof(cooltext)); |
686 | 695 | ||
696 | /* We must fill in the correct sample rate and mpeg version. If the TOC | ||
697 | should be generated, we take that data from the actual stream. If not, | ||
698 | we use the supplied parameters. */ | ||
699 | if(generate_toc) | ||
700 | { | ||
701 | saved_header &= (VERSION_MASK | SAMPLERATE_MASK); | ||
702 | |||
703 | buf[1] |= (saved_header >> 16) & 0xff; | ||
704 | buf[2] |= (saved_header >> 8) & 0xff; | ||
705 | } | ||
706 | else | ||
707 | { | ||
708 | buf[1] |= mpeg_version << 3; | ||
709 | buf[2] |= sample_rate << 2; | ||
710 | } | ||
711 | |||
712 | /* Now get the length of the newly created frame */ | ||
713 | header = BYTES2INT(buf[0], buf[1], buf[2], buf[3]); | ||
714 | mp3headerinfo(&info, header); | ||
715 | |||
687 | #ifdef DEBUG | 716 | #ifdef DEBUG |
688 | for(i = 0;i < 417;i++) | 717 | for(i = 0;i < 417;i++) |
689 | { | 718 | { |
@@ -694,5 +723,5 @@ int create_xing_header(int fd, int startpos, int filesize, | |||
694 | } | 723 | } |
695 | #endif | 724 | #endif |
696 | 725 | ||
697 | return 0; | 726 | return info.frame_size; |
698 | } | 727 | } |
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index 85f9c72a25..7e48040da2 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -489,7 +489,8 @@ unsigned long record_start_time; /* Value of current_tick when recording | |||
489 | was started */ | 489 | was started */ |
490 | static bool saving; /* We are saving the buffer to disk */ | 490 | static bool saving; /* We are saving the buffer to disk */ |
491 | static char recording_filename[MAX_PATH]; | 491 | static char recording_filename[MAX_PATH]; |
492 | 492 | static int rec_frequency_index; /* For create_xing_header() calls */ | |
493 | static int rec_version_index; /* For create_xing_header() calls */ | ||
493 | #endif | 494 | #endif |
494 | 495 | ||
495 | static int mpeg_file; | 496 | static int mpeg_file; |
@@ -1010,13 +1011,6 @@ void IRQ3(void) | |||
1010 | dma_tick(); | 1011 | dma_tick(); |
1011 | else | 1012 | else |
1012 | postpone_dma_tick(); | 1013 | postpone_dma_tick(); |
1013 | |||
1014 | #if 0 | ||
1015 | if(mpeg_mode == MPEG_ENCODER) | ||
1016 | /* Shut off if recording is stopped */ | ||
1017 | if(!is_recording) | ||
1018 | demand_irq_enable(false); | ||
1019 | #endif | ||
1020 | } | 1014 | } |
1021 | #endif | 1015 | #endif |
1022 | 1016 | ||
@@ -1271,6 +1265,7 @@ static void mpeg_thread(void) | |||
1271 | #ifdef HAVE_MAS3587F | 1265 | #ifdef HAVE_MAS3587F |
1272 | int amount_to_save; | 1266 | int amount_to_save; |
1273 | int writelen; | 1267 | int writelen; |
1268 | int framelen; | ||
1274 | #endif | 1269 | #endif |
1275 | 1270 | ||
1276 | is_playing = false; | 1271 | is_playing = false; |
@@ -1734,15 +1729,6 @@ static void mpeg_thread(void) | |||
1734 | DEBUGF("R\n"); | 1729 | DEBUGF("R\n"); |
1735 | t1 = current_tick; | 1730 | t1 = current_tick; |
1736 | len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read); | 1731 | len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read); |
1737 | #if 0 | ||
1738 | if(id3tags[tag_read_idx]->id3.vbr) | ||
1739 | /* Average bitrate * 1.5 */ | ||
1740 | recalculate_watermark( | ||
1741 | (id3tags[tag_read_idx]->id3.bitrate * 3) / 2); | ||
1742 | else | ||
1743 | recalculate_watermark( | ||
1744 | id3tags[tag_read_idx]->id3.bitrate); | ||
1745 | #endif | ||
1746 | if(len > 0) | 1732 | if(len > 0) |
1747 | { | 1733 | { |
1748 | t2 = current_tick; | 1734 | t2 = current_tick; |
@@ -1854,10 +1840,10 @@ static void mpeg_thread(void) | |||
1854 | DEBUGF("Recording...\n"); | 1840 | DEBUGF("Recording...\n"); |
1855 | reset_mp3_buffer(); | 1841 | reset_mp3_buffer(); |
1856 | 1842 | ||
1857 | /* Advance the write pointer 4096+417 bytes to make | 1843 | /* Advance the write pointer 4096+1500 bytes to make |
1858 | room for an ID3 tag plus a VBR header */ | 1844 | room for an ID3 tag plus a VBR header */ |
1859 | mp3buf_write = 4096+417; | 1845 | mp3buf_write = 4096+1500; |
1860 | memset(mp3buf, 0, 4096+417); | 1846 | memset(mp3buf, 0, 4096+1500); |
1861 | 1847 | ||
1862 | /* Insert the ID3 header */ | 1848 | /* Insert the ID3 header */ |
1863 | memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); | 1849 | memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); |
@@ -1898,12 +1884,14 @@ static void mpeg_thread(void) | |||
1898 | if(num_recorded_frames == 0x7ffff) | 1884 | if(num_recorded_frames == 0x7ffff) |
1899 | num_recorded_frames = 0; | 1885 | num_recorded_frames = 0; |
1900 | 1886 | ||
1901 | create_xing_header(mpeg_file, 0, num_rec_bytes, | 1887 | framelen = create_xing_header(mpeg_file, 0, num_rec_bytes, |
1902 | mp3buf, num_recorded_frames, NULL, | 1888 | mp3buf, num_recorded_frames, |
1903 | false); | 1889 | rec_version_index, |
1890 | rec_frequency_index, | ||
1891 | NULL, false); | ||
1904 | 1892 | ||
1905 | lseek(mpeg_file, 4096, SEEK_SET); | 1893 | lseek(mpeg_file, 4096+1500-framelen, SEEK_SET); |
1906 | write(mpeg_file, mp3buf, 417); | 1894 | write(mpeg_file, mp3buf, framelen); |
1907 | close(mpeg_file); | 1895 | close(mpeg_file); |
1908 | 1896 | ||
1909 | mpeg_file = -1; | 1897 | mpeg_file = -1; |
@@ -2841,9 +2829,12 @@ void mpeg_set_recording_options(int frequency, int quality, | |||
2841 | unsigned long val; | 2829 | unsigned long val; |
2842 | 2830 | ||
2843 | is_mpeg1 = (frequency < 3)?true:false; | 2831 | is_mpeg1 = (frequency < 3)?true:false; |
2832 | |||
2833 | rec_version_index = is_mpeg1?3:2; | ||
2834 | rec_frequency_index = frequency % 3; | ||
2844 | 2835 | ||
2845 | val = (quality << 17) | | 2836 | val = (quality << 17) | |
2846 | ((frequency % 3) << 10) | | 2837 | (rec_frequency_index << 10) | |
2847 | ((is_mpeg1?1:0) << 9) | | 2838 | ((is_mpeg1?1:0) << 9) | |
2848 | (1 << 8) | /* CRC on */ | 2839 | (1 << 8) | /* CRC on */ |
2849 | (((channel_mode * 2 + 1) & 3) << 6) | | 2840 | (((channel_mode * 2 + 1) & 3) << 6) | |