Dattorro reverb improvements

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Hello everybody,
I just implemented Dattorro's reverb, which sounds really cool, especially for the low number of delay lines/operations involved. One can this reverb out there :
https://khoin.github.io/DattorroReverbNode/
I wonder if there were some clues to improve this reverb ?
Especially, I noticed the side information is omitted as the reverb just process the mono signal to generate both L and R.
I tried some topology changes in order to include the side part of the input, but whenever I do them the response is not as smooth (decay time is not smooth, or the spectrum is not flat anymore)
I guess Dattorro took a while to tune up every constant, but the fact that the amount of reverb would be related to the mononess of the signal doesn't sound quite logical.
I did some FDN implementation too, with hadamard config. It works fine, but a bit more cpu intensive. :) And finally I liked much the sound of this Dattorro's reverb.
Cheers,
Louis Couka
http://louiscouka.net/ (under construction)

Post

Right, so this type of reverb is usually known as a "figure-8" and you can make such a design "stereo" by duplicating the input diffusion twice with slightly different delay lengths and then injecting them to different parts of the loop, eg. send one of the inputs to one side and the other to the other side after doing the feedback cross-mix. The general design here (after the input diffusion, by a simple chain of all-pass filters in the case of the original) is two chains of all-pass combs, each with some bulk loop-delay and a cross-mixing feedback and you can adjust the number and length of the all-pass filters to change how it sounds. In a sense it's a 2-wide FDN where the delays have been cascaded with a bunch of all-pass filters (which is something you can do with wider FDNs as well; whether it's the best way to go around is another question).

That said, the hard part of any reverb design is tuning, which is somewhat of a trial-and-error process (at best you develop some intuition of how to adjust after playing with them long enough) of figuring out a good set of delays. On the bright-side, figure-8 designs tend to be a bit easier to tune compared to FDNs. You can also make tuning of the damping a bit easier if you borrow the FDN concept of damping all the delays (though if you do this in all-pass filters they won't be quite all-pass anymore so it's bit of a double-edged sword), rather than trying to have overall bulk damping in the loop, but overall there's no real magic bullet to these: algorithmic reverbs do require a fair bit of time spent tuning, listening, retuning ...

Post

Right, so this type of reverb is usually known as a "figure-8" and you can make such a design "stereo" by duplicating the input diffusion twice with slightly different delay lengths and then injecting them to different parts of the loop, eg. send one of the inputs to one side and the other to the other side after doing the feedback cross-mix.
Yes that's exactly what I was trying to do when I was saying doing some topology changes. :)
I also tried to do those injections such the L->R and R->L have a little delay compared to the L->L and R->R impulse responses, to emphasise the wideness via some kind of precedence hass effect. I was quite disappointed since the result was not really confortable, compared to the original mono straightforward version.
You can also make tuning of the damping a bit easier if you borrow the FDN concept of damping all the delays
Yes I was thinking about this too, the drawback I see in such a strategy is that you will add a lot of filters. What make the Dattorro structure cool as well is its tiny structure, but absolutly it's still an idea.

It's also an idea of improvment to replace the input diffuser by some kind of fdn diffuser in which each pole of the modal decomposition would have the same damping value, to avoid some potential coloration in the tail. (just a supposition, I never tried it out). I know Sean Costello doesn't use allpass for diffusers, he said it many times, but I have no idea of what it could really be yet, perhaps this or something FFT based.
(though if you do this in all-pass filters they won't be quite all-pass anymore so it's bit of a double-edged sword)
I don't see the double edged sword side, for me all pass property is only required for an infinite decay, which of course you don't want for the final settings.
That said, the hard part of any reverb design is tuning, which is somewhat of a trial-and-error process (at best you develop some intuition of how to adjust after playing with them long enough) of figuring out a good set of delays. On the bright-side, figure-8 designs tend to be a bit easier to tune compared to FDNs.
Great to know, I'll try to tweak the settings a bit more then.
When I was first studying Reverb I though it would have been easy. :?
In a sense it's a 2-wide FDN where the delays have been cascaded with a bunch of all-pass filters (which is something you can do with wider FDNs as well; whether it's the best way to go around is another question).
I see what you mean, especially I was looking at some conf given by Sean Costello, and he dropped some clues at 1:17
https://www.youtube.com/watch?v=aJLhqfHrwsw&t=4650s
Actually it's a 4X4 FDN with 12 allpass in it. The matrix is a householder one, such it's really fast to compute, if you take the factorization given by : https://ccrma.stanford.edu/~jos/pasp/Ho ... atrix.html
(+ you have the maximally diffuse property for 4X4 version)
He also mentions that he was released a reverb with this scheme in 2009, the year he released the alg. for EOS audio damage which sounds damn great.
Then I also implemented this structure and finally I was quite disappointed by the sound but I didn't tried to tune anything, I just put random values, weither prime or coprime or just random. I guess I was missing some kind of magic powder.
Louis Couka
http://louiscouka.net/ (under construction)

