From 478da628f0eb5fb3b5163dab459927ada52badfc Mon Sep 17 00:00:00 2001 From: Linus Nielsen Feltzing Date: Sun, 20 Apr 2003 22:00:30 +0000 Subject: 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 --- firmware/export/mp3data.h | 2 +- firmware/export/mpeg.h | 6 ++- firmware/mp3data.c | 133 +++++++++++++++++++++++++--------------------- firmware/mpeg.c | 26 ++++++--- 4 files changed, 95 insertions(+), 72 deletions(-) (limited to 'firmware') 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, void (*progressfunc)(int)); int create_xing_header(int fd, int startpos, int filesize, unsigned char *buf, int num_frames, - int mpeg_version, int sample_rate, + unsigned long header_template, void (*progressfunc)(int), bool generate_toc); #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 @@ #define MPEG_PLAY_PENDING_THRESHOLD 0x10000 #define MPEG_PLAY_PENDING_SWAPSIZE 0x10000 +/* For ID3 info and VBR header */ +#define MPEG_RESERVED_HEADER_SPACE (4096 + 1500) + struct mpeg_debug { int mp3buflen; @@ -84,7 +87,8 @@ void mpeg_init_recording(void); void mpeg_init_playback(void); void mpeg_record(char *filename); void mpeg_set_recording_options(int frequency, int quality, - int source, int channel_mode); + int source, int channel_mode, + bool editable); void mpeg_set_recording_gain(int left, int right, int mic); unsigned long mpeg_recorded_time(void); unsigned 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) return bytecount; } -/* This is an MP3 header, 128kbit/s, with silence - MPEG version and sample frequency are not set */ -static const unsigned char xing_frame_header[] = { - 0xff, 0xe2, 0x90, 0x64, 0x86, 0x1f -}; - -static const char cooltext[] = "Rockbox rocks"; - static void int2bytes(unsigned char *buf, int val) { buf[0] = (val >> 24) & 0xff; @@ -602,55 +594,30 @@ int count_mp3_frames(int fd, int startpos, int filesize, } } -/* Note: mpeg_version and sample_rate are 2-bit values, as specified by the - MPEG frame standard. See the tables above. */ +static const char cooltext[] = "Rockbox - rocks your box"; + int create_xing_header(int fd, int startpos, int filesize, unsigned char *buf, int num_frames, - int mpeg_version, int sample_rate, + unsigned long header_template, void (*progressfunc)(int), bool generate_toc) { unsigned long header = 0; - unsigned long saved_header = 0; struct mp3info info; int pos, last_pos; int i, j; int bytes; int filepos; - int tocentry; int x; int index; + unsigned char toc[100]; DEBUGF("create_xing_header()\n"); - /* Create the frame header */ - memset(buf, 0, 1500); - memcpy(buf, xing_frame_header, 6); - - lseek(fd, startpos, SEEK_SET); - buf_init(); - - buf[36] = 'X'; - buf[36+1] = 'i'; - buf[36+2] = 'n'; - buf[36+3] = 'g'; - int2bytes(&buf[36+4], ((num_frames?VBR_FRAMES_FLAG:0) | - (filesize?VBR_BYTES_FLAG:0) | - (generate_toc?VBR_TOC_FLAG:0))); - index = 36+8; - if(num_frames) - { - int2bytes(&buf[index], num_frames); - index += 4; - } - - if(filesize) - { - int2bytes(&buf[index], filesize - startpos); - index += 4; - } - if(generate_toc) { + lseek(fd, startpos, SEEK_SET); + buf_init(); + /* Generate filepos table */ last_pos = 0; filepos = 0; @@ -670,48 +637,90 @@ int create_xing_header(int fd, int startpos, int filesize, filepos += info.frame_size; } - /* Save one header for later use */ + /* Save a header for later use. Yes, we may be passed a header + template in the header_template argument, but since we are + reading headers from the stream anyway, we might as well + use the ones we find. However, we only save one header, and + we want to save one in te middle of the stream, just in case + the first and the last headers are corrupt. */ if(i == 1) - saved_header = header; + header_template = header; if(progressfunc) { progressfunc(50 + i/2); } - tocentry = filepos * 256 / filesize; + /* Fill in the TOC entry */ + toc[i] = filepos * 256 / filesize; DEBUGF("Pos %d: %d relpos: %d filepos: %x tocentry: %x\n", - i, pos, pos-last_pos, filepos, tocentry); - - /* Fill in the TOC entry */ - buf[index + i] = tocentry; + i, pos, pos-last_pos, filepos, toc[i]); last_pos = pos; } + } + + /* Clear the frame */ + memset(buf, 0, 1500); - /* Copy the MPEG version and sample rate from the mpeg stream into - the Xing header */ - saved_header &= (VERSION_MASK | SAMPLERATE_MASK); + /* Use the template header and create a new one */ + mp3headerinfo(&info, header_template); + + /* calculate position of VBR header */ + if ( info.version == MPEG_VERSION1 ) { + if (info.channel_mode == 3) /* mono */ + index = 21; + else + index = 36; + } + else { + if (info.channel_mode == 3) /* mono */ + index = 13; + else + index = 21; + } + + /* We ignore the Protection bit even if the rest of the stream is + protected. (fixme?) */ + header = header_template & ~(BITRATE_MASK | PROTECTION_MASK); + header |= 8 << 12; /* This gives us plenty of space, at least 192 bytes */ + + /* Write the header to the buffer */ + int2bytes(buf, header); - buf[1] |= (saved_header >> 16) & 0xff; - buf[2] |= (saved_header >> 8) & 0xff; + /* Now get the length of the newly created frame */ + mp3headerinfo(&info, header); + + /* Create the Xing data */ + buf[index] = 'X'; + buf[index+1] = 'i'; + buf[index+2] = 'n'; + buf[index+3] = 'g'; + int2bytes(&buf[index+4], ((num_frames?VBR_FRAMES_FLAG:0) | + (filesize?VBR_BYTES_FLAG:0) | + (generate_toc?VBR_TOC_FLAG:0))); + index = index+8; + if(num_frames) + { + int2bytes(&buf[index], num_frames); + index += 4; } - else + + if(filesize) { - /* Fill in the MPEG version and sample rate into the Xing header */ - buf[1] |= mpeg_version << 3; - buf[2] |= sample_rate << 2; + int2bytes(&buf[index], filesize - startpos); + index += 4; } - + + /* Copy the TOC */ + memcpy(buf + index, toc, 100); + + /* And some extra cool info */ memcpy(buf + index + 100, cooltext, sizeof(cooltext)); - /* Now get the length of the newly created frame */ - header = BYTES2INT(buf[0], buf[1], buf[2], buf[3]); - mp3headerinfo(&info, header); - #ifdef DEBUG - for(i = 0;i < 417;i++) + for(i = 0;i < info.framesize;i++) { if(i && !(i % 16)) 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) int amount_to_save; int writelen; int framelen; + unsigned long saved_header; #endif is_playing = false; @@ -1840,10 +1841,10 @@ static void mpeg_thread(void) DEBUGF("Recording...\n"); reset_mp3_buffer(); - /* Advance the write pointer 4096+1500 bytes to make + /* Advance the write pointer to make room for an ID3 tag plus a VBR header */ - mp3buf_write = 4096+1500; - memset(mp3buf, 0, 4096+1500); + mp3buf_write = MPEG_RESERVED_HEADER_SPACE; + memset(mp3buf, 0, MPEG_RESERVED_HEADER_SPACE); /* Insert the ID3 header */ memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); @@ -1883,14 +1884,17 @@ static void mpeg_thread(void) we can no longer trust it */ if(num_recorded_frames == 0x7ffff) num_recorded_frames = 0; + + /* Read the first MP3 frame from the recorded stream */ + lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE, SEEK_SET); + read(mpeg_file, &saved_header, 4); framelen = create_xing_header(mpeg_file, 0, num_rec_bytes, mp3buf, num_recorded_frames, - rec_version_index, - rec_frequency_index, - NULL, false); + saved_header, NULL, false); - lseek(mpeg_file, 4096+1500-framelen, SEEK_SET); + lseek(mpeg_file, MPEG_RESERVED_HEADER_SPACE-framelen, + SEEK_SET); write(mpeg_file, mp3buf, framelen); close(mpeg_file); @@ -2823,7 +2827,8 @@ void mpeg_set_pitch(int pitch) #ifdef HAVE_MAS3587F void mpeg_set_recording_options(int frequency, int quality, - int source, int channel_mode) + int source, int channel_mode, + bool editable) { bool is_mpeg1; unsigned long val; @@ -2844,6 +2849,11 @@ void mpeg_set_recording_options(int frequency, int quality, DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f0, %x)\n", val); + val = editable?4:0; + mas_writemem(MAS_BANK_D0, 0x7f9, &val,1); + + DEBUGF("mas_writemem(MAS_BANK_D0, 0x7f9, %x)\n", val); + val = ((!is_recording << 10) | /* Monitoring */ ((source < 2)?1:2) << 8) | /* Input select */ (1 << 5) | /* SDO strobe invert */ -- cgit v1.2.3