[pulseaudio-discuss] [PATCH] module-virtual-surround-sink: Move normalization heuristic to its own function

2014-04-02 Thread Niels Ole Salscheider
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

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] On scaling the HRIR in module-virtual-surround-sink

2014-04-01 Thread Niels Ole Salscheider
Hello Alexander,

On Tuesday 11 March 2014, 15:00:31, Tanu Kaskinen wrote:
 On Sun, 2014-03-09 at 00:57 +0600, Alexander E. Patrakov wrote:
  Hello.
  
  [Do not blindly apply patches from this e-mail! They mutually exclusive,
  and I don't have a firm opinion which one of them is correct.]
  
  Today I tried to improve the existing module-virtual-surround-sink (but
  the same issue also affects the IIR-based rewrite that is still sitting
  on my laptop). The problem is: the current normalization code does not
  do what it is designed to do. The module clips on some testcases. Let me
  copy-paste the problematic code for easy discussion.
 
 snip
 
  Thoughts?
 
 My thoughts:
 
 The scaling should be put in its own function with a comment that
 explains why the scaling is done, a high level description of how the
 scaling algorithm works, and a note that it's unclear whether the
 algorithm actually makes sense. Something like this could be included
 too: 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).

Would you like to write such a patch or should I do it? Or do you have an idea 
for a better heuristic?

Regards,

Ole
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] On scaling the HRIR in module-virtual-surround-sink

2014-03-09 Thread Niels Ole Salscheider
Hello Alexander,

I wrote that module some time ago. And I had the same problems that you 
describe, i. e. when I tried to avoid clipping in the worst possible case, the 
output was way too quiet.
Therefore I tried to come up with a heuristic and the 1.2 fudge factor seemed 
to work for me. But you are right that it depends on the HRIR and the content 
and I also came across situations in which there was clipping in the meantime.
So this is definitely something that should be fixed.

Kind regards,

Ole
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] virtual-surround: check if resampled memblock is not equal to input

2012-11-24 Thread Niels Ole Salscheider
Since commit e32a408b3cdd46857fdf12210c1bf5bdbf3a96f8, we silence the
input memblock in order to give the resampler enough input samples, if
necessary.
But if there is no need to resample the hrir, the resampled memblock is
actually the same as the input memblock. Thus, we have to make sure that
we do not silence it in this case.
---
 src/modules/module-virtual-surround-sink.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/modules/module-virtual-surround-sink.c 
b/src/modules/module-virtual-surround-sink.c
index 4915278..adaa58f 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -738,8 +738,10 @@ int pa__init(pa_module*m) {
 /* add silence to the hrir until we get enough samples out of the 
resampler */
 while (hrir_copied_length  hrir_total_length) {
 pa_resampler_run(resampler, hrir_temp_chunk, 
hrir_temp_chunk_resampled);
-/* Silence input block */
-pa_silence_memblock(hrir_temp_chunk.memblock, hrir_temp_ss);
+if (hrir_temp_chunk.memblock != hrir_temp_chunk_resampled.memblock) {
+/* Silence input block */
+pa_silence_memblock(hrir_temp_chunk.memblock, hrir_temp_ss);
+}
 
 if (hrir_temp_chunk_resampled.memblock) {
 /* Copy hrir data */
-- 
1.8.0

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] Brrr ... freeze imminent

2012-10-23 Thread Niels Ole Salscheider
Hello,

please consider to also merge version 2 of my patch module-virtual-surround-
sink: add silence to hrir if necessary.

The problem is, that the libsndfile based resamplers do not guarantee to output 
any samples for too short input sequences. Thus, we should append silence to 
the hrir if we do not get enough samples from the resampler.

Regards,

Ole
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 2/2] module-virtual-surround-sound: limit number of hrir samples

2012-10-05 Thread Niels Ole Salscheider
---
 src/modules/module-virtual-surround-sink.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/modules/module-virtual-surround-sink.c 
b/src/modules/module-virtual-surround-sink.c
index 14a666f..0690769 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -724,6 +724,11 @@ int pa__init(pa_module*m) {
  PA_RESAMPLER_SRC_SINC_BEST_QUALITY, 
PA_RESAMPLER_NO_REMAP);
 
 u-hrir_samples = hrir_temp_chunk.length / pa_frame_size(hrir_temp_ss);
+if (u-hrir_samples  64) {
+u-hrir_samples = 64;
+pa_log(The hrir file contains more than 64 samples. Only the first 64 
samples will be used to limit processor usage.);
+}
+
 hrir_total_length = u-hrir_samples * pa_frame_size(hrir_ss);
 u-hrir_channels = hrir_ss.channels;
 
-- 
1.7.12.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 1/2] module-virtual-surround-sink: add silence to hrir if necessary

