summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter D'Hoye <peter.dhoye@gmail.com>2008-10-08 22:18:16 +0000
committerPeter D'Hoye <peter.dhoye@gmail.com>2008-10-08 22:18:16 +0000
commit528fe442fc6e6e077172b2e8a3b586a3ce96d16b (patch)
tree4985fe6f102727419862cf58bcb5aa8a7d736f11
parentcb1173cedd4eb1c8648420a3926a591995390537 (diff)
downloadrockbox-528fe442fc6e6e077172b2e8a3b586a3ce96d16b.tar.gz
rockbox-528fe442fc6e6e077172b2e8a3b586a3ce96d16b.zip
New recording setting to configure how mono recordings are made. Previously, this was always L+R, which was kinda silly if your signal was on L only. This setting allows for L, R or L+R. SWCODEC only for now, to be added for HWCODEC (although that will only be L and L+R probably)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18745 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/aiff_enc.c43
-rw-r--r--apps/codecs/mp3_enc.c28
-rw-r--r--apps/codecs/wav_enc.c41
-rw-r--r--apps/lang/english.lang34
-rw-r--r--apps/menus/recording_menu.c23
-rw-r--r--apps/recorder/recording.c1
-rw-r--r--apps/settings.h3
-rw-r--r--apps/settings_list.c4
-rw-r--r--firmware/export/audio.h1
-rw-r--r--firmware/export/enc_base.h1
-rw-r--r--firmware/pcm_record.c9
11 files changed, 162 insertions, 26 deletions
diff --git a/apps/codecs/aiff_enc.c b/apps/codecs/aiff_enc.c
index 7e085d5721..78c25b8711 100644
--- a/apps/codecs/aiff_enc.c
+++ b/apps/codecs/aiff_enc.c
@@ -72,6 +72,7 @@ struct aiff_header aiff_header =
/* (*) updated when finalizing file */
static int num_channels IBSS_ATTR;
+static int rec_mono_mode IBSS_ATTR;
static uint32_t sample_rate;
static uint32_t enc_size;
static int32_t err IBSS_ATTR;
@@ -226,16 +227,37 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
{
int32_t lr1, lr2;
- lr1 = *(*src)++;
- lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
- err = lr1 & 1;
- lr1 >>= 1;
-
- lr2 = *(*src)++;
- lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
- err = lr2 & 1;
- lr2 >>= 1;
- *(*dst)++ = swap_odd_even_le32((lr1 << 16) | (uint16_t)lr2);
+ switch(rec_mono_mode)
+ {
+ case 1:
+ /* mono = L */
+ lr1 = *(*src)++;
+ lr1 = lr1 >> 16;
+ lr2 = *(*src)++;
+ lr2 = lr2 >> 16;
+ break;
+ case 2:
+ /* mono = R */
+ lr1 = *(*src)++;
+ lr1 = (int16_t)lr1;
+ lr2 = *(*src)++;
+ lr2 = (int16_t)lr2;
+ break;
+ case 0:
+ default:
+ /* mono = (L+R)/2 */
+ lr1 = *(*src)++;
+ lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
+ err = lr1 & 1;
+ lr1 >>= 1;
+
+ lr2 = *(*src)++;
+ lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
+ err = lr2 & 1;
+ lr2 >>= 1;
+ break;
+ }
+ *(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
} /* sample_to_mono */
STATICIRAM void chunk_to_aiff_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
@@ -316,6 +338,7 @@ static bool init_encoder(void)
sample_rate = inputs.sample_rate;
num_channels = inputs.num_channels;
+ rec_mono_mode = inputs.rec_mono_mode;
err = 0;
/* configure the buffer system */
diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c
index 767a292343..555e981a06 100644
--- a/apps/codecs/mp3_enc.c
+++ b/apps/codecs/mp3_enc.c
@@ -90,6 +90,7 @@ typedef struct {
int mean_bits;
int ResvSize;
int channels;
+ int rec_mono_mode;
int granules;
long samplerate;
} config_t;
@@ -1972,12 +1973,14 @@ static int find_samplerate_index(long freq, int *mp3_type)
bool init_mp3_encoder_engine(int sample_rate,
int num_channels,
+ int rec_mono_mode,
struct encoder_config *enc_cfg)
{
const bool stereo = num_channels > 1;
uint32_t avg_byte_per_frame;
cfg.channels = stereo ? 2 : 1;
+ cfg.rec_mono_mode = rec_mono_mode;
cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type);
cfg.samplerate = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id];
@@ -2093,9 +2096,26 @@ STATICIRAM void to_mono_mm(void)
inline void to_mono(uint32_t **samp)
{
int32_t lr = **samp;
- int32_t m = (int16_t)lr + (lr >> 16) + err;
- err = m & 1;
- m >>= 1;
+ int32_t m;
+
+ switch(cfg.rec_mono_mode)
+ {
+ case 1:
+ /* mono = L */
+ m = lr >> 16;
+ break;
+ case 2:
+ /* mono = R */
+ m = (int16_t)lr;
+ break;
+ case 0:
+ default:
+ /* mono = (L+R)/2 */
+ m = (int16_t)lr + (lr >> 16) + err;
+ err = m & 1;
+ m >>= 1;
+ break;
+ }
*(*samp)++ = (m << 16) | (uint16_t)m;
} /* to_mono */
@@ -2517,7 +2537,7 @@ static bool enc_init(void)
return false;
init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels,
- inputs.config);
+ inputs.rec_mono_mode, inputs.config);
err = 0;
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c
index a59eff7581..3627808271 100644
--- a/apps/codecs/wav_enc.c
+++ b/apps/codecs/wav_enc.c
@@ -60,6 +60,7 @@ struct riff_header
#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
static int num_channels IBSS_ATTR;
+static int rec_mono_mode IBSS_ATTR;
static uint32_t sample_rate;
static uint32_t enc_size;
static int32_t err IBSS_ATTR;
@@ -215,15 +216,36 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
{
int32_t lr1, lr2;
- lr1 = *(*src)++;
- lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
- err = lr1 & 1;
- lr1 >>= 1;
-
- lr2 = *(*src)++;
- lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
- err = lr2 & 1;
- lr2 >>= 1;
+ switch(rec_mono_mode)
+ {
+ case 1:
+ /* mono = L */
+ lr1 = *(*src)++;
+ lr1 = lr1 >> 16;
+ lr2 = *(*src)++;
+ lr2 = lr2 >> 16;
+ break;
+ case 2:
+ /* mono = R */
+ lr1 = *(*src)++;
+ lr1 = (uint16_t)lr1;
+ lr2 = *(*src)++;
+ lr2 = (uint16_t)lr2;
+ break;
+ case 0:
+ default:
+ /* mono = (L+R)/2 */
+ lr1 = *(*src)++;
+ lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
+ err = lr1 & 1;
+ lr1 >>= 1;
+
+ lr2 = *(*src)++;
+ lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
+ err = lr2 & 1;
+ lr2 >>= 1;
+ break;
+ }
*(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
} /* sample_to_mono */
@@ -305,6 +327,7 @@ static bool init_encoder(void)
sample_rate = inputs.sample_rate;
num_channels = inputs.num_channels;
+ rec_mono_mode = inputs.rec_mono_mode;
err = 0;
/* configure the buffer system */
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 6acc83613e..04913d6c75 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -847,6 +847,23 @@
</voice>
</phrase>
<phrase>
+ id: LANG_CHANNEL_LEFTRIGHT
+ desc: in sound_settings
+ user:
+ <source>
+ *: none
+ recording_swcodec: "Mono Left + Right"
+ </source>
+ <dest>
+ *: none
+ recording_swcodec: "Mono Left + Right"
+ </dest>
+ <voice>
+ *: none
+ recording_swcodec: "Mono Left plus Right"
+ </voice>
+</phrase>
+<phrase>
id: LANG_CHANNEL_KARAOKE
desc: in sound_settings
user:
@@ -12061,3 +12078,20 @@
albumart: ""
</voice>
</phrase>
+<phrase>
+ id: LANG_RECORDING_MONO_MODE
+ desc: in sound_settings
+ user:
+ <source>
+ *: none
+ recording_swcodec: "Mono mode"
+ </source>
+ <dest>
+ *: none
+ recording_swcodec: "Mono mode"
+ </dest>
+ <voice>
+ *: none
+ recording_swcodec: "Mono mode"
+ </voice>
+</phrase>
diff --git a/apps/menus/recording_menu.c b/apps/menus/recording_menu.c
index 4705afa2ff..6f1aca4850 100644
--- a/apps/menus/recording_menu.c
+++ b/apps/menus/recording_menu.c
@@ -265,6 +265,26 @@ MENUITEM_FUNCTION(recchannels, 0, ID2P(LANG_CHANNELS),
#if CONFIG_CODEC == SWCODEC
+static int recmonomode_func(void)
+{
+ static const struct opt_items names[3] = {
+ [0] = { STR(LANG_CHANNEL_LEFTRIGHT) },
+ [1] = { STR(LANG_CHANNEL_LEFT) },
+ [2] = { STR(LANG_CHANNEL_RIGHT) },
+ };
+
+ int rec_mono_mode = global_settings.rec_mono_mode;
+ bool ret = set_option(str(LANG_RECORDING_MONO_MODE), &rec_mono_mode,
+ INT, names, 3, NULL );
+
+ if (rec_mono_mode != global_settings.rec_mono_mode)
+ global_settings.rec_mono_mode = rec_mono_mode;
+
+ return ret;
+}
+MENUITEM_FUNCTION(recmonomode, 0, ID2P(LANG_RECORDING_MONO_MODE),
+ recmonomode_func, NULL, NULL, Icon_Menu_setting);
+
static int recformat_func(void)
{
static const struct opt_items names[REC_NUM_FORMATS] = {
@@ -608,6 +628,9 @@ MAKE_MENU(recording_settings_menu, ID2P(LANG_RECORDING_SETTINGS),
#endif
&recfrequency, &recsource, /* recsource not shown if no_source */
&recchannels,
+#if CONFIG_CODEC == SWCODEC
+ &recmonomode,
+#endif
#if CONFIG_CODEC == MAS3587F
&rec_editable,
#endif
diff --git a/apps/recorder/recording.c b/apps/recorder/recording.c
index a90853fb64..6f5c7df09a 100644
--- a/apps/recorder/recording.c
+++ b/apps/recorder/recording.c
@@ -628,6 +628,7 @@ void rec_init_recording_options(struct audio_recording_options *options)
options->rec_channels = global_settings.rec_channels;
options->rec_prerecord_time = global_settings.rec_prerecord_time;
#if CONFIG_CODEC == SWCODEC
+ options->rec_mono_mode = global_settings.rec_mono_mode;
options->rec_source_flags = 0;
options->enc_config.rec_format = global_settings.rec_format;
global_to_encoder_config(&options->enc_config);
diff --git a/apps/settings.h b/apps/settings.h
index 9ba4396f9d..d6a21e8ef6 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -341,6 +341,9 @@ struct user_settings
4 = 24kHz
5 = 16kHz */
int rec_channels; /* 0=Stereo, 1=Mono */
+#if CONFIG_CODEC == SWCODEC
+ int rec_mono_mode; /* how to create mono: L, R, L+R */
+#endif
int rec_mic_gain; /* depends on target */
int rec_left_gain; /* depends on target */
int rec_right_gain; /* depands on target */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 8994ca45b7..4c265077ad 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -866,6 +866,10 @@ const struct settings_list settings[] = {
TALK_ID(1792, UNIT_MB)),
{F_T_INT|F_RECSETTING, &global_settings.rec_channels, LANG_CHANNELS, INT(0),
"rec channels","stereo,mono",UNUSED},
+#if CONFIG_CODEC == SWCODEC
+ {F_T_INT|F_RECSETTING, &global_settings.rec_mono_mode,
+ LANG_RECORDING_MONO_MODE, INT(0), "rec mono mode","L+R,L,R",UNUSED},
+#endif
CHOICE_SETTING(F_RECSETTING, rec_split_type, LANG_SPLIT_TYPE, 0,
"rec split type", "Split,Stop,Shutdown", NULL, 3,
ID2P(LANG_START_NEW_FILE), ID2P(LANG_STOP_RECORDING),ID2P(LANG_STOP_RECORDING_AND_SHUTDOWN)),
diff --git a/firmware/export/audio.h b/firmware/export/audio.h
index aedaffbe89..9530082050 100644
--- a/firmware/export/audio.h
+++ b/firmware/export/audio.h
@@ -176,6 +176,7 @@ struct audio_recording_options
int rec_channels;
int rec_prerecord_time;
#if CONFIG_CODEC == SWCODEC
+ int rec_mono_mode;
int rec_source_flags; /* for rec_set_source */
struct encoder_config enc_config;
#else
diff --git a/firmware/export/enc_base.h b/firmware/export/enc_base.h
index e73e87659d..321421c6e7 100644
--- a/firmware/export/enc_base.h
+++ b/firmware/export/enc_base.h
@@ -246,6 +246,7 @@ struct enc_inputs
{
unsigned long sample_rate; /* out - pcm frequency */
int num_channels; /* out - number of audio channels */
+ int rec_mono_mode; /* out - how to create mono */
struct encoder_config *config; /* out - encoder settings */
};
diff --git a/firmware/pcm_record.c b/firmware/pcm_record.c
index 045ace98c4..0e0102af97 100644
--- a/firmware/pcm_record.c
+++ b/firmware/pcm_record.c
@@ -90,6 +90,7 @@ static int rec_source; /* current rec_source setting */
static int rec_frequency; /* current frequency setting */
static unsigned long sample_rate; /* Sample rate in HZ */
static int num_channels; /* Current number of channels */
+static int rec_mono_mode; /* how mono is created */
static struct encoder_config enc_config; /* Current encoder configuration */
static unsigned long pre_record_ticks; /* pre-record time in ticks */
@@ -1178,6 +1179,7 @@ static void pcmrec_set_recording_options(
rec_frequency = options->rec_frequency;
rec_source = options->rec_source;
num_channels = options->rec_channels == 1 ? 1 : 2;
+ rec_mono_mode = options->rec_mono_mode;
pre_record_ticks = options->rec_prerecord_time * HZ;
enc_config = options->enc_config;
enc_config.afmt = rec_format_afmt[enc_config.rec_format];
@@ -1526,17 +1528,18 @@ void enc_get_inputs(struct enc_inputs *inputs)
{
inputs->sample_rate = sample_rate;
inputs->num_channels = num_channels;
+ inputs->rec_mono_mode = rec_mono_mode;
inputs->config = &enc_config;
} /* enc_get_inputs */
-
+
/* set the encoder dimensions (called by encoder codec at initialization and
termination) */
void enc_set_parameters(struct enc_parameters *params)
{
size_t bufsize, resbytes;
-
+
logf("enc_set_parameters");
-
+
if (!params)
{
logf("reset");