summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-04-20 22:00:30 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-04-20 22:00:30 +0000
commit478da628f0eb5fb3b5163dab459927ada52badfc (patch)
tree04e27d8bd6122a23c0fe483c4d35e149d1953179 /firmware
parentc6fb565dd98d2da0cd5ba0e29b73c49617edcb9c (diff)
downloadrockbox-478da628f0eb5fb3b5163dab459927ada52badfc.tar.gz
rockbox-478da628f0eb5fb3b5163dab459927ada52badfc.zip
Xing headers now support mono better, added the 'editable files' option
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3572 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/mp3data.h2
-rw-r--r--firmware/export/mpeg.h6
-rw-r--r--firmware/mp3data.c133
-rw-r--r--firmware/mpeg.c26
4 files changed, 95 insertions, 72 deletions
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index d180935aa4..6b3ff83b1a 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -61,7 +61,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
61 void (*progressfunc)(int)); 61 void (*progressfunc)(int));
62int create_xing_header(int fd, int startpos, int filesize, 62int 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 unsigned long header_template,
65 void (*progressfunc)(int), bool generate_toc); 65 void (*progressfunc)(int), bool generate_toc);
66 66
67#endif 67#endif
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index e971aaac33..d939567f3d 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -32,6 +32,9 @@
32#define MPEG_PLAY_PENDING_THRESHOLD 0x10000 32#define MPEG_PLAY_PENDING_THRESHOLD 0x10000
33#define MPEG_PLAY_PENDING_SWAPSIZE 0x10000 33#define MPEG_PLAY_PENDING_SWAPSIZE 0x10000
34 34
35/* For ID3 info and VBR header */
36#define MPEG_RESERVED_HEADER_SPACE (4096 + 1500)
37
35struct mpeg_debug 38struct mpeg_debug
36{ 39{
37 int mp3buflen; 40 int mp3buflen;
@@ -84,7 +87,8 @@ void mpeg_init_recording(void);
84void mpeg_init_playback(void); 87void mpeg_init_playback(void);
85void mpeg_record(char *filename); 88void mpeg_record(char *filename);
86void mpeg_set_recording_options(int frequency, int quality, 89void mpeg_set_recording_options(int frequency, int quality,
87 int source, int channel_mode); 90 int source, int channel_mode,
91 bool editable);
88void mpeg_set_recording_gain(int left, int right, int mic); 92void mpeg_set_recording_gain(int left, int right, int mic);
89unsigned long mpeg_recorded_time(void); 93unsigned long mpeg_recorded_time(void);
90unsigned long mpeg_num_recorded_bytes(void); 94unsigned long mpeg_num_recorded_bytes(void);
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");
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 7e48040da2..11837d608e 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -1266,6 +1266,7 @@ static void mpeg_thread(void)
1266 int amount_to_save; 1266 int amount_to_save;
1267 int writelen; 1267 int writelen;
1268 int framelen; 1268 int framelen;
1269 unsigned long saved_header;
1269#endif 1270#endif
1270 1271
1271 is_playing = false; 1272 is_playing = false;
@@ -1840,10 +1841,10 @@ static void mpeg_thread(void)
1840 DEBUGF("Recording...\n"); 1841 DEBUGF("Recording...\n");
1841 reset_mp3_buffer(); 1842 reset_mp3_buffer();
1842 1843
1843 /* Advance the write pointer 4096+1500 bytes to make 1844 /* Advance the write pointer to make
1844 room for an ID3 tag plus a VBR header */ 1845 room for an ID3 tag plus a VBR header */
1845 mp3buf_write = 4096+1500; 1846 mp3buf_write = MPEG_RESERVED_HEADER_SPACE;
1846 memset(mp3buf, 0, 4096+1500); 1847 memset(mp3buf, 0, MPEG_RESERVED_HEADER_SPACE);
1847 1848
1848 /* Insert the ID3 header */ 1849 /* Insert the ID3 header */
1849 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); 1850 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header));
@@ -1883,14 +1884,17 @@ static void mpeg_thread(void)
1883 we can no longer trust it */ 1884 we can no longer trust it */
1884 if(num_recorded_frames == 0x7ffff) 1885 if(num_recorded_frames == 0x7ffff)
1885 num_recorded_frames = 0; 1886 num_recorded_frames = 0;
1887
1888 /* Read the first MP3 frame from the recorded stream */
1889 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET);
1890 read(mpeg_file, &saved_header, 4);
1886 1891
1887 framelen = create_xing_header(mpeg_file, 0, num_rec_bytes, 1892 framelen = create_xing_header(mpeg_file, 0, num_rec_bytes,
1888 mp3buf, num_recorded_frames, 1893 mp3buf, num_recorded_frames,
1889 rec_version_index, 1894 saved_header, NULL, false);
1890 rec_frequency_index,
1891 NULL, false);
1892 1895
1893 lseek(mpeg_file, 4096+1500-framelen, SEEK_SET); 1896 lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen,
1897 SEEK_SET);
1894 write(mpeg_file, mp3buf, framelen); 1898 write(mpeg_file, mp3buf, framelen);
1895 close(mpeg_file); 1899 close(mpeg_file);
1896 1900
@@ -2823,7 +2827,8 @@ void mpeg_set_pitch(int pitch)
2823 2827
2824#ifdef HAVE_MAS3587F 2828#ifdef HAVE_MAS3587F
2825void mpeg_set_recording_options(int frequency, int quality, 2829void mpeg_set_recording_options(int frequency, int quality,
2826 int source, int channel_mode) 2830 int source, int channel_mode,
2831 bool editable)
2827{ 2832{
2828 bool is_mpeg1; 2833 bool is_mpeg1;
2829 unsigned long val; 2834 unsigned long val;
@@ -2844,6 +2849,11 @@ void mpeg_set_recording_options(int frequency, int quality,
2844 2849
2845 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val); 2850 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val);
2846 2851
2852 val = editable?4:0;
2853 mas_writemem(MAS_BANK_D0, 0x7f9, &val,1);
2854
2855 DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f9, %x)\n", val);
2856
2847 val = ((!is_recording << 10) | /* Monitoring */ 2857 val = ((!is_recording << 10) | /* Monitoring */
2848 ((source < 2)?1:2) << 8) | /* Input select */ 2858 ((source < 2)?1:2) << 8) | /* Input select */
2849 (1 << 5) | /* SDO strobe invert */ 2859 (1 << 5) | /* SDO strobe invert */