Binaural Convolution

luis693's icon

Hi,

i am trying to convolve a binaurally recorded impulse response and an audio file of your choice using buffir~, buffer, and sfplay to create the effect that the sound is localised somewhere outside the head.

i have attached the patch which is basically taken from buffir~ help and made it possible to import your own audio file and impulse response.

the trouble i'm having is finding out how to make it binaural i.e after changing the source to mono, have the right side of the IR (it's a stereo file) effect only the output you get on the right headphone speaker and left - left, so the left and right are different in the inter-aural time, level and directional filters that will give you a localisation effect.

some help would be very appreciated.

here is the patch

{
"patcher" : {
"fileversion" : 1,
"rect" : [ 25.0, 69.0, 894.0, 744.0 ],
"bglocked" : 0,
"defrect" : [ 25.0, 69.0, 894.0, 744.0 ],
"openrect" : [ 0.0, 0.0, 0.0, 0.0 ],
"openinpresentation" : 0,
"default_fontsize" : 12.0,
"default_fontface" : 0,
"default_fontname" : "Arial",
"gridonopen" : 0,
"gridsize" : [ 15.0, 15.0 ],
"gridsnaponopen" : 0,
"toolbarvisible" : 1,
"boxanimatetime" : 200,
"imprint" : 0,
"enablehscroll" : 1,
"enablevscroll" : 1,
"devicewidth" : 0.0,
"boxes" : [ {
"box" : {
"maxclass" : "flonum",
"numinlets" : 1,
"fontsize" : 12.0,
"numoutlets" : 2,
"patching_rect" : [ 396.0, 336.0, 50.0, 20.0 ],
"outlettype" : [ "float", "bang" ],
"id" : "obj-32",
"minimum" : 0.0,
"fontname" : "Arial",
"maximum" : 1.0
}

}
, {
"box" : {
"maxclass" : "comment",
"text" : "Make audio file Mono. nnnstill need a stereo output for spatialization",
"linecount" : 7,
"numinlets" : 1,
"fontsize" : 12.0,
"numoutlets" : 0,
"patching_rect" : [ 28.0, 234.0, 117.0, 103.0 ],
"id" : "obj-30",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "comment",
"text" : "this obviously hasn't got the different hrtf's for left and right output audio, ILD's or ITD's nnhow do you get these, can't think of a way to seperate right and left IR keeping the ITD's, and there is only one output from buffir. nnPlease can someone help me out with this. nnnthank you in advance for taking a look. ",
"linecount" : 14,
"numinlets" : 1,
"fontsize" : 12.0,
"numoutlets" : 0,
"patching_rect" : [ 203.0, 415.0, 213.0, 200.0 ],
"id" : "obj-29",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "comment",
"text" : "open the audio file to convolve",
"linecount" : 2,
"numinlets" : 1,
"fontsize" : 12.0,
"numoutlets" : 0,
"patching_rect" : [ 124.0, 48.0, 150.0, 34.0 ],
"id" : "obj-28",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "comment",
"text" : "select the impulse response",
"linecount" : 2,
"numinlets" : 1,
"fontsize" : 12.0,
"numoutlets" : 0,
"patching_rect" : [ 409.0, 84.0, 150.0, 34.0 ],
"id" : "obj-27",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "pause",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 203.0, 89.0, 43.0, 18.0 ],
"outlettype" : [ "" ],
"id" : "obj-4",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "0",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 260.0, 88.0, 32.5, 18.0 ],
"outlettype" : [ "" ],
"id" : "obj-5",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "1",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 160.0, 90.0, 32.5, 18.0 ],
"outlettype" : [ "" ],
"id" : "obj-6",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "*~ 0.5",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 141.0, 249.0, 42.0, 20.0 ],
"outlettype" : [ "signal" ],
"id" : "obj-11",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "+~",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 141.0, 216.0, 32.5, 20.0 ],
"outlettype" : [ "signal" ],
"id" : "obj-12",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "open",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 117.0, 88.0, 37.0, 18.0 ],
"outlettype" : [ "" ],
"id" : "obj-18",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "sfplay~ 2",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 3,
"patching_rect" : [ 141.0, 159.0, 59.0, 20.0 ],
"outlettype" : [ "signal", "signal", "bang" ],
"id" : "obj-2",
"fontname" : "Arial",
"save" : [ "#N", "sfplay~", "", 2, 120960, 0, "", ";" ]
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "replace",
"numinlets" : 2,
"fontsize" : 12.0,
"numoutlets" : 1,
"patching_rect" : [ 450.0, 124.0, 50.0, 18.0 ],
"outlettype" : [ "" ],
"id" : "obj-3",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "ezdac~",
"varname" : "autohelp_dac",
"numinlets" : 2,
"numoutlets" : 0,
"patching_rect" : [ 144.0, 510.0, 45.0, 45.0 ],
"id" : "obj-14",
"local" : 1
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "*~ 0.05",
"numinlets" : 2,
"fontsize" : 11.595187,
"numoutlets" : 1,
"patching_rect" : [ 142.0, 390.0, 48.0, 20.0 ],
"outlettype" : [ "signal" ],
"id" : "obj-15",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "comment",
"varname" : "autohelp_dac_text",
"text" : "start audio",
"linecount" : 2,
"numinlets" : 1,
"fontsize" : 11.595187,
"numoutlets" : 0,
"patching_rect" : [ 98.0, 517.0, 38.0, 33.0 ],
"id" : "obj-16",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "panel",
"varname" : "startwinwdow_panel",
"numinlets" : 1,
"border" : 2,
"bgcolor" : [ 1.0, 1.0, 1.0, 1.0 ],
"numoutlets" : 0,
"patching_rect" : [ 94.0, 506.0, 100.0, 55.0 ],
"id" : "obj-17",
"bordercolor" : [ 0.392157, 0.792157, 0.117647, 1.0 ]
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "buffir~ fir_buf 0 10",
"numinlets" : 3,
"fontsize" : 11.595187,
"numoutlets" : 1,
"patching_rect" : [ 141.0, 330.0, 102.0, 20.0 ],
"outlettype" : [ "signal" ],
"id" : "obj-13",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "message",
"text" : "clear",
"numinlets" : 2,
"fontsize" : 11.595187,
"numoutlets" : 1,
"patching_rect" : [ 411.0, 124.0, 36.0, 18.0 ],
"outlettype" : [ "" ],
"id" : "obj-26",
"fontname" : "Arial"
}

}
, {
"box" : {
"maxclass" : "newobj",
"text" : "buffer~ fir_buf 20",
"numinlets" : 1,
"fontsize" : 11.595187,
"numoutlets" : 2,
"patching_rect" : [ 411.0, 171.0, 99.0, 20.0 ],
"outlettype" : [ "float", "bang" ],
"id" : "obj-31",
"fontname" : "Arial"
}

}
],
"lines" : [ {
"patchline" : {
"source" : [ "obj-32", 0 ],
"destination" : [ "obj-15", 1 ],
"hidden" : 0,
"midpoints" : [ 405.5, 370.0, 180.5, 370.0 ]
}

}
, {
"patchline" : {
"source" : [ "obj-11", 0 ],
"destination" : [ "obj-13", 0 ],
"hidden" : 0,
"midpoints" : [ 150.5, 306.0, 150.5, 306.0 ]
}

}
, {
"patchline" : {
"source" : [ "obj-5", 0 ],
"destination" : [ "obj-2", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-4", 0 ],
"destination" : [ "obj-2", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-6", 0 ],
"destination" : [ "obj-2", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-12", 0 ],
"destination" : [ "obj-11", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-2", 1 ],
"destination" : [ "obj-12", 1 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-2", 0 ],
"destination" : [ "obj-12", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-18", 0 ],
"destination" : [ "obj-2", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-3", 0 ],
"destination" : [ "obj-31", 0 ],
"hidden" : 0,
"midpoints" : [ 459.5, 146.0, 420.5, 146.0 ]
}

}
, {
"patchline" : {
"source" : [ "obj-13", 0 ],
"destination" : [ "obj-15", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-15", 0 ],
"destination" : [ "obj-14", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
, {
"patchline" : {
"source" : [ "obj-15", 0 ],
"destination" : [ "obj-14", 1 ],
"hidden" : 0,
"midpoints" : [ 151.5, 418.0, 179.5, 418.0 ]
}

}
, {
"patchline" : {
"source" : [ "obj-26", 0 ],
"destination" : [ "obj-31", 0 ],
"hidden" : 0,
"midpoints" : [ ]
}

}
]
}

}

thank you!

Luis

N.B this is a project, i'm not trying to make anything better than is already out there

Roman Thilenius's icon

i think the minimum responses you should use for a binaural filter is at
least 24 or so ... better 200-500 ... how many samples do you use?

lienar interpolaion between left and right will "move" not at all.

-110

luis693's icon

i am using a 256 sample IR recorded myself using a dummy head and a sine sweep then deconvolved with its inverse and cut down in pro tools to 256 samples.

is what your saying that this should actually work if the IR is right, it looks to me that the same signal is being sent to both left and right dac, meaning it is not infact binaural?

thank you for the quick response, i'll keep a better eye on the thread :)

Roman Thilenius's icon

as i did not look into your patch i understood you only have one response
for hard left and one for hard right, so i wanted to point out that the effect
will only work through movement, i.e. the contrast between the different
angels. :)

since you seem to know all this we can go on step further- i am intrested myself
in such projects: how do you move between the IRs?

recently i posted this abstraction to the forum, maybe it is of some use to you:

110.dekamix~ has been built for things exactly like that.

for 512 channels you might need to extend it a bit, using 0+n*(360/512) as argument
to 110.deg2gain.

the code is straight non-academic.

-110

luis693's icon

at the moment i am stuck in the very beginning of my patch as you can see it's very simple at the moment.

by the looks of one of those patches you posted it seems lie they are for loudspeakers. not sure if i stated earlier that what i am making is for is for reproduction through headphones, which means that it does have to be hard left and right, basically a mono signal convolved with a stereo IR with the left going to the left and right going to the right.

when i listen to this it doesn't sound like it's outside your head as the same signal is going to both the left and right,

once i have the patch working (i.e the signal being convolved when listened to through headphones can be localised outside your own head) then try to see how i could move between different IR's.

also minor question as i'm new to these forums, i'm not getting any email through when there's a reply meaning i keep checking/refreshing?

Luis

luis693's icon

by "this" i meant my patch, just re-read. and after looking it was the first patch which is for loudspeakers.

have just got the ones you posted yourself and will have a look. i'm fairly new to max/msp so we'll see how it goes.

thank you for the help so far

Roman Thilenius's icon

yeah i got you.

well it is for circular panning ... you can use it to driver loudspeakers or to switch/pan
between different FIR/IIR/deconvolution/whatevers inside a DSP code.

for a mono-to-stereo aural filter you would need two of those panners with a 180 degree
offset and it will fit perfectly for this application.

i know that i went one step to fast (because you were asking for somethign different) but
somehow i suggested you to solve these two tasks (how to set up the routing for the
deconvolution and how to move between them) in a single task.

-110

Floating Point's icon

I'm pretty sure you would need to separate your stereo files into two different mono files and then use a different buffir~ for each channel, (I might be wrong as I've never used buffir~, confirmation required)

Max Patch
Copy patch and select New From Clipboard in Max.

Have a look at this:

Roman Thilenius's icon

thats right, except he was so clever and recorded only 180 degrees and
in mono - because that would have been enough ;D

-110

luis693's icon

yes that makes sense, the only part now is the IR's recorded are stereo so the IR would need to also be separated into the left and right channel so the right ear gets convolved with the right side of the IR and left with the left.

i'll split the stereo IR into two Mono L+R and import them separately as for the sound to seem like it is localised outside your head while listening to headphones the left and right need to be convolved with the corresponding IR's (to give the right inter-aural level differences, time differences and the direction dependant filtering between the two ears that takes place when we hear sound)

I also have 11 other IR's from different angles around the head (a dummy head with pinna and omni mic's at the two ear canal entrances), each with a left and a right, so ideally there should be a way to open a stereo audio file (an IR) and store the left channel in a separate buffer than the right?

i'll have a go and see what happens when i split the IR's in the morning. thank you for all the help so far.

anyone reading this interested in listening to a binaural recording check :

luis693's icon

apologies, that one's audio has allot of aliasing going on - poor quality

the quality's much better on this one - use headphones and enjoy :)

Luis

Roman Thilenius's icon

it is possible to import only the right track of a two-channel audio file into
the buffer~ object - but it will be far easier for programming your patch
when split files are already on your disk.

what is the head you are using doing? if i am not mistaken, most dummy heads
will only give you the required delay and phase, but not the frequency filtering
the human ear has, which would be essential for thsi application.

the thing with the phase is half the job of course, but it is not perfect.

you could say it is enough for an effect listened to only on speakers, but not for
the effect you want to have in your headphones.
btw, i just noticed that you were completly right to record it in stereo, you can
skip my comment about this. i was a bit mislead because i forgot what your
recording is all about (i only do rooms).

of course we need the second channel, too.

the only thing i was right about is that 180 degrees are enough, but BECAUSE it is stereo.
-110

luis693's icon

the dummy head has prosthetic pinna (ears) attached to it moulded from the owner of the heads actual ears (small omni mics at the entrance of the ear canal).

the head itself is therefore giving all three things, delay and phase but also an object which filters as some frequencies will go round the head and some will be blocked, also because there are pinna attached the angle which the audio hits the ears will effect the filtering the ears give for different angles.

ah i thought that was where some people might have been coming from :), it's more common on here to find people using room impulse responses which only have to be mono and effect a stereo file. thats most of what i found when i was searching through.

the 12 IR's i have are like a clock face with the dummy head set in the middle, and if this patch works correctly there should (fingers crossed) be a full 360 degree sensation (because of the ears on the dummy head)

ok i'll split the tracks up, this means i might have to use a selector which gets the right L and R from a list, to make it easier to use. i'll work on this and post back, have left my other IR's else where so might be a while :)

Anthony Palomba's icon

I would like to test some of the patches posted here. But I have
no impulses. Does anyone know of any impulses I could test with?

erichonour's icon

There is a pretty extensive set of HRTF measurements of a KEMAR head here:

IRCAM has a database here:

Cheers,
EH