Post

If you want to go FDN, in my experience fast Hadamard transform (or some such similar pair-wise rotation scheme) is usually what you want to use for the feedback.

edit: Not sure what Valhalla reverbs us for diffusion, but one option is to use a feed-forward network where you basically treat a (mono) signal as 2D vector, rotate it, delay one of the components, rotate again, delay one of the components and so on. Assuming the delay lengths are chosen to be coprime, each addition delay doubles the number of reflections and the signal stays "all-pass" in MIMO sense. With pi/2 rotations all the echoes are the same magnitude (assuming no damping), but you can also generate more varied patterns by varying the rotation angle.

Post

Well, I'm trying more deeply the 2 diffusers method. it's not that easy, as when you sum up two allpass you get phase cancellations, it can easily colour the reverb if you're not careful where the entry points are in the tank. The second pb is that to feed the tank in an unbalanced manner (for instance if you feed one part with the L+diffuser, and the other with the R+diffuser) will make the output bounce from R to L (or inverse), with the actual output scheme from Dattorro. So perhaps the output tap values have to be more balanced between R and L instead of what Dattorro proposed, if ever you do the 2 diffusers trick.

Another strategy would be to duplicate the Dattorro's Reverb such you can process the side part and then sum up with the mono reverb part. Which would be a quite heavy because it makes 2 reverbs to compute.
If you want to go FDN, in my experience fast Hadamard transform (or some such similar pair-wise rotation scheme) is usually what you want to use for the feedback.
Yes I did the Hadamard fast transform. Actually Python is so slow that the native matrix multiplication was faster than an handcrafted hadamard fast alg in Python. And it was giving a great sounding result, I had to use N=32, to get a well dense noise sound, perhaps you can go lower if you add modulation. The transient is sharp, perhaps too much, instead of the Dattorro's IR. I guess this is due to the maximal diffuse property of the hadamard matrix. but combining it with the Dattorro's diffuser it certainly can do some magic.

I was liking a lot the tiny structure of the figure of eight scheme which should be really easy on cpu, that's why I focussed my attention on it :)

I guess you can also extract some parameters with the amount of rotation you put in the hadamard transform, I read something like this on another topic on kvr. (like diffusion amount, or crossover L/R amount)
edit: Not sure what Valhalla reverbs us for diffusion, but one option is to use a feed-forward network where you basically treat a (mono) signal as 2D vector, rotate it, delay one of the components, rotate again, delay one of the components and so on. Assuming the delay lengths are chosen to be coprime, each addition delay doubles the number of reflections and the signal stays "all-pass" in MIMO sense. With pi/2 rotations all the echoes are the same magnitude (assuming no damping), but you can also generate more varied patterns by varying the rotation angle.
I read your post about it in another topic. I was quite suprised about this technique I never heard about it except from your post and even by reading it right now, I can't figure out how it's working. (I think understand the alg itself but not the way it works). Did you learn it in a black magic book ? :P

Thanks for your help anyway,
Louis Couka
http://louiscouka.net/ (under construction)

Post

Louis Couka wrote: Mon Apr 19, 2021 9:35 pm I read your post about it in another topic. I was quite suprised about this technique I never heard about it except from your post and even by reading it right now, I can't figure out how it's working. (I think understand the alg itself but not the way it works). Did you learn it in a black magic book ? :P
I honestly can't remember where I got it from, might have been from a KVR post by someone else (Sean?).

Post

mystran wrote: Mon Apr 19, 2021 10:41 pm I honestly can't remember where I got it from, might have been from a KVR post by someone else (Sean?).
If you come across it again, please share!

I'm writing up the generalised form of this (as a blog-post) at the moment - it's pretty simple to construct from the maths, which is how I ended up with it, but it's always reassuring when you can link to someone else doing the same thing.

Post

I'm trying it right now, and it works pretty well, you can get dense/sparse diffusion really easily in function of how you set your delays, and with so few iterations. :o This is a genious trick. Thank so much for it, it could be the one behind the Valhalla Diffuser.
Signalsmith, I can't wait to see your maths explanation behind this. Awesome blog ! :)
Louis Couka
http://louiscouka.net/ (under construction)

Post

