mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 05:05:20 -05:00
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
This commit is contained in:
parent
cb1173cedd
commit
528fe442fc
11 changed files with 160 additions and 24 deletions
|
|
@ -72,6 +72,7 @@ struct aiff_header aiff_header =
|
||||||
/* (*) updated when finalizing file */
|
/* (*) updated when finalizing file */
|
||||||
|
|
||||||
static int num_channels IBSS_ATTR;
|
static int num_channels IBSS_ATTR;
|
||||||
|
static int rec_mono_mode IBSS_ATTR;
|
||||||
static uint32_t sample_rate;
|
static uint32_t sample_rate;
|
||||||
static uint32_t enc_size;
|
static uint32_t enc_size;
|
||||||
static int32_t err IBSS_ATTR;
|
static int32_t err IBSS_ATTR;
|
||||||
|
|
@ -226,6 +227,25 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
|
||||||
{
|
{
|
||||||
int32_t lr1, lr2;
|
int32_t lr1, 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 = *(*src)++;
|
||||||
lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
|
lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
|
||||||
err = lr1 & 1;
|
err = lr1 & 1;
|
||||||
|
|
@ -235,7 +255,9 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
|
||||||
lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
|
lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
|
||||||
err = lr2 & 1;
|
err = lr2 & 1;
|
||||||
lr2 >>= 1;
|
lr2 >>= 1;
|
||||||
*(*dst)++ = swap_odd_even_le32((lr1 << 16) | (uint16_t)lr2);
|
break;
|
||||||
|
}
|
||||||
|
*(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
|
||||||
} /* sample_to_mono */
|
} /* sample_to_mono */
|
||||||
|
|
||||||
STATICIRAM void chunk_to_aiff_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
|
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;
|
sample_rate = inputs.sample_rate;
|
||||||
num_channels = inputs.num_channels;
|
num_channels = inputs.num_channels;
|
||||||
|
rec_mono_mode = inputs.rec_mono_mode;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
/* configure the buffer system */
|
/* configure the buffer system */
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ typedef struct {
|
||||||
int mean_bits;
|
int mean_bits;
|
||||||
int ResvSize;
|
int ResvSize;
|
||||||
int channels;
|
int channels;
|
||||||
|
int rec_mono_mode;
|
||||||
int granules;
|
int granules;
|
||||||
long samplerate;
|
long samplerate;
|
||||||
} config_t;
|
} config_t;
|
||||||
|
|
@ -1972,12 +1973,14 @@ static int find_samplerate_index(long freq, int *mp3_type)
|
||||||
|
|
||||||
bool init_mp3_encoder_engine(int sample_rate,
|
bool init_mp3_encoder_engine(int sample_rate,
|
||||||
int num_channels,
|
int num_channels,
|
||||||
|
int rec_mono_mode,
|
||||||
struct encoder_config *enc_cfg)
|
struct encoder_config *enc_cfg)
|
||||||
{
|
{
|
||||||
const bool stereo = num_channels > 1;
|
const bool stereo = num_channels > 1;
|
||||||
uint32_t avg_byte_per_frame;
|
uint32_t avg_byte_per_frame;
|
||||||
|
|
||||||
cfg.channels = stereo ? 2 : 1;
|
cfg.channels = stereo ? 2 : 1;
|
||||||
|
cfg.rec_mono_mode = rec_mono_mode;
|
||||||
cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
|
cfg.mpg.mode = stereo ? 0 : 3; /* 0=stereo, 3=mono */
|
||||||
cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type);
|
cfg.mpg.smpl_id = find_samplerate_index(sample_rate, &cfg.mpg.type);
|
||||||
cfg.samplerate = sampr_index[cfg.mpg.type][cfg.mpg.smpl_id];
|
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)
|
inline void to_mono(uint32_t **samp)
|
||||||
{
|
{
|
||||||
int32_t lr = **samp;
|
int32_t lr = **samp;
|
||||||
int32_t m = (int16_t)lr + (lr >> 16) + err;
|
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;
|
err = m & 1;
|
||||||
m >>= 1;
|
m >>= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*(*samp)++ = (m << 16) | (uint16_t)m;
|
*(*samp)++ = (m << 16) | (uint16_t)m;
|
||||||
} /* to_mono */
|
} /* to_mono */
|
||||||
|
|
||||||
|
|
@ -2517,7 +2537,7 @@ static bool enc_init(void)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels,
|
init_mp3_encoder_engine(inputs.sample_rate, inputs.num_channels,
|
||||||
inputs.config);
|
inputs.rec_mono_mode, inputs.config);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,7 @@ struct riff_header
|
||||||
#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
|
#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
|
||||||
|
|
||||||
static int num_channels IBSS_ATTR;
|
static int num_channels IBSS_ATTR;
|
||||||
|
static int rec_mono_mode IBSS_ATTR;
|
||||||
static uint32_t sample_rate;
|
static uint32_t sample_rate;
|
||||||
static uint32_t enc_size;
|
static uint32_t enc_size;
|
||||||
static int32_t err IBSS_ATTR;
|
static int32_t err IBSS_ATTR;
|
||||||
|
|
@ -215,6 +216,25 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
|
||||||
{
|
{
|
||||||
int32_t lr1, lr2;
|
int32_t lr1, 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 = (uint16_t)lr1;
|
||||||
|
lr2 = *(*src)++;
|
||||||
|
lr2 = (uint16_t)lr2;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
/* mono = (L+R)/2 */
|
||||||
lr1 = *(*src)++;
|
lr1 = *(*src)++;
|
||||||
lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
|
lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
|
||||||
err = lr1 & 1;
|
err = lr1 & 1;
|
||||||
|
|
@ -224,6 +244,8 @@ static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
|
||||||
lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
|
lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
|
||||||
err = lr2 & 1;
|
err = lr2 & 1;
|
||||||
lr2 >>= 1;
|
lr2 >>= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
|
*(*dst)++ = swap_odd_even_be32((lr1 << 16) | (uint16_t)lr2);
|
||||||
} /* sample_to_mono */
|
} /* sample_to_mono */
|
||||||
|
|
||||||
|
|
@ -305,6 +327,7 @@ static bool init_encoder(void)
|
||||||
|
|
||||||
sample_rate = inputs.sample_rate;
|
sample_rate = inputs.sample_rate;
|
||||||
num_channels = inputs.num_channels;
|
num_channels = inputs.num_channels;
|
||||||
|
rec_mono_mode = inputs.rec_mono_mode;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
|
||||||
/* configure the buffer system */
|
/* configure the buffer system */
|
||||||
|
|
|
||||||
|
|
@ -846,6 +846,23 @@
|
||||||
*: "Mono Right"
|
*: "Mono Right"
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</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>
|
<phrase>
|
||||||
id: LANG_CHANNEL_KARAOKE
|
id: LANG_CHANNEL_KARAOKE
|
||||||
desc: in sound_settings
|
desc: in sound_settings
|
||||||
|
|
@ -12061,3 +12078,20 @@
|
||||||
albumart: ""
|
albumart: ""
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</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>
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,26 @@ MENUITEM_FUNCTION(recchannels, 0, ID2P(LANG_CHANNELS),
|
||||||
|
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#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 int recformat_func(void)
|
||||||
{
|
{
|
||||||
static const struct opt_items names[REC_NUM_FORMATS] = {
|
static const struct opt_items names[REC_NUM_FORMATS] = {
|
||||||
|
|
@ -608,6 +628,9 @@ MAKE_MENU(recording_settings_menu, ID2P(LANG_RECORDING_SETTINGS),
|
||||||
#endif
|
#endif
|
||||||
&recfrequency, &recsource, /* recsource not shown if no_source */
|
&recfrequency, &recsource, /* recsource not shown if no_source */
|
||||||
&recchannels,
|
&recchannels,
|
||||||
|
#if CONFIG_CODEC == SWCODEC
|
||||||
|
&recmonomode,
|
||||||
|
#endif
|
||||||
#if CONFIG_CODEC == MAS3587F
|
#if CONFIG_CODEC == MAS3587F
|
||||||
&rec_editable,
|
&rec_editable,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -628,6 +628,7 @@ void rec_init_recording_options(struct audio_recording_options *options)
|
||||||
options->rec_channels = global_settings.rec_channels;
|
options->rec_channels = global_settings.rec_channels;
|
||||||
options->rec_prerecord_time = global_settings.rec_prerecord_time;
|
options->rec_prerecord_time = global_settings.rec_prerecord_time;
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#if CONFIG_CODEC == SWCODEC
|
||||||
|
options->rec_mono_mode = global_settings.rec_mono_mode;
|
||||||
options->rec_source_flags = 0;
|
options->rec_source_flags = 0;
|
||||||
options->enc_config.rec_format = global_settings.rec_format;
|
options->enc_config.rec_format = global_settings.rec_format;
|
||||||
global_to_encoder_config(&options->enc_config);
|
global_to_encoder_config(&options->enc_config);
|
||||||
|
|
|
||||||
|
|
@ -341,6 +341,9 @@ struct user_settings
|
||||||
4 = 24kHz
|
4 = 24kHz
|
||||||
5 = 16kHz */
|
5 = 16kHz */
|
||||||
int rec_channels; /* 0=Stereo, 1=Mono */
|
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_mic_gain; /* depends on target */
|
||||||
int rec_left_gain; /* depends on target */
|
int rec_left_gain; /* depends on target */
|
||||||
int rec_right_gain; /* depands on target */
|
int rec_right_gain; /* depands on target */
|
||||||
|
|
|
||||||
|
|
@ -866,6 +866,10 @@ const struct settings_list settings[] = {
|
||||||
TALK_ID(1792, UNIT_MB)),
|
TALK_ID(1792, UNIT_MB)),
|
||||||
{F_T_INT|F_RECSETTING, &global_settings.rec_channels, LANG_CHANNELS, INT(0),
|
{F_T_INT|F_RECSETTING, &global_settings.rec_channels, LANG_CHANNELS, INT(0),
|
||||||
"rec channels","stereo,mono",UNUSED},
|
"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,
|
CHOICE_SETTING(F_RECSETTING, rec_split_type, LANG_SPLIT_TYPE, 0,
|
||||||
"rec split type", "Split,Stop,Shutdown", NULL, 3,
|
"rec split type", "Split,Stop,Shutdown", NULL, 3,
|
||||||
ID2P(LANG_START_NEW_FILE), ID2P(LANG_STOP_RECORDING),ID2P(LANG_STOP_RECORDING_AND_SHUTDOWN)),
|
ID2P(LANG_START_NEW_FILE), ID2P(LANG_STOP_RECORDING),ID2P(LANG_STOP_RECORDING_AND_SHUTDOWN)),
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ struct audio_recording_options
|
||||||
int rec_channels;
|
int rec_channels;
|
||||||
int rec_prerecord_time;
|
int rec_prerecord_time;
|
||||||
#if CONFIG_CODEC == SWCODEC
|
#if CONFIG_CODEC == SWCODEC
|
||||||
|
int rec_mono_mode;
|
||||||
int rec_source_flags; /* for rec_set_source */
|
int rec_source_flags; /* for rec_set_source */
|
||||||
struct encoder_config enc_config;
|
struct encoder_config enc_config;
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,7 @@ struct enc_inputs
|
||||||
{
|
{
|
||||||
unsigned long sample_rate; /* out - pcm frequency */
|
unsigned long sample_rate; /* out - pcm frequency */
|
||||||
int num_channels; /* out - number of audio channels */
|
int num_channels; /* out - number of audio channels */
|
||||||
|
int rec_mono_mode; /* out - how to create mono */
|
||||||
struct encoder_config *config; /* out - encoder settings */
|
struct encoder_config *config; /* out - encoder settings */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,7 @@ static int rec_source; /* current rec_source setting */
|
||||||
static int rec_frequency; /* current frequency setting */
|
static int rec_frequency; /* current frequency setting */
|
||||||
static unsigned long sample_rate; /* Sample rate in HZ */
|
static unsigned long sample_rate; /* Sample rate in HZ */
|
||||||
static int num_channels; /* Current number of channels */
|
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 struct encoder_config enc_config; /* Current encoder configuration */
|
||||||
static unsigned long pre_record_ticks; /* pre-record time in ticks */
|
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_frequency = options->rec_frequency;
|
||||||
rec_source = options->rec_source;
|
rec_source = options->rec_source;
|
||||||
num_channels = options->rec_channels == 1 ? 1 : 2;
|
num_channels = options->rec_channels == 1 ? 1 : 2;
|
||||||
|
rec_mono_mode = options->rec_mono_mode;
|
||||||
pre_record_ticks = options->rec_prerecord_time * HZ;
|
pre_record_ticks = options->rec_prerecord_time * HZ;
|
||||||
enc_config = options->enc_config;
|
enc_config = options->enc_config;
|
||||||
enc_config.afmt = rec_format_afmt[enc_config.rec_format];
|
enc_config.afmt = rec_format_afmt[enc_config.rec_format];
|
||||||
|
|
@ -1526,6 +1528,7 @@ void enc_get_inputs(struct enc_inputs *inputs)
|
||||||
{
|
{
|
||||||
inputs->sample_rate = sample_rate;
|
inputs->sample_rate = sample_rate;
|
||||||
inputs->num_channels = num_channels;
|
inputs->num_channels = num_channels;
|
||||||
|
inputs->rec_mono_mode = rec_mono_mode;
|
||||||
inputs->config = &enc_config;
|
inputs->config = &enc_config;
|
||||||
} /* enc_get_inputs */
|
} /* enc_get_inputs */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue