diff options
author | Linus Nielsen Feltzing <linus@haxx.se> | 2003-04-20 22:00:30 +0000 |
---|---|---|
committer | Linus Nielsen Feltzing <linus@haxx.se> | 2003-04-20 22:00:30 +0000 |
commit | 478da628f0eb5fb3b5163dab459927ada52badfc (patch) | |
tree | 04e27d8bd6122a23c0fe483c4d35e149d1953179 | |
parent | c6fb565dd98d2da0cd5ba0e29b73c49617edcb9c (diff) |
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
-rw-r--r-- | apps/lang/english.lang | 5 | ||||
-rw-r--r-- | apps/onplay.c | 6 | ||||
-rw-r--r-- | apps/recorder/recording.c | 30 | ||||
-rw-r--r-- | apps/settings.c | 26 | ||||
-rw-r--r-- | apps/settings.h | 1 | ||||
-rw-r--r-- | apps/sound_menu.c | 7 | ||||
-rw-r--r-- | firmware/export/mp3data.h | 2 | ||||
-rw-r--r-- | firmware/export/mpeg.h | 6 | ||||
-rw-r--r-- | firmware/mp3data.c | 133 | ||||
-rw-r--r-- | firmware/mpeg.c | 26 |
10 files changed, 152 insertions, 90 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index e080491e2c..15d9039018 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -1467,3 +1467,8 @@ id: LANG_INVERT_CURSOR desc: in settings_menu eng: "Invert cursor" new: + +id: LANG_RECORDING_EDITABLE +desc: Editable recordings setting +eng: "Editable files" +new: diff --git a/apps/onplay.c b/apps/onplay.c index 3ba4c1b49c..14e3cdd7a7 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -251,11 +251,11 @@ static bool vbr_fix(void) flen, xingupdate); if(num_frames) { - /* Note: We don't need to pass any values for mpeg_version and - sample_rate because they will be extracted from the mpeg stream */ + /* Note: We don't need to pass a template header because it will be + taken from the mpeg stream */ framelen = create_xing_header(fd, entry.first_frame_offset, flen, xingbuf, num_frames, - 0, 0, xingupdate, true); + 0, xingupdate, true); /* Try to fit the Xing header first in the stream. Replace the existing VBR header if there is one, else see if there is room between the diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c index cf295db19c..14bd37d950 100644 --- a/apps/recorder/recording.c +++ b/apps/recorder/recording.c @@ -169,7 +169,8 @@ bool recording_screen(void) mpeg_set_recording_options(global_settings.rec_frequency, global_settings.rec_quality, global_settings.rec_source, - global_settings.rec_channels); + global_settings.rec_channels, + global_settings.rec_editable); set_gain(); @@ -312,22 +313,29 @@ bool recording_screen(void) mpeg_set_recording_options(global_settings.rec_frequency, global_settings.rec_quality, global_settings.rec_source, - global_settings.rec_channels); + global_settings.rec_channels, + global_settings.rec_editable); set_gain(); update_countdown = 1; /* Update immediately */ break; case BUTTON_F2: - if (f2_rec_screen()) - return SYS_USB_CONNECTED; - update_countdown = 1; /* Update immediately */ + if(mpeg_status()) + { + if (f2_rec_screen()) + return SYS_USB_CONNECTED; + update_countdown = 1; /* Update immediately */ + } break; case BUTTON_F3: - if (f3_rec_screen()) - return SYS_USB_CONNECTED; - update_countdown = 1; /* Update immediately */ + if(mpeg_status()) + { + if (f3_rec_screen()) + return SYS_USB_CONNECTED; + update_countdown = 1; /* Update immediately */ + } break; } @@ -537,7 +545,8 @@ bool f2_rec_screen(void) mpeg_set_recording_options(global_settings.rec_frequency, global_settings.rec_quality, global_settings.rec_source, - global_settings.rec_channels); + global_settings.rec_channels, + global_settings.rec_editable); set_gain(); @@ -621,7 +630,8 @@ bool f3_rec_screen(void) mpeg_set_recording_options(global_settings.rec_frequency, global_settings.rec_quality, global_settings.rec_source, - global_settings.rec_channels); + global_settings.rec_channels, + global_settings.rec_editable); set_gain(); diff --git a/apps/settings.c b/apps/settings.c index 8c132c5f9b..8b74df852b 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -96,8 +96,8 @@ offset abs 0x16 0x2a <(int) Byte offset into resume file> 0x1a 0x2e <time until disk spindown> 0x1b 0x2f <browse current, play selected, queue_resume> -0x1c 0x30 <peak meter hold timeout (bit 0-4)>, - peak_meter_performance (bit 7) +0x1c 0x30 <peak meter hold timeout (bit 0-4), + rec_editable (bit 7)> 0x1d 0x31 <(int) queue resume index> 0x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2), mic gain (bit 4-7)> @@ -125,7 +125,7 @@ modified unless the header & checksum test fails. Rest of config block, only saved to disk: 0xAE fade on pause/unpause/stop setting (bit 0) -0xB0 peak meter clip hold timeout (bit 0-4) +0xB0 peak meter clip hold timeout (bit 0-4), peak meter performance (bit 7) 0xB1 peak meter release step size, peak_meter_dbfs (bit 7) 0xB2 peak meter min either in -db or in percent 0xB3 peak meter max either in -db or in percent @@ -341,7 +341,8 @@ int settings_save( void ) ((global_settings.play_selected & 1) << 1) | ((global_settings.queue_resume & 3) << 2)); - config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold; + config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold | + (global_settings.rec_editable?0x80:0); memcpy(&config_block[0x1d], &global_settings.queue_resume_index, 4); @@ -617,8 +618,11 @@ void settings_load(void) global_settings.queue_resume = (config_block[0x1b] >> 2) & 3; } - if (config_block[0x1c] != 0xFF) + if (config_block[0x1c] != 0xFF) { global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f; + global_settings.rec_editable = + config_block[0x1c]?true:false; + } if (config_block[0x1d] != 0xFF) memcpy(&global_settings.queue_resume_index, &config_block[0x1d], @@ -1029,6 +1033,9 @@ bool settings_load_config(char* file) static char* options[] = {"stereo", "mono"}; set_cfg_option(&global_settings.rec_channels, value, options, 2); } + else if (!strcasecmp(name, "editable recordings")) { + set_cfg_bool(&global_settings.rec_editable, value); + } #endif else if (!strcasecmp(name, "idle poweroff")) { static char* options[] = {"off","1","2","3","4","5","6","7","8", @@ -1434,6 +1441,14 @@ bool settings_save_config(void) global_settings.rec_left_gain, global_settings.rec_right_gain); write(fd, buf, strlen(buf)); + + { + static char* options[] = {"off", "on"}; + snprintf(buf, sizeof(buf), "editable recordings: %s\r\n", + options[global_settings.rec_editable]); + write(fd, buf, strlen(buf)); + } + #endif close(fd); @@ -1467,6 +1482,7 @@ void settings_reset(void) { global_settings.rec_mic_gain = 8; global_settings.rec_left_gain = 2; /* 0dB */ global_settings.rec_right_gain = 2; /* 0dB */ + global_settings.rec_editable = false; global_settings.resume = RESUME_ASK; global_settings.contrast = DEFAULT_CONTRAST_SETTING; global_settings.invert = DEFAULT_INVERT_SETTING; diff --git a/apps/settings.h b/apps/settings.h index 7876a18afa..0ff7cb2102 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -74,6 +74,7 @@ struct user_settings int rec_mic_gain; /* 0-15 */ int rec_left_gain; /* 0-15 */ int rec_right_gain; /* 0-15 */ + bool rec_editable; /* true means that the bit reservoir is off */ /* device settings */ diff --git a/apps/sound_menu.c b/apps/sound_menu.c index 9ac95e46b8..84d389a47a 100644 --- a/apps/sound_menu.c +++ b/apps/sound_menu.c @@ -219,6 +219,12 @@ static bool recquality(void) &global_settings.rec_quality, NULL, 1, 0, 7 ); } + +static bool receditable(void) +{ + return set_bool(str(LANG_RECORDING_EDITABLE), + &global_settings.rec_editable); +} #endif /* HAVE_MAS3587F */ static void set_chanconf(int val) @@ -275,6 +281,7 @@ bool recording_menu(void) { str(LANG_RECORDING_FREQUENCY), recfrequency }, { str(LANG_RECORDING_SOURCE), recsource }, { str(LANG_RECORDING_CHANNELS), recchannels }, + { str(LANG_RECORDING_EDITABLE), receditable }, }; m=menu_init( items, sizeof items / sizeof(struct menu_items) ); 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 */ |