Compressor: simplify makeup gain setting, expand release range, finally provide documention in the manual!

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23518 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jeffrey Goode 2009-11-04 18:14:36 +00:00
parent a06feaa7ec
commit 95e2d72759
7 changed files with 71 additions and 69 deletions

View file

@ -137,8 +137,8 @@ struct eq_state
struct compressor_menu
{
int threshold; /* dB - from menu */
bool auto_gain; /* 0 = off, 1 = auto */
int ratio; /* from menu */
int gain; /* dB - from menu */
bool soft_knee; /* 0 = hard knee, 1 = soft knee */
int release; /* samples - from menu */
};
@ -1542,11 +1542,12 @@ void dsp_set_replaygain(void)
/** SET COMPRESSOR
* Called by the menu system to configure the compressor process */
void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
int c_knee, int c_release)
{
bool changed = false;
bool active = (c_threshold < 0);
bool new_auto_gain = (c_gain == 1);
const int comp_ratio[] = {2, 4, 6, 10, 0};
int new_ratio = comp_ratio[c_ratio];
bool new_knee = (c_knee == 1);
@ -1560,32 +1561,22 @@ void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
c_menu.threshold, active ? "Yes" : "No");
}
if (c_menu.auto_gain != new_auto_gain)
{
changed = true;
c_menu.auto_gain = new_auto_gain;
logf(" Compressor Makeup Gain: %s",
c_menu.auto_gain ? "Auto" : "Off");
}
if (c_menu.ratio != new_ratio)
{
changed = true;
c_menu.ratio = new_ratio;
if (c_menu.ratio)
{
logf(" Compressor Ratio: %d:1", c_menu.ratio);
}
{ logf(" Compressor Ratio: %d:1", c_menu.ratio); }
else
{
logf(" Compressor Ratio: Limit");
}
}
if (c_menu.gain != c_gain)
{
changed = true;
c_menu.gain = c_gain;
if (c_menu.gain >= 0)
{
logf(" Compressor Makeup Gain: %d dB", c_menu.gain);
}
else
{
logf(" Compressor Makeup Gain: Auto");
}
{ logf(" Compressor Ratio: Limit"); }
}
if (c_menu.soft_knee != new_knee)
@ -1731,9 +1722,8 @@ void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
#endif
/* if using auto peak, then makeup gain is max offset - .1dB headroom */
int32_t db_makeup = (c_menu.gain == -1) ?
-(db_curve[3].offset) - 0x199A : c_menu.gain << 16;
comp_makeup_gain = fp_factor(db_makeup, 16) << 8;
comp_makeup_gain = c_menu.auto_gain ?
fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
/* calculate per-sample gain change a rate of 10db over release time */

View file

@ -82,7 +82,7 @@ int32_t sound_get_pitch(void);
void dsp_set_timestretch(int32_t percent);
int32_t dsp_get_timestretch(void);
int dsp_callback(int msg, intptr_t param);
void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
int c_knee, int c_release);
#endif

View file

@ -109,16 +109,16 @@ static int timestretch_callback(int action,const struct menu_item_ex *this_item)
/* compressor submenu */
MENUITEM_SETTING(compressor_threshold,
&global_settings.compressor_threshold, lowlatency_callback);
MENUITEM_SETTING(compressor_ratio,
&global_settings.compressor_ratio, lowlatency_callback);
MENUITEM_SETTING(compressor_gain,
&global_settings.compressor_makeup_gain, lowlatency_callback);
MENUITEM_SETTING(compressor_ratio,
&global_settings.compressor_ratio, lowlatency_callback);
MENUITEM_SETTING(compressor_knee,
&global_settings.compressor_knee, lowlatency_callback);
MENUITEM_SETTING(compressor_release,
&global_settings.compressor_release_time, lowlatency_callback);
MAKE_MENU(compressor_menu,ID2P(LANG_COMPRESSOR), NULL, Icon_NOICON,
&compressor_threshold, &compressor_ratio, &compressor_gain,
&compressor_threshold, &compressor_gain, &compressor_ratio,
&compressor_knee, &compressor_release);
#endif

View file

@ -982,8 +982,8 @@ void settings_apply(bool read_disk)
dsp_dither_enable(global_settings.dithering_enabled);
dsp_timestretch_enable(global_settings.timestretch_enabled);
dsp_set_compressor(global_settings.compressor_threshold,
global_settings.compressor_ratio,
global_settings.compressor_makeup_gain,
global_settings.compressor_ratio,
global_settings.compressor_knee,
global_settings.compressor_release_time);
#endif

View file

@ -792,8 +792,8 @@ struct user_settings
#if CONFIG_CODEC == SWCODEC
int compressor_threshold;
int compressor_ratio;
int compressor_makeup_gain;
int compressor_ratio;
int compressor_knee;
int compressor_release_time;
#endif

View file

@ -364,30 +364,12 @@ static void compressor_set(int val)
{
(void)val;
dsp_set_compressor(global_settings.compressor_threshold,
global_settings.compressor_ratio,
global_settings.compressor_makeup_gain,
global_settings.compressor_ratio,
global_settings.compressor_knee,
global_settings.compressor_release_time);
}
static const char* auto_formatter(char *buffer, size_t buffer_size,
int val, const char *unit)
{
if (val == -1)
return str(LANG_AUTO);
else
snprintf(buffer, buffer_size, "%d %s", val, unit);
return buffer;
}
static int32_t auto_getlang(int value, int unit)
{
if (value == -1)
return LANG_AUTO;
else
return TALK_ID(value, unit);
}
static const char* db_format(char* buffer, size_t buffer_size, int value,
const char* unit)
{
@ -1293,24 +1275,24 @@ const struct settings_list settings[] = {
LANG_COMPRESSOR_THRESHOLD, 0,
"compressor threshold", UNIT_DB, 0, -24,
-3, formatter_unit_0_is_off, getlang_unit_0_is_off, compressor_set),
CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_makeup_gain,
LANG_COMPRESSOR_GAIN, 1, "compressor makeup gain",
"off,auto", compressor_set, 2,
ID2P(LANG_OFF), ID2P(LANG_AUTO)),
CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_ratio,
LANG_COMPRESSOR_RATIO, 1, "compressor ratio",
"2:1,4:1,6:1,10:1,limit", compressor_set, 5,
ID2P(LANG_COMPRESSOR_RATIO_2), ID2P(LANG_COMPRESSOR_RATIO_4),
ID2P(LANG_COMPRESSOR_RATIO_6), ID2P(LANG_COMPRESSOR_RATIO_10),
ID2P(LANG_COMPRESSOR_RATIO_LIMIT)),
INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_makeup_gain,
LANG_COMPRESSOR_GAIN, -1,
"compressor makeup gain", UNIT_DB, -1, 20,
1, auto_formatter, auto_getlang, compressor_set),
CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_knee,
LANG_COMPRESSOR_KNEE, 1, "compressor knee",
"hard knee,soft knee", compressor_set, 2,
ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)),
INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_release_time,
LANG_COMPRESSOR_RELEASE, 100,
"compressor release time", UNIT_MS, 20, 200,
10, NULL, NULL, compressor_set),
LANG_COMPRESSOR_RELEASE, 500,
"compressor release time", UNIT_MS, 100, 1000,
100, NULL, NULL, compressor_set),
#endif
#ifdef HAVE_WM8758
SOUND_SETTING(F_NO_WRAP, bass_cutoff, LANG_BASS_CUTOFF,

View file

@ -445,18 +445,48 @@ experience with more complex audio.
}
\opt{swcodec}{
\section{Limiter Preamp}
The limiter preamp raises the gain of the audio by the selected amount. The associated
limiter function works on the resulting louder signal to reduce any peaks to below the
maximum level. The default selection of 0dB turns all limiter processing off.
\section{Compressor}
The \setting{Compressor} reduces, or compresses, the dynamic range of the audio
signal. This makes the quieter and louder sections closer to the same volume
level by progressively reducing the gain of louder signals. When subsequently
amplified, this has the effect of making the quieter sections louder while
keeping the louder sections from clipping. This allows listening to the quiet
sections of dynamic material in noisy environments while preventing sudden loud
sections from being overbearing.
The limiter has the effect of reducing dynamic range by amplifying quiet sections while
loud sections are kept just under maximum gain. This allows listening to the quiet sections
of dynamic material in noisy environments while preventing sudden loud sections from being
overbearing.
There are several settings associated with the compressor. The first, and most
important, is the \setting{Threshold}. The threshold is the audio input level
at which the compressor begins to act. Any level louder than the threshold
will be compressed to some extent. The maximum amount of compression, or the
quietest level at which the compressor will operate, is -24db. The default of
Off disables the compressor.
Think of this as a smart volume control. The preamp in effect turns up the volume by the
amount you select so that you can hear quiet passages. But it senses when a loud section is
about to play and quickly and smoothly lowers the volume as necessary to keep the audio
under the maximum limit. As the loud section fades, the volume is turned back up.
The \setting{Makeup Gain} setting has two options: Off and Auto. Off means
that the compressed audio will not be amplified after compression. The default
of Auto will amplify the signal so that the loudest possible signal after
compression will be just under the clipping limit. This is desirable because
the compressed signal without makeup gain is quieter than the input signal.
Makeup Gain in Auto restores the signal to the maximum possible level and
brings the quieter audio up with it. This is what makes it possible to hear
the quieter audio in noisy environments.
The \setting{Ratio} setting determines how aggressively the compressor reduces
gain above the threshold. For example, the 2:1 setting means that for each
two decibels of input signal above the threshold, the compressor will only
allow the output to appear as one decibel. The higher the ratio, the harder
the signal is compressed. The ratio setting of Limit means essentially a ratio
of infinity to one. In this case, the output signal is not allowed to exceed
the threshold at all.
The \setting{Knee} setting determines how abrupt the transition is from a
non-compressed signal to a compressed signal. Hard Knee means that the
transition occurs precisely at the threshold. The Soft Knee setting smoothes
the transition from plus or minus three decibels around the threshold.
The \setting{Release Time} setting sets the recovery time after the signal is
compressed. Once the compressor determines that compression is necessary,
the input signal is reduced appropriately, but the gain isn't allowed to
immediately return to normal levels. This is necessary to reduce artifacts
such as "pumping." Instead, the gain is allowed to return to normal at the
chosen rate. Release Time is the time for the gain to recover by 10dB.
}