2012-10-05 Thread Niels Ole Salscheider
Otherwise, the hrir might be too short to get completely resampled
---
 src/modules/module-virtual-surround-sink.c | 47 --
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/src/modules/module-virtual-surround-sink.c 
b/src/modules/module-virtual-surround-sink.c
index d64e577..14a666f 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -550,10 +550,13 @@ int pa__init(pa_module*m) {
 pa_channel_map hrir_map;
 
 pa_sample_spec hrir_temp_ss;
-pa_memchunk hrir_temp_chunk;
+pa_memchunk hrir_temp_chunk, hrir_temp_chunk_resampled;
 pa_resampler *resampler;
 
+size_t hrir_copied_length, hrir_total_length;
+
 hrir_temp_chunk.memblock = NULL;
+hrir_temp_chunk_resampled.memblock = NULL;
 
 pa_assert(m);
 
@@ -719,17 +722,40 @@ int pa__init(pa_module*m) {
 /* resample hrir */
 resampler = pa_resampler_new(u-sink-core-mempool, hrir_temp_ss, 
hrir_map, hrir_ss, hrir_map,
  PA_RESAMPLER_SRC_SINC_BEST_QUALITY, 
PA_RESAMPLER_NO_REMAP);
-pa_resampler_run(resampler, hrir_temp_chunk, hrir_temp_chunk);
-pa_resampler_free(resampler);
 
-u-hrir_samples =  hrir_temp_chunk.length / pa_frame_size(hrir_ss);
+u-hrir_samples = hrir_temp_chunk.length / pa_frame_size(hrir_temp_ss);
+hrir_total_length = u-hrir_samples * pa_frame_size(hrir_ss);
 u-hrir_channels = hrir_ss.channels;
 
-/* copy hrir data */
-hrir_data = (float *) pa_memblock_acquire(hrir_temp_chunk.memblock);
-u-hrir_data = (float *) pa_xmalloc(hrir_temp_chunk.length);
-memcpy(u-hrir_data, hrir_data, hrir_temp_chunk.length);
-pa_memblock_release(hrir_temp_chunk.memblock);
+u-hrir_data = (float *) pa_xmalloc(hrir_total_length);
+hrir_copied_length = 0;
+
+/* add silence to the hrir until we get enough samples out of the 
resampler */
+while (hrir_copied_length  hrir_total_length) {
+pa_resampler_run(resampler, hrir_temp_chunk, 
hrir_temp_chunk_resampled);
+/* Silence input block */
+pa_silence_memblock(hrir_temp_chunk.memblock, hrir_temp_ss);
+
+if (hrir_temp_chunk_resampled.memblock) {
+/* Copy hrir data */
+hrir_data = (float *) 
pa_memblock_acquire(hrir_temp_chunk_resampled.memblock);
+
+if (hrir_total_length - hrir_copied_length = 
hrir_temp_chunk_resampled.length) {
+memcpy(u-hrir_data + hrir_copied_length, hrir_data, 
hrir_temp_chunk_resampled.length);
+hrir_copied_length += hrir_temp_chunk_resampled.length;
+} else {
+memcpy(u-hrir_data + hrir_copied_length, hrir_data, 
hrir_total_length - hrir_copied_length);
+hrir_copied_length = hrir_total_length;
+}
+
+pa_memblock_release(hrir_temp_chunk_resampled.memblock);
+pa_memblock_unref(hrir_temp_chunk_resampled.memblock);
+hrir_temp_chunk_resampled.memblock = NULL;
+}
+}
+
+pa_resampler_free(resampler);
+
 pa_memblock_unref(hrir_temp_chunk.memblock);
 hrir_temp_chunk.memblock = NULL;
 
@@ -797,6 +823,9 @@ fail:
 if (hrir_temp_chunk.memblock)
 pa_memblock_unref(hrir_temp_chunk.memblock);
 
+if (hrir_temp_chunk_resampled.memblock)
+pa_memblock_unref(hrir_temp_chunk_resampled.memblock);
+
 if (ma)
 pa_modargs_free(ma);
 
-- 
1.7.12.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 1/2] module-virtual-surround-sink: add silence to hrir if necessary

2012-10-05 Thread Niels Ole Salscheider
Otherwise, the hrir might be too short to get completely resampled

v2: take different sample rates into account
---
 src/modules/module-virtual-surround-sink.c | 47 --
 1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/src/modules/module-virtual-surround-sink.c 
b/src/modules/module-virtual-surround-sink.c
index d64e577..50f101d 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -550,10 +550,13 @@ int pa__init(pa_module*m) {
 pa_channel_map hrir_map;
 
 pa_sample_spec hrir_temp_ss;
-pa_memchunk hrir_temp_chunk;
+pa_memchunk hrir_temp_chunk, hrir_temp_chunk_resampled;
 pa_resampler *resampler;
 
+size_t hrir_copied_length, hrir_total_length;
+
 hrir_temp_chunk.memblock = NULL;
+hrir_temp_chunk_resampled.memblock = NULL;
 
 pa_assert(m);
 
@@ -719,17 +722,40 @@ int pa__init(pa_module*m) {
 /* resample hrir */
 resampler = pa_resampler_new(u-sink-core-mempool, hrir_temp_ss, 
hrir_map, hrir_ss, hrir_map,
  PA_RESAMPLER_SRC_SINC_BEST_QUALITY, 
PA_RESAMPLER_NO_REMAP);
-pa_resampler_run(resampler, hrir_temp_chunk, hrir_temp_chunk);
-pa_resampler_free(resampler);
 
-u-hrir_samples =  hrir_temp_chunk.length / pa_frame_size(hrir_ss);
+u-hrir_samples = hrir_temp_chunk.length / pa_frame_size(hrir_temp_ss) * 
hrir_ss.rate / hrir_temp_ss.rate;
+hrir_total_length = u-hrir_samples * pa_frame_size(hrir_ss);
 u-hrir_channels = hrir_ss.channels;
 
-/* copy hrir data */
-hrir_data = (float *) pa_memblock_acquire(hrir_temp_chunk.memblock);
-u-hrir_data = (float *) pa_xmalloc(hrir_temp_chunk.length);
-memcpy(u-hrir_data, hrir_data, hrir_temp_chunk.length);
-pa_memblock_release(hrir_temp_chunk.memblock);
+u-hrir_data = (float *) pa_xmalloc(hrir_total_length);
+hrir_copied_length = 0;
+
+/* add silence to the hrir until we get enough samples out of the 
resampler */
+while (hrir_copied_length  hrir_total_length) {
+pa_resampler_run(resampler, hrir_temp_chunk, 
hrir_temp_chunk_resampled);
+/* Silence input block */
+pa_silence_memblock(hrir_temp_chunk.memblock, hrir_temp_ss);
+
+if (hrir_temp_chunk_resampled.memblock) {
+/* Copy hrir data */
+hrir_data = (float *) 
pa_memblock_acquire(hrir_temp_chunk_resampled.memblock);
+
+if (hrir_total_length - hrir_copied_length = 
hrir_temp_chunk_resampled.length) {
+memcpy(u-hrir_data + hrir_copied_length, hrir_data, 
hrir_temp_chunk_resampled.length);
+hrir_copied_length += hrir_temp_chunk_resampled.length;
+} else {
+memcpy(u-hrir_data + hrir_copied_length, hrir_data, 
hrir_total_length - hrir_copied_length);
+hrir_copied_length = hrir_total_length;
+}
+
+pa_memblock_release(hrir_temp_chunk_resampled.memblock);
+pa_memblock_unref(hrir_temp_chunk_resampled.memblock);
+hrir_temp_chunk_resampled.memblock = NULL;
+}
+}
+
+pa_resampler_free(resampler);
+
 pa_memblock_unref(hrir_temp_chunk.memblock);
 hrir_temp_chunk.memblock = NULL;
 
@@ -797,6 +823,9 @@ fail:
 if (hrir_temp_chunk.memblock)
 pa_memblock_unref(hrir_temp_chunk.memblock);
 
+if (hrir_temp_chunk_resampled.memblock)
+pa_memblock_unref(hrir_temp_chunk_resampled.memblock);
+
 if (ma)
 pa_modargs_free(ma);
 
-- 
1.7.12.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH 2/2] module-virtual-surround-sound: limit number of hrir samples

2012-10-05 Thread Niels Ole Salscheider
v2: better log message
---
 src/modules/module-virtual-surround-sink.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/modules/module-virtual-surround-sink.c 
b/src/modules/module-virtual-surround-sink.c
index 50f101d..e5c5dc1 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -724,6 +724,11 @@ int pa__init(pa_module*m) {
  PA_RESAMPLER_SRC_SINC_BEST_QUALITY, 
PA_RESAMPLER_NO_REMAP);
 
 u-hrir_samples = hrir_temp_chunk.length / pa_frame_size(hrir_temp_ss) * 
hrir_ss.rate / hrir_temp_ss.rate;
+if (u-hrir_samples  64) {
+u-hrir_samples = 64;
+pa_log(The (resampled) hrir contains more than 64 samples. Only the 
first 64 samples will be used to limit processor usage.);
+}
+
 hrir_total_length = u-hrir_samples * pa_frame_size(hrir_ss);
 u-hrir_channels = hrir_ss.channels;
 
-- 
1.7.12.2

___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


Re: [pulseaudio-discuss] [PATCH] add module-virtual-surround-sink

2012-02-25 Thread Niels Ole Salscheider
Hello,

 The resampling is only done at initialization time, so you could use the
 memchunk only locally in pa__init() and copy the data to a plain float
 array in userdata. But I'm not saying that that is necessarily better -
 if you prefer storing the memchunk in userdata, that's ok.

I changed it.

 I had a look at some WAVE documentation[1], and it seems that the file
 may or may not have the channel map information. The channel map
 information is included with files that use the extensible format. The
 documentation says that the extensible format should be used whenever
 the file contains more than 2 channels. It's still not a strict
 requirement.
[...]

You are right, the impulse response files did not use the extensible format. 
I changed this for my impulse responses and now it works as expected.
I think we should just require that the impulse response file uses the 
extensible format.

  And aren't hrir_ss and hrir_map redundant
  anyway - shouldn't the hrir sample spec and channel map be the same as
  what the sink has?

I do not think that they are redundant. The sink's sample spec and channel map 
default to the hrir's but they still can be overwritten by the user.

However, I could modify the hrir_data afterwards so that they match if you 
prefer that solution.

 This isn't really good enough for handling NULL hrir_file. If hrir_file
 is NULL, pa_sound_file_load() won't be called, and that's not good.
 There should be something like this:
 
 if (!(hrir_file = pa_modargs_get_value(ma, hrir, NULL))) {
 pa_log(The mandatory 'hrir' module argument is missing.);
 goto fail;
 }

Fixed.

 hrir_temp_chunk.memblock needs to be set to NULL here, otherwise in case
 of failure it will be unreffed twice.

Fixed.

I have attached a new version of the patch.

Regards,

OleFrom b97e66866ef7a21b874f858ca6a90804ce2470a6 Mon Sep 17 00:00:00 2001
From: Niels Ole Salscheider niels_...@salscheider-online.de
Date: Sun, 8 Jan 2012 21:22:35 +0100
Subject: [PATCH] add module-virtual-surround-sink

It provides a virtual surround sound effect

v2: Normalize hrir to avoid clipping, some cleanups
v3: use fabs, not abs
v4: implement changes proposed by Tanu Kaskinen
v5: likewise
v6: use channel map from hrir file
---
 src/Makefile.am|7 +
 ...rtual-sink.c = module-virtual-surround-sink.c} |  308 +++-
 2 files changed, 249 insertions(+), 66 deletions(-)
 copy src/modules/{module-virtual-sink.c = module-virtual-surround-sink.c} (68%)

diff --git a/src/Makefile.am b/src/Makefile.am
index 603ccc3..9aa31f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1019,6 +1019,7 @@ modlibexec_LTLIBRARIES += \
 		module-loopback.la \
 		module-virtual-sink.la \
 		module-virtual-source.la \
+		module-virtual-surround-sink.la \
 		module-switch-on-connect.la \
 		module-filter-apply.la \
 		module-filter-heuristics.la
@@ -1319,6 +1320,7 @@ SYMDEF_FILES = \
 		module-loopback-symdef.h \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
+		module-virtual-surround-sink-symdef.h \
 		module-switch-on-connect-symdef.h \
 		module-filter-apply-symdef.h \
 		module-filter-heuristics-symdef.h
@@ -1535,6 +1537,11 @@ module_virtual_source_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
 module_virtual_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_virtual_source_la_LIBADD = $(MODULE_LIBADD)
 
+module_virtual_surround_sink_la_SOURCES = modules/module-virtual-surround-sink.c
+module_virtual_surround_sink_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
+module_virtual_surround_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_virtual_surround_sink_la_LIBADD = $(MODULE_LIBADD)
+
 # X11
 
 module_x11_bell_la_SOURCES = modules/x11/module-x11-bell.c
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-surround-sink.c
similarity index 68%
copy from src/modules/module-virtual-sink.c
copy to src/modules/module-virtual-surround-sink.c
index cf11ffa..656af7e 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -3,6 +3,7 @@
 
 Copyright 2010 Intel Corporation
 Contributor: Pierre-Louis Bossart pierre-louis.boss...@intel.com
+Copyright 2012 Niels Ole Salscheider niels_...@salscheider-online.de
 
 PulseAudio is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -37,11 +38,15 @@
 #include pulsecore/rtpoll.h
 #include pulsecore/sample-util.h
 #include pulsecore/ltdl-helper.h
+#include pulsecore/sound-file.h
+#include pulsecore/resampler.h
 
-#include module-virtual-sink-symdef.h
+#include math.h
 
-PA_MODULE_AUTHOR(Pierre-Louis Bossart);
-PA_MODULE_DESCRIPTION(_(Virtual sink));
+#include module-virtual-surround-sink-symdef.h
+
+PA_MODULE_AUTHOR(Niels Ole Salscheider);
+PA_MODULE_DESCRIPTION(_(Virtual surround sink));
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
@@ -54,6 +59,7

Re: [pulseaudio-discuss] [PATCH] add module-virtual-surround-sink

2012-02-23 Thread Niels Ole Salscheider
Hello,

 One question about the processing: does it add any latency?

That depends on the impulse response. In general, the current output sample is 
a weighted sum of the current input sample and some preceding.
Provided that the first values of the impulse response are not equal (or 
approximately) zero there is no added latency.

 The hrir data and the input buffer don't really need to be stored inside
 memchunks. They could be just arrays of floats.

I fixed this for the input buffer but pa_resampler_run stores the hrir data 
inside a memchunk.

 I guess master_channels is unneeded now that it's hardcoded to be 2. And
 this piece of code can be simplified to be just two assignments to dst.

Fixed. Is it ok to assume that the first channel is left and the second is 
right or do I need to get this information from the sink input sample spec?

 Pulseaudio's convention is one more indentation level for the cases
 inside the switch.

 You need to check that hrir_file isn't NULL.

 The hrir_temp_chunk memblock needs to be unreffed also in the fail
 section if it's non-NULL to avoid memory leaks. For that reason the
 memblock pointer also has to be set to NULL here and in the beginning of
 the function.

All fixed. I have attached an updated patch.

 Wouldn't it be better to default to the hrir file channel map? In that
 case the file reading needs to be done before initializing the sink
 channel map.

 Shouldn't the default hrir channel map be hrir_temp_map, i.e. the
 channel map of the file? And aren't hrir_ss and hrir_map redundant
 anyway - shouldn't the hrir sample spec and channel map be the same as
 what the sink has?

That is what I would like to do, too. But the channel map that is returned by 
pa_sound_file_load is wrong. I am not even sure if there is a way to store 
the channel map in the wav header.
Because of that I provided a way to specify the channel map of the hrir wav. 
Is there a better solution?

Regards,

OleFrom c124c11f82051a835e695b94392eba8b63e27254 Mon Sep 17 00:00:00 2001
From: Niels Ole Salscheider niels_...@salscheider-online.de
Date: Sun, 8 Jan 2012 21:22:35 +0100
Subject: [PATCH] add module-virtual-surround-sink

It provides a virtual surround sound effect

v2: Normalize hrir to avoid clipping, some cleanups
v3: use fabs, not abs
v4: implement changes proposed by Tanu Kaskinen
v5: likewise
---
 src/Makefile.am|7 +
 ...rtual-sink.c = module-virtual-surround-sink.c} |  321 
 2 files changed, 265 insertions(+), 63 deletions(-)
 copy src/modules/{module-virtual-sink.c = module-virtual-surround-sink.c} (66%)

