summaryrefslogtreecommitdiff
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
parentc6fb565dd98d2da0cd5ba0e29b73c49617edcb9c (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.lang5
-rw-r--r--apps/onplay.c6
-rw-r--r--apps/recorder/recording.c30
-rw-r--r--apps/settings.c26
-rw-r--r--apps/settings.h1
-rw-r--r--apps/sound_menu.c7
-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
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 */