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
diff --git a/apps/dsp.c b/apps/dsp.c
index 7aab8f5..7292328 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -137,8 +137,8 @@
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 @@
/** 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 @@
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 @@
#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 */
diff --git a/apps/dsp.h b/apps/dsp.h
index f87037d..092a99f 100644
--- a/apps/dsp.h
+++ b/apps/dsp.h
@@ -82,7 +82,7 @@
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
diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c
index 6031580..0ce860c 100644
--- a/apps/menus/sound_menu.c
+++ b/apps/menus/sound_menu.c
@@ -109,16 +109,16 @@
/* 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
diff --git a/apps/settings.c b/apps/settings.c
index f12bd92..2de4aa8 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -982,8 +982,8 @@
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
diff --git a/apps/settings.h b/apps/settings.h
index 6de8208..5dfcc7c 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -792,8 +792,8 @@
#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
diff --git a/apps/settings_list.c b/apps/settings_list.c
index d9ca889..c92772b 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -364,30 +364,12 @@
{
(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 @@
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,
diff --git a/manual/configure_rockbox/sound_settings.tex b/manual/configure_rockbox/sound_settings.tex
index 3e78dd6..53272af 100644
--- a/manual/configure_rockbox/sound_settings.tex
+++ b/manual/configure_rockbox/sound_settings.tex
@@ -445,18 +445,48 @@
}
\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.
}