diff --git a/src/Makefile.am b/src/Makefile.am
index 603ccc3..9aa31f4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1019,6 +1019,7 @@ modlibexec_LTLIBRARIES += \
 		module-loopback.la \
 		module-virtual-sink.la \
 		module-virtual-source.la \
+		module-virtual-surround-sink.la \
 		module-switch-on-connect.la \
 		module-filter-apply.la \
 		module-filter-heuristics.la
@@ -1319,6 +1320,7 @@ SYMDEF_FILES = \
 		module-loopback-symdef.h \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
+		module-virtual-surround-sink-symdef.h \
 		module-switch-on-connect-symdef.h \
 		module-filter-apply-symdef.h \
 		module-filter-heuristics-symdef.h
@@ -1535,6 +1537,11 @@ module_virtual_source_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
 module_virtual_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_virtual_source_la_LIBADD = $(MODULE_LIBADD)
 
+module_virtual_surround_sink_la_SOURCES = modules/module-virtual-surround-sink.c
+module_virtual_surround_sink_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
+module_virtual_surround_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_virtual_surround_sink_la_LIBADD = $(MODULE_LIBADD)
+
 # X11
 
 module_x11_bell_la_SOURCES = modules/x11/module-x11-bell.c
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-surround-sink.c
similarity index 66%
copy from src/modules/module-virtual-sink.c
copy to src/modules/module-virtual-surround-sink.c
index cf11ffa..78c354e 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -3,6 +3,7 @@
 
 Copyright 2010 Intel Corporation
 Contributor: Pierre-Louis Bossart pierre-louis.boss...@intel.com
