[pulseaudio-discuss] [PATCH] module-virtual-surround-sink: Move normalization heuristic to its own function
Niels Ole Salscheider
niels_ole at salscheider-online.de
Wed Apr 2 13:32:34 PDT 2014
This patch also adds a description how the heuristic works and mentions that
there is a scaling factor that can be adjusted if there is audible clipping.
---
src/modules/module-virtual-surround-sink.c | 57 +++++++++++++++++++++---------
1 file changed, 40 insertions(+), 17 deletions(-)
diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c
index 1d6cfc6..34f23fd 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -519,6 +519,45 @@ static pa_channel_position_t mirror_channel(pa_channel_position_t channel) {
}
}
+static void normalize_hrir(struct userdata *u) {
+ /* normalize hrir to avoid audible clipping
+ *
+ * The following heuristic tries to avoid audible clipping. It cannot avoid
+ * clipping in the worst case though, because the scaling factor would
+ * become too large resulting in a too quiet signal.
+ * The idea of the heuristic is to avoid clipping when a single click is
+ * played back on all channels. The scaling factor describes the additional
+ * factor that is necessary to avoid clipping for "normal" signals.
+ *
+ * This algorithm doesn't pretend to be perfect, it's just something that
+ * appears to work (not too quiet, no audible clipping) on the material that
+ * it has been tested on. If you find a real-world example where this
+ * algorithm results in audible clipping, please write a patch that adjusts
+ * the scaling factor constants or improves the algorithm (or if you can't
+ * write a patch, at least report the problem to the PulseAudio mailing list
+ * or bug tracker). */
+
+ const float scaling_factor = 2.5;
+
+ float hrir_sum, hrir_max;
+ unsigned i, j;
+
+ hrir_max = 0;
+ for (i = 0; i < u->hrir_samples; i++) {
+ hrir_sum = 0;
+ for (j = 0; j < u->hrir_channels; j++)
+ hrir_sum += fabs(u->hrir_data[i * u->hrir_channels + j]);
+
+ if (hrir_sum > hrir_max)
+ hrir_max = hrir_sum;
+ }
+
+ for (i = 0; i < u->hrir_samples; i++) {
+ for (j = 0; j < u->hrir_channels; j++)
+ u->hrir_data[i * u->hrir_channels + j] /= hrir_max * scaling_factor;
+ }
+}
+
int pa__init(pa_module*m) {
struct userdata *u;
pa_sample_spec ss, sink_input_ss;
@@ -533,7 +572,6 @@ int pa__init(pa_module*m) {
const char *hrir_file;
unsigned i, j, found_channel_left, found_channel_right;
- float hrir_sum, hrir_max;
float *hrir_data;
pa_sample_spec hrir_ss;
@@ -758,22 +796,7 @@ int pa__init(pa_module*m) {
goto fail;
}
- /* normalize hrir to avoid clipping */
- hrir_max = 0;
- for (i = 0; i < u->hrir_samples; i++) {
- hrir_sum = 0;
- for (j = 0; j < u->hrir_channels; j++)
- hrir_sum += fabs(u->hrir_data[i * u->hrir_channels + j]);
-
- if (hrir_sum > hrir_max)
- hrir_max = hrir_sum;
- }
- if (hrir_max > 1) {
- for (i = 0; i < u->hrir_samples; i++) {
- for (j = 0; j < u->hrir_channels; j++)
- u->hrir_data[i * u->hrir_channels + j] /= hrir_max * 1.2;
- }
- }
+ normalize_hrir(u);
/* create mapping between hrir and input */
u->mapping_left = (unsigned *) pa_xnew0(unsigned, u->channels);
--
1.9.1
More information about the pulseaudio-discuss
mailing list