summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2012-04-26 17:19:16 -0400
committerMichael Sevakis <jethead71@rockbox.org>2012-04-26 17:19:16 -0400
commit0842d7f7e1f123926bc7741c6ecfbcd631a65bea (patch)
tree3030e3bd5e1a322a8601379f2bd61aa71a50fc99
parent97a535d83c0f057b190c7a82f95297696b25a0df (diff)
downloadrockbox-0842d7f7e1f123926bc7741c6ecfbcd631a65bea.tar.gz
rockbox-0842d7f7e1f123926bc7741c6ecfbcd631a65bea.zip
Consolidate compressor settings into a struct.
Doing that makes things cleaner for later on. Change-Id: I4e279aa57ace16a348acc0fc09059592325ec95f
-rw-r--r--apps/menus/sound_menu.c15
-rw-r--r--apps/settings.c7
-rw-r--r--apps/settings.h13
-rw-r--r--apps/settings_list.c15
-rw-r--r--lib/rbcodec/dsp/compressor.c368
-rw-r--r--lib/rbcodec/dsp/compressor.h2
-rw-r--r--lib/rbcodec/dsp/dsp.c4
-rw-r--r--lib/rbcodec/dsp/dsp.h3
8 files changed, 216 insertions, 211 deletions
diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c
index e93d73b7ed..0817304f8d 100644
--- a/apps/menus/sound_menu.c
+++ b/apps/menus/sound_menu.c
@@ -126,15 +126,20 @@ static int timestretch_callback(int action,const struct menu_item_ex *this_item)
126 126
127 /* compressor submenu */ 127 /* compressor submenu */
128 MENUITEM_SETTING(compressor_threshold, 128 MENUITEM_SETTING(compressor_threshold,
129 &global_settings.compressor_threshold, lowlatency_callback); 129 &global_settings.compressor_settings.threshold,
130 lowlatency_callback);
130 MENUITEM_SETTING(compressor_gain, 131 MENUITEM_SETTING(compressor_gain,
131 &global_settings.compressor_makeup_gain, lowlatency_callback); 132 &global_settings.compressor_settings.makeup_gain,
133 lowlatency_callback);
132 MENUITEM_SETTING(compressor_ratio, 134 MENUITEM_SETTING(compressor_ratio,
133 &global_settings.compressor_ratio, lowlatency_callback); 135 &global_settings.compressor_settings.ratio,
136 lowlatency_callback);
134 MENUITEM_SETTING(compressor_knee, 137 MENUITEM_SETTING(compressor_knee,
135 &global_settings.compressor_knee, lowlatency_callback); 138 &global_settings.compressor_settings.knee,
139 lowlatency_callback);
136 MENUITEM_SETTING(compressor_release, 140 MENUITEM_SETTING(compressor_release,
137 &global_settings.compressor_release_time, lowlatency_callback); 141 &global_settings.compressor_settings.release_time,
142 lowlatency_callback);
138 MAKE_MENU(compressor_menu,ID2P(LANG_COMPRESSOR), NULL, Icon_NOICON, 143 MAKE_MENU(compressor_menu,ID2P(LANG_COMPRESSOR), NULL, Icon_NOICON,
139 &compressor_threshold, &compressor_gain, &compressor_ratio, 144 &compressor_threshold, &compressor_gain, &compressor_ratio,
140 &compressor_knee, &compressor_release); 145 &compressor_knee, &compressor_release);
diff --git a/apps/settings.c b/apps/settings.c
index 13913f2d85..a267f51765 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -781,9 +781,6 @@ void settings_apply(bool read_disk)
781#ifdef HAVE_LCD_BITMAP 781#ifdef HAVE_LCD_BITMAP
782 int rc; 782 int rc;
783#endif 783#endif
784#if CONFIG_CODEC == SWCODEC
785 int i;
786#endif
787 sound_settings_apply(); 784 sound_settings_apply();
788 785
789#ifdef HAVE_DISK_STORAGE 786#ifdef HAVE_DISK_STORAGE
@@ -991,7 +988,7 @@ void settings_apply(bool read_disk)
991 /* Configure software equalizer, hardware eq is handled in audio_init() */ 988 /* Configure software equalizer, hardware eq is handled in audio_init() */
992 dsp_set_eq(global_settings.eq_enabled); 989 dsp_set_eq(global_settings.eq_enabled);
993 dsp_set_eq_precut(global_settings.eq_precut); 990 dsp_set_eq_precut(global_settings.eq_precut);
994 for(i = 0; i < 5; i++) { 991 for(int i = 0; i < 5; i++) {
995 dsp_set_eq_coefs(i); 992 dsp_set_eq_coefs(i);
996 } 993 }
997 994
@@ -999,7 +996,7 @@ void settings_apply(bool read_disk)
999#ifdef HAVE_PITCHSCREEN 996#ifdef HAVE_PITCHSCREEN
1000 dsp_timestretch_enable(global_settings.timestretch_enabled); 997 dsp_timestretch_enable(global_settings.timestretch_enabled);
1001#endif 998#endif
1002 dsp_set_compressor(); 999 dsp_set_compressor(&global_settings.compressor_settings);
1003#endif 1000#endif
1004 1001
1005#ifdef HAVE_SPDIF_POWER 1002#ifdef HAVE_SPDIF_POWER
diff --git a/apps/settings.h b/apps/settings.h
index fb562c9191..b312c1e784 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -772,11 +772,14 @@ struct user_settings
772#endif 772#endif
773 773
774#if CONFIG_CODEC == SWCODEC 774#if CONFIG_CODEC == SWCODEC
775 int compressor_threshold; 775 struct compressor_settings
776 int compressor_makeup_gain; 776 {
777 int compressor_ratio; 777 int threshold;
778 int compressor_knee; 778 int makeup_gain;
779 int compressor_release_time; 779 int ratio;
780 int knee;
781 int release_time;
782 } compressor_settings;
780#endif 783#endif
781 784
782 int sleeptimer_duration; /* In minutes; 0=off */ 785 int sleeptimer_duration; /* In minutes; 0=off */
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 6780c78ed3..af48d11c85 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -436,7 +436,7 @@ static void crossfeed_cross_set(int val)
436static void compressor_set(int val) 436static void compressor_set(int val)
437{ 437{
438 (void)val; 438 (void)val;
439 dsp_set_compressor(); 439 dsp_set_compressor(&global_settings.compressor_settings);
440} 440}
441 441
442static const char* db_format(char* buffer, size_t buffer_size, int value, 442static const char* db_format(char* buffer, size_t buffer_size, int value,
@@ -1482,25 +1482,26 @@ const struct settings_list settings[] = {
1482#endif 1482#endif
1483 1483
1484 /* compressor */ 1484 /* compressor */
1485 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_threshold, 1485 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.threshold,
1486 LANG_COMPRESSOR_THRESHOLD, 0, 1486 LANG_COMPRESSOR_THRESHOLD, 0,
1487 "compressor threshold", UNIT_DB, 0, -24, 1487 "compressor threshold", UNIT_DB, 0, -24,
1488 -3, formatter_unit_0_is_off, getlang_unit_0_is_off, compressor_set), 1488 -3, formatter_unit_0_is_off, getlang_unit_0_is_off,
1489 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_makeup_gain, 1489 compressor_set),
1490 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_settings.makeup_gain,
1490 LANG_COMPRESSOR_GAIN, 1, "compressor makeup gain", 1491 LANG_COMPRESSOR_GAIN, 1, "compressor makeup gain",
1491 "off,auto", compressor_set, 2, 1492 "off,auto", compressor_set, 2,
1492 ID2P(LANG_OFF), ID2P(LANG_AUTO)), 1493 ID2P(LANG_OFF), ID2P(LANG_AUTO)),
1493 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_ratio, 1494 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_settings.ratio,
1494 LANG_COMPRESSOR_RATIO, 1, "compressor ratio", 1495 LANG_COMPRESSOR_RATIO, 1, "compressor ratio",
1495 "2:1,4:1,6:1,10:1,limit", compressor_set, 5, 1496 "2:1,4:1,6:1,10:1,limit", compressor_set, 5,
1496 ID2P(LANG_COMPRESSOR_RATIO_2), ID2P(LANG_COMPRESSOR_RATIO_4), 1497 ID2P(LANG_COMPRESSOR_RATIO_2), ID2P(LANG_COMPRESSOR_RATIO_4),
1497 ID2P(LANG_COMPRESSOR_RATIO_6), ID2P(LANG_COMPRESSOR_RATIO_10), 1498 ID2P(LANG_COMPRESSOR_RATIO_6), ID2P(LANG_COMPRESSOR_RATIO_10),
1498 ID2P(LANG_COMPRESSOR_RATIO_LIMIT)), 1499 ID2P(LANG_COMPRESSOR_RATIO_LIMIT)),
1499 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_knee, 1500 CHOICE_SETTING(F_SOUNDSETTING|F_NO_WRAP, compressor_settings.knee,
1500 LANG_COMPRESSOR_KNEE, 1, "compressor knee", 1501 LANG_COMPRESSOR_KNEE, 1, "compressor knee",
1501 "hard knee,soft knee", compressor_set, 2, 1502 "hard knee,soft knee", compressor_set, 2,
1502 ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)), 1503 ID2P(LANG_COMPRESSOR_HARD_KNEE), ID2P(LANG_COMPRESSOR_SOFT_KNEE)),
1503 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_release_time, 1504 INT_SETTING_NOWRAP(F_SOUNDSETTING, compressor_settings.release_time,
1504 LANG_COMPRESSOR_RELEASE, 500, 1505 LANG_COMPRESSOR_RELEASE, 500,
1505 "compressor release time", UNIT_MS, 100, 1000, 1506 "compressor release time", UNIT_MS, 100, 1000,
1506 100, NULL, NULL, compressor_set), 1507 100, NULL, NULL, compressor_set),
diff --git a/lib/rbcodec/dsp/compressor.c b/lib/rbcodec/dsp/compressor.c
index 3a8d52e4da..a6c1ac1018 100644
--- a/lib/rbcodec/dsp/compressor.c
+++ b/lib/rbcodec/dsp/compressor.c
@@ -29,6 +29,8 @@
29/*#define LOGF_ENABLE*/ 29/*#define LOGF_ENABLE*/
30#include "logf.h" 30#include "logf.h"
31 31
32static struct compressor_settings curr_set; /* Cached settings */
33
32static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */ 34static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
33static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */ 35static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
34static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */ 36static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
@@ -38,214 +40,210 @@ static int32_t release_gain IBSS_ATTR; /* S7.24 format */
38 40
39/** COMPRESSOR UPDATE 41/** COMPRESSOR UPDATE
40 * Called via the menu system to configure the compressor process */ 42 * Called via the menu system to configure the compressor process */
41bool compressor_update(void) 43bool compressor_update(const struct compressor_settings *settings)
42{ 44{
43 static int curr_set[5]; 45 /* make settings values useful */
44 int new_set[5] = { 46 int threshold = settings->threshold;
45 global_settings.compressor_threshold, 47 bool auto_gain = settings->makeup_gain == 1;
46 global_settings.compressor_makeup_gain, 48 static const int comp_ratios[] = { 2, 4, 6, 10, 0 };
47 global_settings.compressor_ratio, 49 int ratio = comp_ratios[settings->ratio];
48 global_settings.compressor_knee, 50 bool soft_knee = settings->knee == 1;
49 global_settings.compressor_release_time}; 51 int release = settings->release_time * NATIVE_FREQUENCY / 1000;
50
51 /* make menu values useful */
52 int threshold = new_set[0];
53 bool auto_gain = (new_set[1] == 1);
54 const int comp_ratios[] = {2, 4, 6, 10, 0};
55 int ratio = comp_ratios[new_set[2]];
56 bool soft_knee = (new_set[3] == 1);
57 int release = new_set[4] * NATIVE_FREQUENCY / 1000;
58 52
59 bool changed = false; 53 bool changed = false;
60 bool active = (threshold < 0); 54 bool active = threshold < 0;
61 55
62 for (int i = 0; i < 5; i++) 56 if (memcmp(settings, &curr_set, sizeof (curr_set)))
63 { 57 {
64 if (curr_set[i] != new_set[i]) 58 /* Compressor settings have changed since last call */
65 { 59 changed = true;
66 changed = true;
67 curr_set[i] = new_set[i];
68 60
69#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE) 61#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
70 switch (i) 62 if (settings->threshold != curr_set.threshold)
71 { 63 {
72 case 0: 64 logf(" Compressor Threshold: %d dB\tEnabled: %s",
73 logf(" Compressor Threshold: %d dB\tEnabled: %s", 65 threshold, active ? "Yes" : "No");
74 threshold, active ? "Yes" : "No");
75 break;
76 case 1:
77 logf(" Compressor Makeup Gain: %s",
78 auto_gain ? "Auto" : "Off");
79 break;
80 case 2:
81 if (ratio)
82 { logf(" Compressor Ratio: %d:1", ratio); }
83 else
84 { logf(" Compressor Ratio: Limit"); }
85 break;
86 case 3:
87 logf(" Compressor Knee: %s", soft_knee?"Soft":"Hard");
88 break;
89 case 4:
90 logf(" Compressor Release: %d", release);
91 break;
92 }
93#endif
94 } 66 }
95 }
96 67
97 if (changed && active) 68 if (settings->makeup_gain != curr_set.makeup_gain)
98 {
99 /* configure variables for compressor operation */
100 static const int32_t db[] = {
101 /* positive db equivalents in S15.16 format */
102 0x000000, 0x241FA4, 0x1E1A5E, 0x1A94C8,
103 0x181518, 0x1624EA, 0x148F82, 0x1338BD,
104 0x120FD2, 0x1109EB, 0x101FA4, 0x0F4BB6,
105 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E,
106 0x0C0A8C, 0x0B83BE, 0x0B04A5, 0x0A8C6C,
107 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398,
108 0x0884F6, 0x082A30, 0x07D2FA, 0x077F0F,
109 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF,
110 0x060546, 0x05C0DA, 0x057E78, 0x053E03,
111 0x04FF5F, 0x04C273, 0x048726, 0x044D64,
112 0x041518, 0x03DE30, 0x03A89B, 0x037448,
113 0x03412A, 0x030F32, 0x02DE52, 0x02AE80,
114 0x027FB0, 0x0251D6, 0x0224EA, 0x01F8E2,
115 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC,
116 0x0128EB, 0x010190, 0x00DAE4, 0x00B4E1,
117 0x008F82, 0x006AC1, 0x004699, 0x002305};
118
119 struct curve_point
120 { 69 {
121 int32_t db; /* S15.16 format */ 70 logf(" Compressor Makeup Gain: %s",
122 int32_t offset; /* S15.16 format */ 71 auto_gain ? "Auto" : "Off");
123 } db_curve[5]; 72 }
124 73
125 /** Set up the shape of the compression curve first as decibel 74 if (settings->ratio != cur_set.ratio)
126 values */
127 /* db_curve[0] = bottom of knee
128 [1] = threshold
129 [2] = top of knee
130 [3] = 0 db input
131 [4] = ~+12db input (2 bits clipping overhead) */
132
133 db_curve[1].db = threshold << 16;
134 if (soft_knee)
135 { 75 {
136 /* bottom of knee is 3dB below the threshold for soft knee*/
137 db_curve[0].db = db_curve[1].db - (3 << 16);
138 /* top of knee is 3dB above the threshold for soft knee */
139 db_curve[2].db = db_curve[1].db + (3 << 16);
140 if (ratio) 76 if (ratio)
141 /* offset = -3db * (ratio - 1) / ratio */ 77 { logf(" Compressor Ratio: %d:1", ratio); }
142 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
143 * (ratio - 1) / ratio);
144 else 78 else
145 /* offset = -3db for hard limit */ 79 { logf(" Compressor Ratio: Limit"); }
146 db_curve[2].offset = (-3 << 16);
147 } 80 }
148 else 81
82 if (settings->knee != cur_set.knee)
149 { 83 {
150 /* bottom of knee is at the threshold for hard knee */ 84 logf(" Compressor Knee: %s", soft_knee?"Soft":"Hard");
151 db_curve[0].db = threshold << 16;
152 /* top of knee is at the threshold for hard knee */
153 db_curve[2].db = threshold << 16;
154 db_curve[2].offset = 0;
155 } 85 }
156 86
157 /* Calculate 0db and ~+12db offsets */ 87 if (settings->release_time != cur_set.release_time)
158 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
159 if (ratio)
160 { 88 {
161 /* offset = threshold * (ratio - 1) / ratio */ 89 logf(" Compressor Release: %d", release);
162 db_curve[3].offset = (int32_t)((long long)(threshold << 16)
163 * (ratio - 1) / ratio);
164 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
165 * (ratio - 1) / ratio) + db_curve[3].offset;
166 } 90 }
91#endif
92
93 curr_set = *settings;
94 }
95
96 if (!changed || !active)
97 return active;
98
99 /* configure variables for compressor operation */
100 static const int32_t db[] = {
101 /* positive db equivalents in S15.16 format */
102 0x000000, 0x241FA4, 0x1E1A5E, 0x1A94C8,
103 0x181518, 0x1624EA, 0x148F82, 0x1338BD,
104 0x120FD2, 0x1109EB, 0x101FA4, 0x0F4BB6,
105 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E,
106 0x0C0A8C, 0x0B83BE, 0x0B04A5, 0x0A8C6C,
107 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398,
108 0x0884F6, 0x082A30, 0x07D2FA, 0x077F0F,
109 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF,
110 0x060546, 0x05C0DA, 0x057E78, 0x053E03,
111 0x04FF5F, 0x04C273, 0x048726, 0x044D64,
112 0x041518, 0x03DE30, 0x03A89B, 0x037448,
113 0x03412A, 0x030F32, 0x02DE52, 0x02AE80,
114 0x027FB0, 0x0251D6, 0x0224EA, 0x01F8E2,
115 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC,
116 0x0128EB, 0x010190, 0x00DAE4, 0x00B4E1,
117 0x008F82, 0x006AC1, 0x004699, 0x002305};
118
119 struct curve_point
120 {
121 int32_t db; /* S15.16 format */
122 int32_t offset; /* S15.16 format */
123 } db_curve[5];
124
125 /** Set up the shape of the compression curve first as decibel
126 values */
127 /* db_curve[0] = bottom of knee
128 [1] = threshold
129 [2] = top of knee
130 [3] = 0 db input
131 [4] = ~+12db input (2 bits clipping overhead) */
132
133 db_curve[1].db = threshold << 16;
134 if (soft_knee)
135 {
136 /* bottom of knee is 3dB below the threshold for soft knee*/
137 db_curve[0].db = db_curve[1].db - (3 << 16);
138 /* top of knee is 3dB above the threshold for soft knee */
139 db_curve[2].db = db_curve[1].db + (3 << 16);
140 if (ratio)
141 /* offset = -3db * (ratio - 1) / ratio */
142 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
143 * (ratio - 1) / ratio);
167 else 144 else
168 { 145 /* offset = -3db for hard limit */
169 /* offset = threshold for hard limit */ 146 db_curve[2].offset = (-3 << 16);
170 db_curve[3].offset = (threshold << 16); 147 }
171 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset; 148 else
172 } 149 {
173 150 /* bottom of knee is at the threshold for hard knee */
174 /** Now set up the comp_curve table with compression offsets in the 151 db_curve[0].db = threshold << 16;
175 form of gain factors in S7.24 format */ 152 /* top of knee is at the threshold for hard knee */
176 /* comp_curve[0] is 0 (-infinity db) input */ 153 db_curve[2].db = threshold << 16;
177 comp_curve[0] = UNITY; 154 db_curve[2].offset = 0;
178 /* comp_curve[1 to 63] are intermediate compression values 155 }
179 corresponding to the 6 MSB of the input values of a non-clipped 156
180 signal */ 157 /* Calculate 0db and ~+12db offsets */
181 for (int i = 1; i < 64; i++) 158 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
182 { 159 if (ratio)
183 /* db constants are stored as positive numbers; 160 {
184 make them negative here */ 161 /* offset = threshold * (ratio - 1) / ratio */
185 int32_t this_db = -db[i]; 162 db_curve[3].offset = (int32_t)((long long)(threshold << 16)
186 163 * (ratio - 1) / ratio);
187 /* no compression below the knee */ 164 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
188 if (this_db <= db_curve[0].db) 165 * (ratio - 1) / ratio) + db_curve[3].offset;
189 comp_curve[i] = UNITY; 166 }
190 167 else
191 /* if soft knee and below top of knee, 168 {
192 interpolate along soft knee slope */ 169 /* offset = threshold for hard limit */
193 else if (soft_knee && (this_db <= db_curve[2].db)) 170 db_curve[3].offset = (threshold << 16);
194 comp_curve[i] = fp_factor(fp_mul( 171 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
195 ((this_db - db_curve[0].db) / 6), 172 }
196 db_curve[2].offset, 16), 16) << 8; 173
197 174 /** Now set up the comp_curve table with compression offsets in the
198 /* interpolate along ratio slope above the knee */ 175 form of gain factors in S7.24 format */
199 else 176 /* comp_curve[0] is 0 (-infinity db) input */
200 comp_curve[i] = fp_factor(fp_mul( 177 comp_curve[0] = UNITY;
201 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16), 178 /* comp_curve[1 to 63] are intermediate compression values
202 db_curve[3].offset, 16), 16) << 8; 179 corresponding to the 6 MSB of the input values of a non-clipped
203 } 180 signal */
204 /* comp_curve[64] is the compression level of a maximum level, 181 for (int i = 1; i < 64; i++)
205 non-clipped signal */ 182 {
206 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8; 183 /* db constants are stored as positive numbers;
207 184 make them negative here */
208 /* comp_curve[65] is the compression level of a maximum level, 185 int32_t this_db = -db[i];
209 clipped signal */ 186
210 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8; 187 /* no compression below the knee */
211 188 if (this_db <= db_curve[0].db)
189 comp_curve[i] = UNITY;
190
191 /* if soft knee and below top of knee,
192 interpolate along soft knee slope */
193 else if (soft_knee && (this_db <= db_curve[2].db))
194 comp_curve[i] = fp_factor(fp_mul(
195 ((this_db - db_curve[0].db) / 6),
196 db_curve[2].offset, 16), 16) << 8;
197
198 /* interpolate along ratio slope above the knee */
199 else
200 comp_curve[i] = fp_factor(fp_mul(
201 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
202 db_curve[3].offset, 16), 16) << 8;
203 }
204 /* comp_curve[64] is the compression level of a maximum level,
205 non-clipped signal */
206 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
207
208 /* comp_curve[65] is the compression level of a maximum level,
209 clipped signal */
210 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
211
212#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE) 212#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
213 logf("\n *** Compression Offsets ***"); 213 logf("\n *** Compression Offsets ***");
214 /* some settings for display only, not used in calculations */ 214 /* some settings for display only, not used in calculations */
215 db_curve[0].offset = 0; 215 db_curve[0].offset = 0;
216 db_curve[1].offset = 0; 216 db_curve[1].offset = 0;
217 db_curve[3].db = 0; 217 db_curve[3].db = 0;
218
219 for (int i = 0; i <= 4; i++)
220 {
221 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
222 (float)db_curve[i].db / (1 << 16),
223 (float)db_curve[i].offset / (1 << 16));
224 }
225
226 logf("\nGain factors:");
227 for (int i = 1; i <= 65; i++)
228 {
229 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
230 if (i % 4 == 0) debugf("\n");
231 }
232 debugf("\n");
233#endif
234
235 /* if using auto peak, then makeup gain is max offset -
236 .1dB headroom */
237 comp_makeup_gain = auto_gain ?
238 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
239 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
240 218
241 /* calculate per-sample gain change a rate of 10db over release time 219 for (int i = 0; i <= 4; i++)
242 */ 220 {
243 comp_rel_slope = 0xAF0BB2 / release; 221 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
244 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY); 222 (float)db_curve[i].db / (1 << 16),
245 223 (float)db_curve[i].offset / (1 << 16));
246 release_gain = UNITY;
247 } 224 }
248 225
226 logf("\nGain factors:");
227 for (int i = 1; i <= 65; i++)
228 {
229 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
230 if (i % 4 == 0) debugf("\n");
231 }
232 debugf("\n");
233#endif
234
235 /* if using auto peak, then makeup gain is max offset -
236 .1dB headroom */
237 comp_makeup_gain = auto_gain ?
238 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
239 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
240
241 /* calculate per-sample gain change a rate of 10db over release time
242 */
243 comp_rel_slope = 0xAF0BB2 / release;
244 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
245
246 release_gain = UNITY;
249 return active; 247 return active;
250} 248}
251 249
diff --git a/lib/rbcodec/dsp/compressor.h b/lib/rbcodec/dsp/compressor.h
index 6154372e05..d0e33f6e2c 100644
--- a/lib/rbcodec/dsp/compressor.h
+++ b/lib/rbcodec/dsp/compressor.h
@@ -23,7 +23,7 @@
23#define COMPRESSOR_H 23#define COMPRESSOR_H
24 24
25void compressor_process(int count, struct dsp_data *data, int32_t *buf[]); 25void compressor_process(int count, struct dsp_data *data, int32_t *buf[]);
26bool compressor_update(void); 26bool compressor_update(const struct compressor_settings *settings);
27void compressor_reset(void); 27void compressor_reset(void);
28 28
29#endif /* COMPRESSOR_H */ 29#endif /* COMPRESSOR_H */
diff --git a/lib/rbcodec/dsp/dsp.c b/lib/rbcodec/dsp/dsp.c
index 4da555747b..4061fa7186 100644
--- a/lib/rbcodec/dsp/dsp.c
+++ b/lib/rbcodec/dsp/dsp.c
@@ -1565,9 +1565,9 @@ void dsp_set_replaygain(void)
1565 1565
1566/** SET COMPRESSOR 1566/** SET COMPRESSOR
1567 * Called by the menu system to configure the compressor process */ 1567 * Called by the menu system to configure the compressor process */
1568void dsp_set_compressor(void) 1568void dsp_set_compressor(const struct compressor_settings *settings)
1569{ 1569{
1570 /* enable/disable the compressor */ 1570 /* enable/disable the compressor */
1571 AUDIO_DSP.compressor_process = compressor_update() ? 1571 AUDIO_DSP.compressor_process = compressor_update(settings) ?
1572 compressor_process : NULL; 1572 compressor_process : NULL;
1573} 1573}
diff --git a/lib/rbcodec/dsp/dsp.h b/lib/rbcodec/dsp/dsp.h
index 2a00f649f8..0da62747a3 100644
--- a/lib/rbcodec/dsp/dsp.h
+++ b/lib/rbcodec/dsp/dsp.h
@@ -120,6 +120,7 @@ int32_t sound_get_pitch(void);
120void dsp_set_timestretch(int32_t percent); 120void dsp_set_timestretch(int32_t percent);
121int32_t dsp_get_timestretch(void); 121int32_t dsp_get_timestretch(void);
122int dsp_callback(int msg, intptr_t param); 122int dsp_callback(int msg, intptr_t param);
123void dsp_set_compressor(void); 123struct compressor_settings;
124void dsp_set_compressor(const struct compressor_settings *settings);
124 125
125#endif 126#endif