+Copyright 2012 Niels Ole Salscheider niels_...@salscheider-online.de
 
 PulseAudio is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -37,11 +38,15 @@
 #include pulsecore/rtpoll.h
 #include pulsecore/sample-util.h
 #include pulsecore/ltdl-helper.h
+#include pulsecore/sound-file.h
+#include pulsecore/resampler.h
 
-#include module-virtual-sink-symdef.h
+#include math.h
 
-PA_MODULE_AUTHOR(Pierre-Louis Bossart);
-PA_MODULE_DESCRIPTION(_(Virtual sink));
+#include module-virtual-surround-sink-symdef.h
+
+PA_MODULE_AUTHOR(Niels Ole Salscheider);
+PA_MODULE_DESCRIPTION(_(Virtual surround sink

Re: [pulseaudio-discuss] [PATCH] add module-virtual-surround-sink

2012-02-17 Thread Niels Ole Salscheider
Hello,

 First complaint: doesn't your git nag about trailing whitespace?

It seems that this was not enabled in my git config (although I cannot remember 
disabling it). I have fixed the mentioned lines.

 current_latency is in module-virtual-sink only for instructive purposes.
 If it's not needed in the filter, it should be removed from the code.

 I think a switch would be nicer than if here.

Both fixed.

 I'd put this variable inside the innermost if, because it's not used
 elsewhere in this function.

I think that is not allowed in C89/C90...

[...]
 My preferences for selecting the channel map and sample spec for the
 sink input and sink are the following:
 
 Sink input:
 Channel map: Always stereo.
 Sample format: Always float32ne.
 Sample rate: Always match the filter sink.
 
 Sink:
 Channel map: Default to the impulse response file channel map. Allow the
 user to override that default with the channels and/or channel_map
 module arguments. pa_modargs_get_sample_spec_and_channel_map() will take
 care of initializing the channel map appropriately.
 Sample format: Always float32ne.
 Sample rate: I'm not quite sure about this. I guess defaulting to the
 master sink rate would be best. The other alternative would be
 defaulting to the impulse response file's rate. The user should be able
 to override the default with the rate module argument.

That sounds sensible. I think at some point I got confused by sink_input being 
the input for the master sink that accepts the output signal I compute.

I hope I got it right now. I have attached a new version of my patch.

Regards,

OleFrom 56ac4d4a95971818657202677bf0646b3626a2a4 Mon Sep 17 00:00:00 2001
From: Niels Ole Salscheider niels_...@salscheider-online.de
Date: Sun, 8 Jan 2012 21:22:35 +0100
Subject: [PATCH] add module-virtual-surround-sink

It provides a virtual surround sound effect

v2: Normalize hrir to avoid clipping, some cleanups
v3: use fabs, not abs
v4: implement changes proposed by Tanu Kaskinen
---
 src/Makefile.am|7 +
 ...rtual-sink.c = module-virtual-surround-sink.c} |  344 
 2 files changed, 288 insertions(+), 63 deletions(-)
 copy src/modules/{module-virtual-sink.c = module-virtual-surround-sink.c} (63%)

diff --git a/src/Makefile.am b/src/Makefile.am
index 521bf50..8f942f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1009,6 +1009,7 @@ modlibexec_LTLIBRARIES += \
 		module-loopback.la \
 		module-virtual-sink.la \
 		module-virtual-source.la \
+		module-virtual-surround-sink.la \
 		module-switch-on-connect.la \
 		module-filter-apply.la \
 		module-filter-heuristics.la
@@ -1309,6 +1310,7 @@ SYMDEF_FILES = \
 		module-loopback-symdef.h \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
+		module-virtual-surround-sink-symdef.h \
 		module-switch-on-connect-symdef.h \
 		module-filter-apply-symdef.h \
 		module-filter-heuristics-symdef.h
@@ -1525,6 +1527,11 @@ module_virtual_source_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
 module_virtual_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_virtual_source_la_LIBADD = $(MODULE_LIBADD)
 
+module_virtual_surround_sink_la_SOURCES = modules/module-virtual-surround-sink.c
+module_virtual_surround_sink_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
+module_virtual_surround_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_virtual_surround_sink_la_LIBADD = $(MODULE_LIBADD)
+
 # X11
 
 module_x11_bell_la_SOURCES = modules/x11/module-x11-bell.c
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-surround-sink.c
similarity index 63%
copy from src/modules/module-virtual-sink.c
copy to src/modules/module-virtual-surround-sink.c
index cf11ffa..d3dfe6f 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -3,6 +3,7 @@
 
 Copyright 2010 Intel Corporation
 Contributor: Pierre-Louis Bossart pierre-louis.boss...@intel.com
+Copyright 2012 Niels Ole Salscheider niels_...@salscheider-online.de
 
 PulseAudio is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -37,11 +38,15 @@
 #include pulsecore/rtpoll.h
 #include pulsecore/sample-util.h
 #include pulsecore/ltdl-helper.h
+#include pulsecore/sound-file.h
+#include pulsecore/resampler.h
 
-#include module-virtual-sink-symdef.h
+#include math.h
 
-PA_MODULE_AUTHOR(Pierre-Louis Bossart);
-PA_MODULE_DESCRIPTION(_(Virtual sink));
+#include module-virtual-surround-sink-symdef.h
+
+PA_MODULE_AUTHOR(Niels Ole Salscheider);
+PA_MODULE_DESCRIPTION(_(Virtual surround sink));
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
@@ -54,6 +59,8 @@ PA_MODULE_USAGE(
   channel_map=channel map 
   use_volume_sharing=yes or no 
   force_flat_volume=yes or no 
+  hrir=/path/to/left_hrir.wav 
+  hrir_channel_map=channel map 
 ));
 
 #define MEMBLOCKQ_MAXLENGTH (16

