Deconvolution question

demers's icon

Dear all,

I'm slowly trying to work out how to convert a room response (sweep tone recorded in a room) into an impulse response. The consensus seems to be that one convolves the reversed original sweep tone with the recorded sweep tone to produce the IR, but one source has told me this type of convolution requires a DFT. The operation is intended to move all the components of the recorded sweep back to a single point in time, like a Dirac function. Is Max/MSP capable of such an operation? fft~ seems more like an STFT...

Any wisdom on this matter would be much appreciated!

Jean-Francois Charles's icon

> I would be much easier if there was a non real-time fft object operating on
> large arrays, I don't really know anything about real-time operations with
> blocks.
Did you try [jit.fft]?
J-F.
--
Extreme Time Stretching (update Dec 29th)
http://www.jeanfrancoischarles.com

j.y.bernier's icon

Quote: deadflagblue@gmail.com wrote on Fri, 09 January 2009 07:28
----------------------------------------------------
> This operation can be done with patcher objects but what about the zero padding in real-time??
----------------------------------------------------
Patcher ovelap-add:

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

Patcher C*~ (complex multiply):

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

Patcher convsub~

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

Patcher conv~

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

Suitable for convolutions up to 4096 (2048 impulse response with zero padding). For larger RI sizes, you need to use pfft~

j.y.bernier's icon

Quote: deadflagblue@gmail.com wrote on Fri, 09 January 2009 13:29
----------------------------------------------------
> What are the advantages of using pfft~ over fft~ that allows longer convolutions??
----------------------------------------------------

fft~ has a 4k limit. pfft~ a 64k limit, that is 0.74s at 44.1 for a non circular, zero-padded convolution.

Pierre Alexandre Tremblay's icon

Dear all

I am very, very interested in this thread, can you share your
findings? I am in the same process now and I have to use commercial
deconvolver which is a pain for sharing the IR after...

thanks

pa

Pierre Alexandre Tremblay's icon
j.y.bernier's icon

Quote: deadflagblue@gmail.com wrote on Sun, 11 January 2009 18:14
----------------------------------------------------
> Just one question the overlap-add subpatch got me a bit confused, isn't it there for the zero padding of the input-blocks to length N_h? I thought the overlap-add method is direct (linear) convolution of input blocks then summed together?
----------------------------------------------------
The zero-padding/overlap-add algorithm transforms a circular (periodic) convolution into a linear convolution suitable for example to process an infinite real-time signal with an impulse response,as opposed to processing a single buffer 'one-shot'. The zeropad ensures that the products won't foldback to lower indices.

The pfft~ version is just a bit different, i'll copy it at the end of this post.I use the fft~ version for crosstalk cancelation or HRTF processing where IR are short. The pfft~ version can do some nice convoverbs but latency is terrible of course.

Note that 64k is not enough for sinesweep deconvolution, And convolution is only a step in obtaining inverse IR. Most authors use AURORA plugins for CoolEdit (once a free product, now Adobe Audition). Logic and other studio software now have i.r. processing as an integrated part (see Apple's Impulse Response Utility).

I've thinked about a Java extra-long FFT (we are not concerned by efficiency here). I'm playing with Octave, an opensource Matlab-like, and i think it's a workable choice. Jeremy Bernstein's shell, and filewatch objects can help integration with Max, Maybe there's is a Max/Matlab bridge somewhere.

j.y.bernier's icon

As promised:

Patcher pconvsub~

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

Anthony Palomba's icon

I think your pconv~ got pasted twice.

j.y.bernier's icon

How stupid!

Well, it was just a "pconv~ Buffer 65536 32768" between adc~ and dac~ as a way to illustrate how to invoke the patcher. #3 should always be half of #2.

Pierre Alexandre Tremblay's icon

> Pheww! that was a long post..

but an amazing one! Aliki is my new friend, will report on this
later this month... (trying to finish a piece right now!)

thanks again

pa

j.y.bernier's icon

Thanks a lot deadflagblue. It seems like you've filled my roadmap for two monthes (lol). Since my first goal is learning, getting a working system coming second, this will be:

1) Implement Farina's method for exponential sine sweep deconvolution
2) Compare with direct impulse measurement
3) Use Aliki and compare with above
4) Try to equalize a PC speaker system with inverse filtering plus crosstalk cancelation

Some comments on step 1:

My starting points are Agelo Farina's papers 183-AES24, 154-AES110, AES121 Workshop. I got them being an AES member but you may find them on the internet.

Basically, Angelo exposes the maths for exponential sine-sweeps and shows how it separates inharmonic content when the driver/speaker behaves non linearly. The system IR can be recovered by convolving the recorded response with the test signal's inverse filter, being simply itself equalized and time-reversed.

To cut on time, i use the MATLAB program generate_sinesweeps.m (or the result sinesweeps.wav) given by the RealSimple Project Home Page at the excellent CCRMA. Of course, the sine sweep can be done within Max.

Max plays the file and poke~ the response into a buffer. The buffer is written to a file, processed by Octave/Matlab which writes the result into a second file binded to a Max waveform~.

Above is the sine sweep response. Under, the computed IR. The system in use is my iMac speakers and internal mic, obviously not a setup suitable for step 4 but enough for a test. The picture is only of interest when compared to

where i accidentally overloaded the speakers, producing the harmonics peaks. That's where exponential sweeps shine: non-linearities are rejected into negative times. We can just cut them if interested in first-odrer only, or use the Volterra series expansion as descibed in 154-AES110 (i won't do that).

Here are the steps for deconvolving:

- Read sinesweep and response (same length).

- Equalization: As the exponential sine sweep has a 6db/oct emphasis, a 6db/oct roloff filter (simple differentiator) is needed for equalization. In Matlab/Octave, this is filter ([1,-1,0],[0,0], sinesweep). In Max, this would be a onepole~ or a biquad~ with [1, -1, 0, 0, 0].

- Time-reversal: flipud(sinesweep) in Matlab. In max, this would be mxj buf.Op (reverse).

- Zero-padding: as my test signal contains TWO sweeps, simply zero the second half of both signals [Matlab: sinesweep(L/2+1:L) = 0; response(L/2+1:L) = 0;] Should the buffers contain only one sweep, they'd have to be extended to twice their size. This ensures we do a linear convolution, not a periodic one.

- Convolution: ifft(fft(sinesweep).*fft(response)) in Octave/Matlab. The length of the signal (8 seconds here) would imply a Max external like CNMAT's firbank~ or zippernoise's tconvolution~.

That's it.

I don't publish code for now here because it needs to be further validated (it's easy to get outputs, it's less easy to get correct outputs) and the Max code is pretty uninteresting, made of buffer~, poke~, waveform~ ... The tricky part is the Matlab one (although very short). Some refinements in equalization may be necessary to take in account the band-limited characteristic of the system.

But, who knows, a MaxMSP sine sweep deconvo toolbox may be on the way?

Now heading to step2..........

Roman Thilenius's icon

why build something which already has been built.

why not leave deconvolution to the nineties where it belongs and invent a matter transformer instead.

-110

demers's icon

Hey folks,

I must say I was shocked to see all these responses when I checked back - so long after my original post! I'll have to trudge through all this now, so I'll reserve my thoughts for later.

For now, I just wanted to confirm that I did in fact learn Octave and wrote a routine there for producing IRs. Still tweaking it but I think I have more of a handle on it now.

j.y.bernier, am I correct in assuming that your patches are in fact designed as self-enclosed abstractions? I've been trying to figure out how to produce those (SDK?), so if you have any tips I will certainly welcome them.

Thank you all for not letting this topic fall into the nether regions...