summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeffrey Goode <jeffg7@gmail.com>2009-11-04 18:14:36 +0000
committerJeffrey Goode <jeffg7@gmail.com>2009-11-04 18:14:36 +0000
commit95e2d72759543b739a8faba7545fe6d9752fb4ef (patch)
treef8afc86797e83fd4556ec17e857d4caa097d3bb9
parenta06feaa7ecb010e6a6d85f49e6392f06f9f814a2 (diff)
downloadrockbox-95e2d72759543b739a8faba7545fe6d9752fb4ef.tar.gz
rockbox-95e2d72759543b739a8faba7545fe6d9752fb4ef.zip
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
-rw-r--r--apps/dsp.c38
-rw-r--r--apps/dsp.h2
-rw-r--r--apps/menus/sound_menu.c6
-rw-r--r--apps/settings.c2
-rw-r--r--apps/settings.h2
-rw-r--r--apps/settings_list.c34
-rw-r--r--manual/configure_rockbox/sound_settings.tex58
7 files changed, 72 insertions, 70 deletions
diff --git a/apps/dsp.c b/apps/dsp.c
index 7aab8f5c37..7292328212 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -137,8 +137,8 @@ struct eq_state
137struct compressor_menu 137struct compressor_menu
138{ 138{
139 int threshold; /* dB - from menu */ 139 int threshold; /* dB - from menu */
140 bool auto_gain; /* 0 = off, 1 = auto */
140 int ratio; /* from menu */ 141 int ratio; /* from menu */
141 int gain; /* dB - from menu */
142 bool soft_knee; /* 0 = hard knee, 1 = soft knee */ 142 bool soft_knee; /* 0 = hard knee, 1 = soft knee */
143 int release; /* samples - from menu */ 143 int release; /* samples - from menu */
144}; 144};
@@ -1542,11 +1542,12 @@ void dsp_set_replaygain(void)
1542 1542
1543/** SET COMPRESSOR 1543/** SET COMPRESSOR
1544 * Called by the menu system to configure the compressor process */ 1544 * Called by the menu system to configure the compressor process */
1545void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain, 1545void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
1546 int c_knee, int c_release) 1546 int c_knee, int c_release)
1547{ 1547{
1548 bool changed = false; 1548 bool changed = false;
1549 bool active = (c_threshold < 0); 1549 bool active = (c_threshold < 0);
1550 bool new_auto_gain = (c_gain == 1);
1550 const int comp_ratio[] = {2, 4, 6, 10, 0}; 1551 const int comp_ratio[] = {2, 4, 6, 10, 0};
1551 int new_ratio = comp_ratio[c_ratio]; 1552 int new_ratio = comp_ratio[c_ratio];
1552 bool new_knee = (c_knee == 1); 1553 bool new_knee = (c_knee == 1);
@@ -1560,32 +1561,22 @@ void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
1560 c_menu.threshold, active ? "Yes" : "No"); 1561 c_menu.threshold, active ? "Yes" : "No");
1561 } 1562 }
1562 1563
1563 if (c_menu.ratio != new_ratio) 1564 if (c_menu.auto_gain != new_auto_gain)
1564 { 1565 {
1565 changed = true; 1566 changed = true;
1566 c_menu.ratio = new_ratio; 1567 c_menu.auto_gain = new_auto_gain;
1567 if (c_menu.ratio) 1568 logf(" Compressor Makeup Gain: %s",
1568 { 1569 c_menu.auto_gain ? "Auto" : "Off");
1569 logf(" Compressor Ratio: %d:1", c_menu.ratio);
1570 }
1571 else
1572 {
1573 logf(" Compressor Ratio: Limit");
1574 }
1575 } 1570 }
1576 1571
1577 if (c_menu.gain != c_gain) 1572 if (c_menu.ratio != new_ratio)
1578 { 1573 {
1579 changed = true; 1574 changed = true;
1580 c_menu.gain = c_gain; 1575 c_menu.ratio = new_ratio;
1581 if (c_menu.gain >= 0) 1576 if (c_menu.ratio)
1582 { 1577 { logf(" Compressor Ratio: %d:1", c_menu.ratio); }
1583 logf(" Compressor Makeup Gain: %d dB", c_menu.gain);
1584 }
1585 else 1578 else
1586 { 1579 { logf(" Compressor Ratio: Limit"); }
1587 logf(" Compressor Makeup Gain: Auto");
1588 }
1589 } 1580 }
1590 1581
1591 if (c_menu.soft_knee != new_knee) 1582 if (c_menu.soft_knee != new_knee)
@@ -1731,9 +1722,8 @@ void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
1731#endif 1722#endif
1732 1723
1733 /* if using auto peak, then makeup gain is max offset - .1dB headroom */ 1724 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1734 int32_t db_makeup = (c_menu.gain == -1) ? 1725 comp_makeup_gain = c_menu.auto_gain ?
1735 -(db_curve[3].offset) - 0x199A : c_menu.gain << 16; 1726 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1736 comp_makeup_gain = fp_factor(db_makeup, 16) << 8;
1737 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY); 1727 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1738 1728
1739 /* calculate per-sample gain change a rate of 10db over release time */ 1729 /* calculate per-sample gain change a rate of 10db over release time */
diff --git a/apps/dsp.h b/apps/dsp.h
index f87037d368..092a99f052 100644
--- a/apps/dsp.h
+++ b/apps/dsp.h
@@ -82,7 +82,7 @@ int32_t sound_get_pitch(void);
82void dsp_set_timestretch(int32_t percent); 82void dsp_set_timestretch(int32_t percent);
83int32_t dsp_get_timestretch(void); 83int32_t dsp_get_timestretch(void);
84int dsp_callback(int msg, intptr_t param); 84int dsp_callback(int msg, intptr_t param);
85void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain, 85void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
86 int c_knee, int c_release); 86 int c_knee, int c_release);
87 87
88#endif 88#endif
diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c
index 60315804a9..0ce860cb7c 100644
--- a/apps/menus/sound_menu.c
+++ b/apps/menus/sound_menu.c
@@ -109,16 +109,16 @@ static int timestretch_callback(int action,const struct menu_item_ex *this_item)
109 /* compressor submenu */ 109 /* compressor submenu */
110 MENUITEM_SETTING(compressor_threshold, 110 MENUITEM_SETTING(compressor_threshold,
111 &global_settings.compressor_threshold, lowlatency_callback); 111 &global_settings.compressor_threshold, lowlatency_callback);
112 MENUITEM_SETTING(compressor_ratio,
113 &global_settings.compressor_ratio, lowlatency_callback);
114 MENUITEM_SETTING(compressor_gain, 112 MENUITEM_SETTING(compressor_gain,
115 &global_settings.compressor_makeup_gain, lowlatency_callback); 113 &global_settings.compressor_makeup_gain, lowlatency_callback);
114 MENUITEM_SETTING(compressor_ratio,
115 &global_settings.compressor_ratio, lowlatency_callback);
116 MENUITEM_SETTING(compressor_knee, 116 MENUITEM_SETTING(compressor_knee,
117 &global_settings.compressor_knee, lowlatency_callback); 117 &global_settings.compressor_knee, lowlatency_callback);
118 MENUITEM_SETTING(compressor_release, 118 MENUITEM_SETTING(compressor_release,
119 &global_settings.compressor_release_time, lowlatency_callback); 119 &global_settings.compressor_release_time, lowlatency_callback);
120 MAKE_MENU(compressor_menu,ID2P(LANG_COMPRESSOR), NULL, Icon_NOICON, 120 MAKE_MENU(compressor_menu,ID2P(LANG_COMPRESSOR), NULL, Icon_NOICON,
121 &compressor_threshold, &compressor_ratio, &compressor_gain, 121 &compressor_threshold, &compressor_gain, &compressor_ratio,
122 &compressor_knee, &compressor_release); 122 &compressor_knee, &compressor_release);
123#endif 123#endif
124 124
diff --git a/apps/settings.c b/apps/settings.c
index f12bd92bfd..2de4aa8c71 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -982,8 +982,8 @@ void settings_apply(bool read_disk)
982 dsp_dither_enable(global_settings.dithering_enabled); 982 dsp_dither_enable(global_settings.dithering_enabled);
983 dsp_timestretch_enable(global_settings.timestretch_enabled); 983 dsp_timestretch_enable(global_settings.timestretch_enabled);
984 dsp_set_compressor(global_settings.compressor_threshold, 984 dsp_set_compressor(global_settings.compressor_threshold,
985 global_settings.compressor_ratio,
986 global_settings.compressor_makeup_gain, 985 global_settings.compressor_makeup_gain,
986 global_settings.compressor_ratio,
987 global_settings.compressor_knee, 987 global_settings.compressor_knee,
988 global_settings.compressor_release_time); 988 global_settings.compressor_release_time);
989#endif 989#endif
diff --git a/apps/settings.h b/apps/settings.h
index 6de820807f..5dfcc7cb14 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -792,8 +792,8 @@ struct user_settings
792 792
793#if CONFIG_CODEC == SWCODEC 793#if CONFIG_CODEC == SWCODEC
794 int compressor_threshold; 794 int compressor_threshold;
795 int compressor_ratio;
796 int compressor_makeup_gain; 795 int compressor_makeup_gain;
796 int compressor_ratio;
797 int compressor_knee; 797 int compressor_knee;
798 int compressor_release_time; 798 int compressor_release_time;
799#endif 799#endif
diff --git a/apps/settings_list.c b/apps/settings_list.c
index d9ca889458..c92772beb9 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -364,30 +364,12 @@ static void compressor_set(int val)
364{ 364{
365 (void)val; 365 (void)val;
366 dsp_set_compressor(global_settings.compressor_threshold, 366 dsp_set_compressor(global_settings.compressor_threshold,
367 global_settings.compressor_ratio,
368 global_settings.compressor_makeup_gain, 367 global_settings.compressor_makeup_gain,
368 global_settings.compressor_ratio,
369 global_settings.compressor_knee, 369 global_settings.compressor_knee,
370 global_settings.compressor_release_time); 370 global_settings.compressor_release_time);
371} 371}
372 372
373static const char* auto_formatter(char *buffer, size_t buffer_size,
374 int val, const char *unit)
375{
376 if (val == -1)
377 return str(LANG_AUTO);
378 else
379 snprintf(buffer, buffer_size, "%d %s", val, unit);
380 return buffer;
381}
382
383static int32_t auto_getlang(int value, int unit)
384{
385 if (value == -1)
386 return LANG_AUTO;
387 else
388 return TALK_ID(value, unit);
389}
390
391static const char* db_format(char* buffer, size_t buffer_size, int value, 373static const char* db_format(char* buffer, size_t buffer_size, int value,
392 const char* unit) 374 const char* unit)
393{ 375{
@@ -1293,24 +1275,24 @@ const struct settings_list settings[] = {
1293 LANG_COMPRESSOR_THRESHOLD, 0, 1275 LANG_COMPRESSOR_THRESHOLD, 0,
1294 "compressor threshold", UNIT_DB, 0, -24, 1276 "compressor threshold", UNIT_DB, 0, -24,
1295 -3, formatter_unit_0_is_off, getlang_unit_0_is_off, compressor_set), 1277 -3, formatter_unit_0_is_off, getlang_unit_0_is_off, compressor_set),
1278 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_makeup_gain,
1279 LANG_COMPRESSOR_GAIN, 1, "compressor makeup gain",
1280 "off,auto", compressor_set, 2,
1281 ID2P(LANG_OFF), ID2P(LANG_AUTO)),
1296 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_ratio, 1282 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_ratio,
1297 LANG_COMPRESSOR_RATIO, 1, "compressor ratio", 1283 LANG_COMPRESSOR_RATIO, 1, "compressor ratio",
1298 "2:1,4:1,6:1,10:1,limit", compressor_set, 5, 1284 "2:1,4:1,6:1,10:1,limit", compressor_set, 5,
1299 ID2P(LANG_COMPRESSOR_RATIO_2), ID2P(LANG_COMPRESSOR_RATIO_4), 1285 ID2P(LANG_COMPRESSOR_RATIO_2), ID2P(LANG_COMPRESSOR_RATIO_4),
1300 ID2P(LANG_COMPRESSOR_RATIO_6), ID2P(LANG_COMPRESSOR_RATIO_10), 1286 ID2P(LANG_COMPRESSOR_RATIO_6), ID2P(LANG_COMPRESSOR_RATIO_10),
1301 ID2P(LANG_COMPRESSOR_RATIO_LIMIT)), 1287 ID2P(LANG_COMPRESSOR_RATIO_LIMIT)),
1302 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_makeup_gain,
1303 LANG_COMPRESSOR_GAIN, -1,
1304 "compressor makeup gain", UNIT_DB, -1, 20,
1305 1, auto_formatter, auto_getlang, compressor_set),
1306 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_knee, 1288 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_knee,
1307 LANG_COMPRESSOR_KNEE, 1, "compressor knee", 1289 LANG_COMPRESSOR_KNEE, 1, "compressor knee",
1308 "hard knee,soft knee", compressor_set, 2, 1290 "hard knee,soft knee", compressor_set, 2,
1309 ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)), 1291 ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)),
1310 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_release_time, 1292 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_release_time,
1311 LANG_COMPRESSOR_RELEASE, 100, 1293 LANG_COMPRESSOR_RELEASE, 500,
1312 "compressor release time", UNIT_MS, 20, 200, 1294 "compressor release time", UNIT_MS, 100, 1000,
1313 10, NULL, NULL, compressor_set), 1295 100, NULL, NULL, compressor_set),
1314#endif 1296#endif
1315#ifdef HAVE_WM8758 1297#ifdef HAVE_WM8758
1316 SOUND_SETTING(F_NO_WRAP, bass_cutoff, LANG_BASS_CUTOFF, 1298 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 3e78dd65f5..53272afba1 100644
--- a/manual/configure_rockbox/sound_settings.tex
+++ b/manual/configure_rockbox/sound_settings.tex
@@ -445,18 +445,48 @@ experience with more complex audio.
445} 445}
446 446
447\opt{swcodec}{ 447\opt{swcodec}{
448\section{Limiter Preamp} 448\section{Compressor}
449The limiter preamp raises the gain of the audio by the selected amount. The associated 449The \setting{Compressor} reduces, or compresses, the dynamic range of the audio
450limiter function works on the resulting louder signal to reduce any peaks to below the 450signal. This makes the quieter and louder sections closer to the same volume
451maximum level. The default selection of 0dB turns all limiter processing off. 451level by progressively reducing the gain of louder signals. When subsequently
452 452amplified, this has the effect of making the quieter sections louder while
453The limiter has the effect of reducing dynamic range by amplifying quiet sections while 453keeping the louder sections from clipping. This allows listening to the quiet
454loud sections are kept just under maximum gain. This allows listening to the quiet sections 454sections of dynamic material in noisy environments while preventing sudden loud
455of dynamic material in noisy environments while preventing sudden loud sections from being 455sections from being overbearing.
456overbearing. 456
457 457There are several settings associated with the compressor. The first, and most
458Think of this as a smart volume control. The preamp in effect turns up the volume by the 458important, is the \setting{Threshold}. The threshold is the audio input level
459amount you select so that you can hear quiet passages. But it senses when a loud section is 459at which the compressor begins to act. Any level louder than the threshold
460about to play and quickly and smoothly lowers the volume as necessary to keep the audio 460will be compressed to some extent. The maximum amount of compression, or the
461under the maximum limit. As the loud section fades, the volume is turned back up. 461quietest level at which the compressor will operate, is -24db. The default of
462Off disables the compressor.
463
464The \setting{Makeup Gain} setting has two options: Off and Auto. Off means
465that the compressed audio will not be amplified after compression. The default
466of Auto will amplify the signal so that the loudest possible signal after
467compression will be just under the clipping limit. This is desirable because
468the compressed signal without makeup gain is quieter than the input signal.
469Makeup Gain in Auto restores the signal to the maximum possible level and
470brings the quieter audio up with it. This is what makes it possible to hear
471the quieter audio in noisy environments.
472
473The \setting{Ratio} setting determines how aggressively the compressor reduces
474gain above the threshold. For example, the 2:1 setting means that for each
475two decibels of input signal above the threshold, the compressor will only
476allow the output to appear as one decibel. The higher the ratio, the harder
477the signal is compressed. The ratio setting of Limit means essentially a ratio
478of infinity to one. In this case, the output signal is not allowed to exceed
479the threshold at all.
480
481The \setting{Knee} setting determines how abrupt the transition is from a
482non-compressed signal to a compressed signal. Hard Knee means that the
483transition occurs precisely at the threshold. The Soft Knee setting smoothes
484the transition from plus or minus three decibels around the threshold.
485
486The \setting{Release Time} setting sets the recovery time after the signal is
487compressed. Once the compressor determines that compression is necessary,
488the input signal is reduced appropriately, but the gain isn't allowed to
489immediately return to normal levels. This is necessary to reduce artifacts
490such as "pumping." Instead, the gain is allowed to return to normal at the
491chosen rate. Release Time is the time for the gain to recover by 10dB.
462} 492}