Re: [pulseaudio-discuss] [PATCH] add module-virtual-surround-sink

2012-01-22 Thread Niels Ole Salscheider
Hello,

 1) Is the license of the HRTF dataset that you use compatible with GPL?

The Listen HRIR dataset is public domain so it is GPL compatible.

The HRIR based on the Kemar dummy head is provided free with no restrictions 
on use, provided the authors are cited when the data is used in any research 
or commercial application.
But there is no need to distribute all HRIRs with pulseaudio. I think a few 
good that are GPL compatible are enough.

 2) Why should we do this advanced downmixing in an optional module?
 I.e., why not just replace the default downmixing algorighm without
 creating a module for that?

Replacing the default downmixing algorithm is not a good idea since this one 
only works for headphones. And you might want to use a simpler one on a low 
end machine since folding needs some cpu cycles.
But if there is a better place to implement this, I am fine with it, too.

I forgot to add a small fix to my last patch; I have attached a new version.

Regards,

OleFrom 4e8a09d44ca8df7a7cc32662d0a784c77f09523c Mon Sep 17 00:00:00 2001
From: Niels Ole Salscheider niels_...@salscheider-online.de
Date: Sun, 8 Jan 2012 21:22:35 +0100
Subject: [PATCH] add module-virtual-surround-sink

