03.04.2014 02:32, Niels Ole Salscheider wrote: > 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. The patch does what it says (and nothing more) and is consistent with the suggestions proposed by Tanu. It should be applied. > --- > 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); -- Alexander E. Patrakov