signalsmith wrote: Tue Apr 20, 2021 10:45 am I'm writing up the generalised form of this (as a blog-post) at the moment - it's pretty simple to construct from the maths, which is how I ended up with it, but it's always reassuring when you can link to someone else doing the same thing.
Here's a general version: both unitary transforms and pure delays are linear and preserve the L2 norm. These two conditions together are sufficient that any arbitrary signal-flow graph that only consists of unitary transforms, pure delays and simple signal-paths (ie. no branches, merging paths or dead-ends; this is basically the same as a linear type-system where every variable must be used exactly once) is necessarily an all-pass in the MIMO sense (or "lossless" if connected into a closed loop).

These conditions are not necessary for a system to be all-pass, but they are sufficient. For example a standard Schroeder all-pass normally doesn't have a unitary matrix, so the signal in the delay line has a scaling factor that depends on the cofficient (which doesn't matter if the coefficient is constant), but we could factor this scaling out and normalize the transform if we wanted to (eg. to avoid transient issues when changing the coefficient). Since we can build any all-pass filter out of unitary transforms and pure-delays (eg. normalized ladders are one simple way to do it), we can also allow arbitrary all-pass filters as building blocks directly (even if implemented in other ways).

The nice thing about these conditions being sufficient though is that you can randomly [edit: and I literally mean randomly as in you can use a PRNG or whatever to do it for you] connect delays (and all-pass filters) with unitary transforms like toy bricks and never get anything that isn't allpass (obviously ignoring numerical precision). Both FDNs and (lossless) figure-8 are simple special cases, but so is the "feedfoward diffusor" I mentioned above.

ps. There's a cool additional benefit from having all your transforms be unitary such that the L2 norm is preserved in the global sense though: if you can change the transforms over time (as long as they remain unitary) and not lose or gain energy (which in practice means more or less the same as "no ugly transient responses").
Last edited by mystran on Wed Apr 21, 2021 7:54 am, edited 1 time in total.

Post

but one option is to use a feed-forward network where you basically treat a (mono) signal as 2D vector
When you say you treat it as a 2D, was you thinking at one of the scheme bellow ?

Code: Select all

0 1 2 3 4 5
to :

Code: Select all

0 2 4
1 3 5
or :

Code: Select all

0 1 2 3 4 5
0 1 2 3 4 5
What I implemented yet is the first version but I just realized it was not time invariant. As the IR of the system will be different if you trigger the impulse at an even or odd sample time.
Now If I do the second scheme perhaps it will be time invariant but I'll certainly lose the lossless property.
Louis Couka
http://louiscouka.net/ (under construction)

Post

Louis Couka wrote: Tue Apr 20, 2021 7:29 pm
but one option is to use a feed-forward network where you basically treat a (mono) signal as 2D vector
When you say you treat it as a 2D, was you thinking at one of the scheme bellow ?
No. What I mean is that you take signal and make it a vector signal by adding another "channel" (which you can set to zero initially) such that each of the samples is now a 2-component vector. You can then rotate each of these vector valued samples and you can delay one component more than the other.

Post

Ok got it thanks. :) And then finally you sum it I guess ? to get your 1D vector back.
Louis Couka
http://louiscouka.net/ (under construction)

Post

Louis Couka wrote: Tue Apr 20, 2021 8:06 pm Ok got it thanks. :) And then finally you sum it I guess ? to get your 1D vector back.
Well, if you sum it back to 1D (or throw away one of the components) then it's no longer spectrally white.

Post

Louis Couka wrote: Mon Apr 19, 2021 9:35 pm
edit: Not sure what Valhalla reverbs us for diffusion, but one option is to use a feed-forward network where you basically treat a (mono) signal as 2D vector, rotate it, delay one of the components, rotate again, delay one of the components and so on. Assuming the delay lengths are chosen to be coprime, each addition delay doubles the number of reflections and the signal stays "all-pass" in MIMO sense. With pi/2 rotations all the echoes are the same magnitude (assuming no damping), but you can also generate more varied patterns by varying the rotation angle.
I read your post about it in another topic. I was quite suprised about this technique I never heard about it except from your post and even by reading it right now, I can't figure out how it's working. (I think understand the alg itself but not the way it works). Did you learn it in a black magic book ? :P
That sounds like Miller Puckette to me: http://msp.ucsd.edu/techniques/v0.11/bo ... de111.html

Post

Louis Couka wrote: Mon Apr 19, 2021 7:20 pm Yes I was thinking about this too, the drawback I see in such a strategy is that you will add a lot of filters. What make the Dattorro structure cool as well is its tiny structure, but absolutly it's still an idea.
The filters (typically one-poles) should be free on modern CPUs. The CPU cost boils down to the memory accesses and how well you take advantage of the cache. Whatever you do though, anything that has a core of say 6-16 delays (not counting diffusion) should be totally fine, CPU-wise. You could even use a lot more, but I doubt it will help perceptually.

Richard
Synapse Audio Software - www.synapse-audio.com

Post Reply

Return to “DSP and Plugin Development”