It provides a virtual surround sound effect

v2: Normalize hrir to avoid clipping, some cleanups
v3: use fabs, not abs
---
 src/Makefile.am|7 +
 ...rtual-sink.c = module-virtual-surround-sink.c} |  272 +---
 2 files changed, 246 insertions(+), 33 deletions(-)
 copy src/modules/{module-virtual-sink.c = module-virtual-surround-sink.c} (69%)

diff --git a/src/Makefile.am b/src/Makefile.am
index 521bf50..8f942f0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1009,6 +1009,7 @@ modlibexec_LTLIBRARIES += \
 		module-loopback.la \
 		module-virtual-sink.la \
 		module-virtual-source.la \
+		module-virtual-surround-sink.la \
 		module-switch-on-connect.la \
 		module-filter-apply.la \
 		module-filter-heuristics.la
@@ -1309,6 +1310,7 @@ SYMDEF_FILES = \
 		module-loopback-symdef.h \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
+		module-virtual-surround-sink-symdef.h \
 		module-switch-on-connect-symdef.h \
 		module-filter-apply-symdef.h \
 		module-filter-heuristics-symdef.h
@@ -1525,6 +1527,11 @@ module_virtual_source_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
 module_virtual_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_virtual_source_la_LIBADD = $(MODULE_LIBADD)
 
+module_virtual_surround_sink_la_SOURCES = modules/module-virtual-surround-sink.c
+module_virtual_surround_sink_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
+module_virtual_surround_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_virtual_surround_sink_la_LIBADD = $(MODULE_LIBADD)
+
 # X11
 
 module_x11_bell_la_SOURCES = modules/x11/module-x11-bell.c
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-surround-sink.c
similarity index 69%
copy from src/modules/module-virtual-sink.c
copy to src/modules/module-virtual-surround-sink.c
index e7c476e..b3100e4 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -3,6 +3,7 @@
 
 Copyright 2010 Intel Corporation
 Contributor: Pierre-Louis Bossart pierre-louis.boss...@intel.com
+Copyright 2012 Niels Ole Salscheider niels_...@salscheider-online.de
 
 PulseAudio is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -40,11 +41,15 @@
 #include pulsecore/rtpoll.h
 #include pulsecore/sample-util.h
 #include pulsecore/ltdl-helper.h
+#include pulsecore/sound-file.h
+#include pulsecore/resampler.h
 
-#include module-virtual-sink-symdef.h
+#include math.h
 
-PA_MODULE_AUTHOR(Pierre-Louis Bossart);
-PA_MODULE_DESCRIPTION(_(Virtual sink));
+#include module-virtual-surround-sink-symdef.h
+
+PA_MODULE_AUTHOR(Niels Ole Salscheider);
+PA_MODULE_DESCRIPTION(_(Virtual surround sink));
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
@@ -57,6 +62,8 @@ PA_MODULE_USAGE(
   channel_map=channel map 
   use_volume_sharing=yes or no 
   force_flat_volume=yes or no 
+  hrir=/path/to/left_hrir.wav 
+  hrir_channel_map=channel map 
 ));
 
 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
