mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
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:
parent
a06feaa7ec
commit
95e2d72759
7 changed files with 71 additions and 69 deletions
40
apps/dsp.c
40
apps/dsp.c
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue