From 528fe442fc6e6e077172b2e8a3b586a3ce96d16b Mon Sep 17 00:00:00 2001 From: Peter D'Hoye Date: Wed, 8 Oct 2008 22:18:16 +0000 Subject: 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 --- apps/codecs/aiff_enc.c | 43 +++++++++++++++++++++++++++++++++---------- apps/codecs/mp3_enc.c | 28 ++++++++++++++++++++++++---- apps/codecs/wav_enc.c | 41 ++++++++++++++++++++++++++++++++--------- apps/lang/english.lang | 34 ++++++++++++++++++++++++++++++++++ apps/menus/recording_menu.c | 23 +++++++++++++++++++++++ apps/recorder/recording.c | 1 + apps/settings.h | 3 +++ apps/settings_list.c | 4 ++++ firmware/export/audio.h | 1 + firmware/export/enc_base.h | 1 + firmware/pcm_record.c | 9 ++++++--- 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 @@ -846,6 +846,23 @@ *: "Mono Right" + + id: LANG_CHANNEL_LEFTRIGHT + desc: in sound_settings + user: + + *: none + recording_swcodec: "Mono Left + Right" + + + *: none + recording_swcodec: "Mono Left + Right" + + + *: none + recording_swcodec: "Mono Left plus Right" + + id: LANG_CHANNEL_KARAOKE desc: in sound_settings @@ -12061,3 +12078,20 @@ albumart: "" + + id: LANG_RECORDING_MONO_MODE + desc: in sound_settings + user: + + *: none + recording_swcodec: "Mono mode" + + + *: none + recording_swcodec: "Mono mode" + + + *: none + recording_swcodec: "Mono mode" + + 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"); -- cgit v1.2.3