@@ -74,6 +81,21 @@ struct userdata {
 
 pa_bool_t auto_desc;
 unsigned channels;
+unsigned hrir_channels;
+unsigned master_channels;
+
+unsigned *mapping_left;
+unsigned *mapping_right;
+
+unsigned output_left, output_right;
+
+unsigned hrir_samples;
+pa_sample_spec hrir_ss;
+pa_channel_map hrir_map;
+pa_memchunk hrir_chunk;
+
+pa_memchunk input_buffer_chunk;
+int input_buffer_offset;
 };
 
 static const char* const valid_modargs[] = {
@@ -86,6 +108,8 @@ static const char* const valid_modargs[] = {
 channel_map,
 use_volume_sharing,
 force_flat_volume,
+hrir,
+hrir_channel_map

Re: [pulseaudio-discuss] [PATCH] add module-virtual-surround-sink

2012-01-22 Thread Niels Ole Salscheider
Hello,

 OK, so in the future we need a different algorithm for desktop speakers.
 Something like find out stereo sound that, when convolved with the
 HRIR and summed for each ear, produces the same result as the original
 5.1 sound convolved with the appropriate HRIR, but at high-enough
 frequencies only.

That is possible with crosstalk cancellation. It requires knowledge of the 
transfer functions from each speaker to each ear, though. I have no idea how 
well it would work if we just estimate the transfer functions but there seem 
to be commercial products that do so.

 As for the complexity - yes, it can be reduced substantially, because
 you use the simplest possible implementation of convolution with a
 rather long filter. Please try to use FFT-based convolution and
 benchmark.
 
 Or, even better, try to approximate one of the available HRIRs with a
 combination of an IIR filter of some low (4-6) order and a
 fixed-per-channel delay, and hard-code that. As there is no scientific
 way of designing IIR filters with arbitrary impulse response yet, the
 simplest possible way of doing such approximation is to autogenerate
 random IIR filters of a given order, compare their response with the
 desired one, and leave the whole thing running for a day or so until it
 finds something suitable.

Sure, my code is O(n^2) while FFT is O(n log n) but it is somewhat simpler and 
has less overhead.
I will try your proposed alternatives when I find the time to do so (exams are 
coming up).

Regards,

Ole

signature.asc
Description: This is a digitally signed message part.
___
pulseaudio-discuss mailing list
pulseaudio-discuss@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss


[pulseaudio-discuss] [PATCH] add module-virtual-surround-sink

2012-01-08 Thread Niels Ole Salscheider
Hello,

this is the first version of a patch to add module-virtual-surround-sink.

This module provides a virtual surround sound effect by folding the audio 
signal with a measured impulse response.

What do you think?

I have uploaded suitable impulse responses to:
http://stuff.salscheider-online.de/hrir_kemar.tar.gz
http://stuff.salscheider-online.de/hrir_listen.tar.gz

The first archive contains an impulse response for the KEMAR dummy head and is 
quite small. If that impulse response does not work well for you, you can try 
the listen database. This archive contains a folder demos that should help 
you to find a suitable impulse response.

Regards,

OleFrom c391c1ef13e9d6b67303ee56680e2dbadd33ed9f Mon Sep 17 00:00:00 2001
From: Niels Ole Salscheider niels_...@salscheider-online.de
Date: Sun, 8 Jan 2012 21:22:35 +0100
Subject: [PATCH] add module-virtual-surround-sink

It provides a virtual surround sound effect
---
 src/Makefile.am|7 +
 ...rtual-sink.c = module-virtual-surround-sink.c} |  246 +---
 2 files changed, 216 insertions(+), 37 deletions(-)
 copy src/modules/{module-virtual-sink.c = module-virtual-surround-sink.c} (71%)

diff --git a/src/Makefile.am b/src/Makefile.am
index 02635fa..187a6bb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1016,6 +1016,7 @@ modlibexec_LTLIBRARIES += \
 		module-loopback.la \
 		module-virtual-sink.la \
 		module-virtual-source.la \
+		module-virtual-surround-sink.la \
 		module-switch-on-connect.la \
 		module-filter-apply.la \
 		module-filter-heuristics.la
@@ -1316,6 +1317,7 @@ SYMDEF_FILES = \
 		module-loopback-symdef.h \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
+		module-virtual-surround-sink-symdef.h \
 		module-switch-on-connect-symdef.h \
 		module-filter-apply-symdef.h \
 		module-filter-heuristics-symdef.h
@@ -1532,6 +1534,11 @@ module_virtual_source_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
 module_virtual_source_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_virtual_source_la_LIBADD = $(MODULE_LIBADD)
 
+module_virtual_surround_sink_la_SOURCES = modules/module-virtual-surround-sink.c
+module_virtual_surround_sink_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
+module_virtual_surround_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_virtual_surround_sink_la_LIBADD = $(MODULE_LIBADD)
+
 # X11
 
 module_x11_bell_la_SOURCES = modules/x11/module-x11-bell.c
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-surround-sink.c
similarity index 71%
copy from src/modules/module-virtual-sink.c
copy to src/modules/module-virtual-surround-sink.c
index e7c476e..a5ca837 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -3,6 +3,7 @@
 
 Copyright 2010 Intel Corporation
 Contributor: Pierre-Louis Bossart pierre-louis.boss...@intel.com
+Copyright 2012 Niels Ole Salscheider niels_...@salscheider-online.de
 
 PulseAudio is free software; you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -40,11 +41,13 @@
 #include pulsecore/rtpoll.h
 #include pulsecore/sample-util.h
 #include pulsecore/ltdl-helper.h
+#include pulsecore/sound-file.h
+#include pulsecore/resampler.h
 
-#include module-virtual-sink-symdef.h
+#include module-virtual-surround-sink-symdef.h
 
-PA_MODULE_AUTHOR(Pierre-Louis Bossart);
-PA_MODULE_DESCRIPTION(_(Virtual sink));
+PA_MODULE_AUTHOR(Niels Ole Salscheider);
+PA_MODULE_DESCRIPTION(_(Virtual surround sink));
 PA_MODULE_VERSION(PACKAGE_VERSION);
 PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
@@ -57,6 +60,8 @@ PA_MODULE_USAGE(
   channel_map=channel map 
   use_volume_sharing=yes or no 
   force_flat_volume=yes or no 
+  hrir=/path/to/left_hrir.wav 
+  hrir_channel_map=channel map 
 ));
 
 #define MEMBLOCKQ_MAXLENGTH (16*1024*1024)
@@ -74,6 +79,19 @@ struct userdata {
 
 pa_bool_t auto_desc;
 unsigned channels;
+unsigned hrir_channels;
+unsigned master_channels;
+
+unsigned *mapping_left;
+unsigned *mapping_right;
+
+unsigned hrir_samples;
+pa_sample_spec hrir_ss;
+pa_channel_map hrir_map;
+pa_memchunk hrir_chunk;
+
+pa_memchunk input_buffer_chunk;
+int input_buffer_offset;
 };
 
 static const char* const valid_modargs[] = {
@@ -86,6 +104,8 @@ static const char* const valid_modargs[] = {
 channel_map,
 use_volume_sharing,
 force_flat_volume,
+hrir,
+hrir_channel_map,
 NULL
 };
 
@@ -202,9 +222,15 @@ static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk
 struct userdata *u;
 float *src, *dst;
 size_t fs;
-unsigned n, c;
+unsigned n;
 pa_memchunk tchunk;
 pa_usec_t current_latency PA_GCC_UNUSED;
+
+unsigned j, k, l;
+float sum_right, sum_left;
+float current_sample;
+float *hrir_data;
+float *input_buffer_data