summaryrefslogtreecommitdiff
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 =
72/* (*) updated when finalizing file */ 72/* (*) updated when finalizing file */
73 73
74static int num_channels IBSS_ATTR; 74static int num_channels IBSS_ATTR;
75static int rec_mono_mode IBSS_ATTR;
75static uint32_t sample_rate; 76static uint32_t sample_rate;
76static uint32_t enc_size; 77static uint32_t enc_size;
77static int32_t err IBSS_ATTR; 78static int32_t err IBSS_ATTR;
@@ -226,16 +227,37 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
226{ 227{
227 int32_t lr1, lr2; 228 int32_t lr1, lr2;
228 229
229 lr1 = *(*src)++; 230 switch(rec_mono_mode)
230 lr1 = (int16_t)lr1 + (lr1 >> 16) + err; 231 {
231 err = lr1 & 1; 232 case 1:
232 lr1 >>= 1; 233 /* mono = L */
233 234 lr1 = *(*src)++;
234 lr2 = *(*src)++; 235 lr1 = lr1 >> 16;
235 lr2 = (int16_t)lr2 + (lr2 >> 16) + err; 236 lr2 = *(*src)++;
236 err = lr2 & 1; 237 lr2 = lr2 >> 16;
237 lr2 >>= 1; 238 break;
238 *(*dst)++ = swap_odd_even_le32((lr1 << 16) | (uint16_t)lr2); 239 case 2:
240 /* mono = R */
241 lr1 = *(*src)++;
242 lr1 = (int16_t)lr1;
243 lr2 = *(*src)++;
244 lr2 = (int16_t)lr2;
245 break;
246 case 0:
247 default:
248 /* mono = (L+R)/2 */
249 lr1 = *(*src)++;
250 lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
251 err = lr1 & 1;
252 lr1 >>= 1;
253
254 lr2 = *(*src)++;
255 lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
256 err = lr2 & 1;
257 lr2 >>= 1;
258 break;
259 }
260 *(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
239} /* sample_to_mono */ 261} /* sample_to_mono */
240 262
241STATICIRAM void chunk_to_aiff_format(uint32_t *src, uint32_t *dst) ICODE_ATTR; 263STATICIRAM void chunk_to_aiff_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
@@ -316,6 +338,7 @@ static bool init_encoder(void)
316 338
317 sample_rate = inputs.sample_rate; 339 sample_rate = inputs.sample_rate;
318 num_channels = inputs.num_channels; 340 num_channels = inputs.num_channels;
341 rec_mono_mode = inputs.rec_mono_mode;
319 err = 0; 342 err = 0;
320 343
321 /* configure the buffer system */ 344 /* 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 {
90 int mean_bits; 90 int mean_bits;
91 int ResvSize; 91 int ResvSize;
92 int channels; 92 int channels;
93 int rec_mono_mode;
93 int granules; 94 int granules;
94 long samplerate; 95 long samplerate;
95} config_t; 96} config_t;
@@ -1972,12 +1973,14 @@ static int find_samplerate_index(long freq, int *mp3_type)
1972 1973
1973bool init_mp3_encoder_engine(int sample_rate, 1974bool init_mp3_encoder_engine(int sample_rate,
1974 int num_channels, 1975 int num_channels,
1976 int rec_mono_mode,
1975 struct encoder_config *enc_cfg) 1977 struct encoder_config *enc_cfg)
1976{ 1978{
1977 const bool stereo = num_channels > 1; 1979 const bool stereo = num_channels > 1;
1978 uint32_t avg_byte_per_frame; 1980 uint32_t avg_byte_per_frame;
1979 1981
1980 cfg.channels = stereo ? 2 : 1; 1982 cfg.channels = stereo ? 2 : 1;
1983 cfg.rec_mono_mode = rec_mono_mode;
1981 cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */ 1984 cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
1982 cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type); 1985 cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type);
1983 cfg.samplerate = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id]; 1986 cfg.samplerate = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id];
@@ -2093,9 +2096,26 @@ STATICIRAM void to_mono_mm(void)
2093 inline void to_mono(uint32_t **samp) 2096 inline void to_mono(uint32_t **samp)
2094 { 2097 {
2095 int32_t lr = **samp; 2098 int32_t lr = **samp;
2096 int32_t m = (int16_t)lr + (lr >> 16) + err; 2099 int32_t m;
2097 err = m & 1; 2100
2098 m >>= 1; 2101 switch(cfg.rec_mono_mode)
2102 {
2103 case 1:
2104 /* mono = L */
2105 m = lr >> 16;
2106 break;
2107 case 2:
2108 /* mono = R */
2109 m = (int16_t)lr;
2110 break;
2111 case 0:
2112 default:
2113 /* mono = (L+R)/2 */
2114 m = (int16_t)lr + (lr >> 16) + err;
2115 err = m & 1;
2116 m >>= 1;
2117 break;
2118 }
2099 *(*samp)++ = (m << 16) | (uint16_t)m; 2119 *(*samp)++ = (m << 16) | (uint16_t)m;
2100 } /* to_mono */ 2120 } /* to_mono */
2101 2121
@@ -2517,7 +2537,7 @@ static bool enc_init(void)
2517 return false; 2537 return false;
2518 2538
2519 init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels, 2539 init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels,
2520 inputs.config); 2540 inputs.rec_mono_mode, inputs.config);
2521 2541
2522 err = 0; 2542 err = 0;
2523 2543
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
60#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4) 60#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
61 61
62static int num_channels IBSS_ATTR; 62static int num_channels IBSS_ATTR;
63static int rec_mono_mode IBSS_ATTR;
63static uint32_t sample_rate; 64static uint32_t sample_rate;
64static uint32_t enc_size; 65static uint32_t enc_size;
65static int32_t err IBSS_ATTR; 66static int32_t err IBSS_ATTR;
@@ -215,15 +216,36 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
215{ 216{
216 int32_t lr1, lr2; 217 int32_t lr1, lr2;
217 218
218 lr1 = *(*src)++; 219 switch(rec_mono_mode)
219 lr1 = (int16_t)lr1 + (lr1 >> 16) + err; 220 {
220 err = lr1 & 1; 221 case 1:
221 lr1 >>= 1; 222 /* mono = L */
222 223 lr1 = *(*src)++;
223 lr2 = *(*src)++; 224 lr1 = lr1 >> 16;
224 lr2 = (int16_t)lr2 + (lr2 >> 16) + err; 225 lr2 = *(*src)++;
225 err = lr2 & 1; 226 lr2 = lr2 >> 16;
226 lr2 >>= 1; 227 break;
228 case 2:
229 /* mono = R */
230 lr1 = *(*src)++;
231 lr1 = (uint16_t)lr1;
232 lr2 = *(*src)++;
233 lr2 = (uint16_t)lr2;
234 break;
235 case 0:
236 default:
237 /* mono = (L+R)/2 */
238 lr1 = *(*src)++;
239 lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
240 err = lr1 & 1;
241 lr1 >>= 1;
242
243 lr2 = *(*src)++;
244 lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
245 err = lr2 & 1;
246 lr2 >>= 1;
247 break;
248 }
227 *(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2); 249 *(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
228} /* sample_to_mono */ 250} /* sample_to_mono */
229 251
@@ -305,6 +327,7 @@ static bool init_encoder(void)
305 327
306 sample_rate = inputs.sample_rate; 328 sample_rate = inputs.sample_rate;
307 num_channels = inputs.num_channels; 329 num_channels = inputs.num_channels;
330 rec_mono_mode = inputs.rec_mono_mode;
308 err = 0; 331 err = 0;
309 332
310 /* configure the buffer system */ 333 /* 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 @@
847 </voice> 847 </voice>
848</phrase> 848</phrase>
849<phrase> 849<phrase>
850 id: LANG_CHANNEL_LEFTRIGHT
851 desc: in sound_settings
852 user:
853 <source>
854 *: none
855 recording_swcodec: "Mono Left + Right"
856 </source>
857 <dest>
858 *: none
859 recording_swcodec: "Mono Left + Right"
860 </dest>
861 <voice>
862 *: none
863 recording_swcodec: "Mono Left plus Right"
864 </voice>
865</phrase>
866<phrase>
850 id: LANG_CHANNEL_KARAOKE 867 id: LANG_CHANNEL_KARAOKE
851 desc: in sound_settings 868 desc: in sound_settings
852 user: 869 user:
@@ -12061,3 +12078,20 @@
12061 albumart: "" 12078 albumart: ""
12062 </voice> 12079 </voice>
12063</phrase> 12080</phrase>
12081<phrase>
12082 id: LANG_RECORDING_MONO_MODE
12083 desc: in sound_settings
12084 user:
12085 <source>
12086 *: none
12087 recording_swcodec: "Mono mode"
12088 </source>
12089 <dest>
12090 *: none
12091 recording_swcodec: "Mono mode"
12092 </dest>
12093 <voice>
12094 *: none
12095 recording_swcodec: "Mono mode"
12096 </voice>
12097</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),
265 265
266#if CONFIG_CODEC == SWCODEC 266#if CONFIG_CODEC == SWCODEC
267 267
268static int recmonomode_func(void)
269{
270 static const struct opt_items names[3] = {
271 [0] = { STR(LANG_CHANNEL_LEFTRIGHT) },
272 [1] = { STR(LANG_CHANNEL_LEFT) },
273 [2] = { STR(LANG_CHANNEL_RIGHT) },
274 };
275
276 int rec_mono_mode = global_settings.rec_mono_mode;
277 bool ret = set_option(str(LANG_RECORDING_MONO_MODE), &rec_mono_mode,
278 INT, names, 3, NULL );
279
280 if (rec_mono_mode != global_settings.rec_mono_mode)
281 global_settings.rec_mono_mode = rec_mono_mode;
282
283 return ret;
284}
285MENUITEM_FUNCTION(recmonomode, 0, ID2P(LANG_RECORDING_MONO_MODE),
286 recmonomode_func, NULL, NULL, Icon_Menu_setting);
287
268static int recformat_func(void) 288static int recformat_func(void)
269{ 289{
270 static const struct opt_items names[REC_NUM_FORMATS] = { 290 static const struct opt_items names[REC_NUM_FORMATS] = {
@@ -608,6 +628,9 @@ MAKE_MENU(recording_settings_menu, ID2P(LANG_RECORDING_SETTINGS),
608#endif 628#endif
609 &recfrequency, &recsource, /* recsource not shown if no_source */ 629 &recfrequency, &recsource, /* recsource not shown if no_source */
610 &recchannels, 630 &recchannels,
631#if CONFIG_CODEC == SWCODEC
632 &recmonomode,
633#endif
611#if CONFIG_CODEC == MAS3587F 634#if CONFIG_CODEC == MAS3587F
612 &rec_editable, 635 &rec_editable,
613#endif 636#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)
628 options->rec_channels = global_settings.rec_channels; 628 options->rec_channels = global_settings.rec_channels;
629 options->rec_prerecord_time = global_settings.rec_prerecord_time; 629 options->rec_prerecord_time = global_settings.rec_prerecord_time;
630#if CONFIG_CODEC == SWCODEC 630#if CONFIG_CODEC == SWCODEC
631 options->rec_mono_mode = global_settings.rec_mono_mode;
631 options->rec_source_flags = 0; 632 options->rec_source_flags = 0;
632 options->enc_config.rec_format = global_settings.rec_format; 633 options->enc_config.rec_format = global_settings.rec_format;
633 global_to_encoder_config(&options->enc_config); 634 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
341 4 = 24kHz 341 4 = 24kHz
342 5 = 16kHz */ 342 5 = 16kHz */
343 int rec_channels; /* 0=Stereo, 1=Mono */ 343 int rec_channels; /* 0=Stereo, 1=Mono */
344#if CONFIG_CODEC == SWCODEC
345 int rec_mono_mode; /* how to create mono: L, R, L+R */
346#endif
344 int rec_mic_gain; /* depends on target */ 347 int rec_mic_gain; /* depends on target */
345 int rec_left_gain; /* depends on target */ 348 int rec_left_gain; /* depends on target */
346 int rec_right_gain; /* depands on target */ 349 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[] = {
866 TALK_ID(1792, UNIT_MB)), 866 TALK_ID(1792, UNIT_MB)),
867 {F_T_INT|F_RECSETTING, &global_settings.rec_channels, LANG_CHANNELS, INT(0), 867 {F_T_INT|F_RECSETTING, &global_settings.rec_channels, LANG_CHANNELS, INT(0),
868 "rec channels","stereo,mono",UNUSED}, 868 "rec channels","stereo,mono",UNUSED},
869#if CONFIG_CODEC == SWCODEC
870 {F_T_INT|F_RECSETTING, &global_settings.rec_mono_mode,
871 LANG_RECORDING_MONO_MODE, INT(0), "rec mono mode","L+R,L,R",UNUSED},
872#endif
869 CHOICE_SETTING(F_RECSETTING, rec_split_type, LANG_SPLIT_TYPE, 0, 873 CHOICE_SETTING(F_RECSETTING, rec_split_type, LANG_SPLIT_TYPE, 0,
870 "rec split type", "Split,Stop,Shutdown", NULL, 3, 874 "rec split type", "Split,Stop,Shutdown", NULL, 3,
871 ID2P(LANG_START_NEW_FILE), ID2P(LANG_STOP_RECORDING),ID2P(LANG_STOP_RECORDING_AND_SHUTDOWN)), 875 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
176 int rec_channels; 176 int rec_channels;
177 int rec_prerecord_time; 177 int rec_prerecord_time;
178#if CONFIG_CODEC == SWCODEC 178#if CONFIG_CODEC == SWCODEC
179 int rec_mono_mode;
179 int rec_source_flags; /* for rec_set_source */ 180 int rec_source_flags; /* for rec_set_source */
180 struct encoder_config enc_config; 181 struct encoder_config enc_config;
181#else 182#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
246{ 246{
247 unsigned long sample_rate; /* out - pcm frequency */ 247 unsigned long sample_rate; /* out - pcm frequency */
248 int num_channels; /* out - number of audio channels */ 248 int num_channels; /* out - number of audio channels */
249 int rec_mono_mode; /* out - how to create mono */
249 struct encoder_config *config; /* out - encoder settings */ 250 struct encoder_config *config; /* out - encoder settings */
250}; 251};
251 252
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 */
90static int rec_frequency; /* current frequency setting */ 90static int rec_frequency; /* current frequency setting */
91static unsigned long sample_rate; /* Sample rate in HZ */ 91static unsigned long sample_rate; /* Sample rate in HZ */
92static int num_channels; /* Current number of channels */ 92static int num_channels; /* Current number of channels */
93static int rec_mono_mode; /* how mono is created */
93static struct encoder_config enc_config; /* Current encoder configuration */ 94static struct encoder_config enc_config; /* Current encoder configuration */
94static unsigned long pre_record_ticks; /* pre-record time in ticks */ 95static unsigned long pre_record_ticks; /* pre-record time in ticks */
95 96
@@ -1178,6 +1179,7 @@ static void pcmrec_set_recording_options(
1178 rec_frequency = options->rec_frequency; 1179 rec_frequency = options->rec_frequency;
1179 rec_source = options->rec_source; 1180 rec_source = options->rec_source;
1180 num_channels = options->rec_channels == 1 ? 1 : 2; 1181 num_channels = options->rec_channels == 1 ? 1 : 2;
1182 rec_mono_mode = options->rec_mono_mode;
1181 pre_record_ticks = options->rec_prerecord_time * HZ; 1183 pre_record_ticks = options->rec_prerecord_time * HZ;
1182 enc_config = options->enc_config; 1184 enc_config = options->enc_config;
1183 enc_config.afmt = rec_format_afmt[enc_config.rec_format]; 1185 enc_config.afmt = rec_format_afmt[enc_config.rec_format];
@@ -1526,17 +1528,18 @@ void enc_get_inputs(struct enc_inputs *inputs)
1526{ 1528{
1527 inputs->sample_rate = sample_rate; 1529 inputs->sample_rate = sample_rate;
1528 inputs->num_channels = num_channels; 1530 inputs->num_channels = num_channels;
1531 inputs->rec_mono_mode = rec_mono_mode;
1529 inputs->config = &enc_config; 1532 inputs->config = &enc_config;
1530} /* enc_get_inputs */ 1533} /* enc_get_inputs */
1531 1534
1532/* set the encoder dimensions (called by encoder codec at initialization and 1535/* set the encoder dimensions (called by encoder codec at initialization and
1533 termination) */ 1536 termination) */
1534void enc_set_parameters(struct enc_parameters *params) 1537void enc_set_parameters(struct enc_parameters *params)
1535{ 1538{
1536 size_t bufsize, resbytes; 1539 size_t bufsize, resbytes;
1537 1540
1538 logf("enc_set_parameters"); 1541 logf("enc_set_parameters");
1539 1542
1540 if (!params) 1543 if (!params)
1541 { 1544 {
1542 logf("reset"); 1545 logf("reset");