Dattorro reverb improvements

 KVRist
 Topic Starter
 60 posts since 28 Jul, 2016
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,
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)
http://louiscouka.net/ (under construction)
 KVRAF
 7884 posts since 12 Feb, 2006 from Helsinki, Finland
Right, so this type of reverb is usually known as a "figure8" 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 crossmix. The general design here (after the input diffusion, by a simple chain of allpass filters in the case of the original) is two chains of allpass combs, each with some bulk loopdelay and a crossmixing feedback and you can adjust the number and length of the allpass filters to change how it sounds. In a sense it's a 2wide FDN where the delays have been cascaded with a bunch of allpass 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 trialanderror 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 brightside, figure8 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 allpass filters they won't be quite allpass anymore so it's bit of a doubleedged 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 ...
That said, the hard part of any reverb design is tuning, which is somewhat of a trialanderror 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 brightside, figure8 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 allpass filters they won't be quite allpass anymore so it's bit of a doubleedged 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 ...

 KVRist
 Topic Starter
 60 posts since 28 Jul, 2016
Yes that's exactly what I was trying to do when I was saying doing some topology changes.Right, so this type of reverb is usually known as a "figure8" 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 crossmix.
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.
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.You can also make tuning of the damping a bit easier if you borrow the FDN concept of damping all the delays
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.
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.(though if you do this in allpass filters they won't be quite allpass anymore so it's bit of a doubleedged sword)
Great to know, I'll try to tweak the settings a bit more then.That said, the hard part of any reverb design is tuning, which is somewhat of a trialanderror 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 brightside, figure8 designs tend to be a bit easier to tune compared to FDNs.
When I was first studying Reverb I though it would have been easy.
I see what you mean, especially I was looking at some conf given by Sean Costello, and he dropped some clues at 1:17In a sense it's a 2wide FDN where the delays have been cascaded with a bunch of allpass filters (which is something you can do with wider FDNs as well; whether it's the best way to go around is another question).
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)
http://louiscouka.net/ (under construction)
 KVRAF
 7884 posts since 12 Feb, 2006 from Helsinki, Finland
If you want to go FDN, in my experience fast Hadamard transform (or some such similar pairwise 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 feedforward 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 "allpass" 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.
edit: Not sure what Valhalla reverbs us for diffusion, but one option is to use a feedforward 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 "allpass" 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.

 KVRist
 Topic Starter
 60 posts since 28 Jul, 2016
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.
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)
Thanks for your help anyway,
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.
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.If you want to go FDN, in my experience fast Hadamard transform (or some such similar pairwise rotation scheme) is usually what you want to use for the feedback.
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)
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 ?edit: Not sure what Valhalla reverbs us for diffusion, but one option is to use a feedforward 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 "allpass" 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.
Thanks for your help anyway,
Louis Couka
http://louiscouka.net/ (under construction)
http://louiscouka.net/ (under construction)
 KVRAF
 7884 posts since 12 Feb, 2006 from Helsinki, Finland
I honestly can't remember where I got it from, might have been from a KVR post by someone else (Sean?).Louis Couka wrote: ↑Mon Apr 19, 2021 1: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 ?

 KVRist
 88 posts since 5 Jul, 2018 from Cambridge, UK
If you come across it again, please share!
I'm writing up the generalised form of this (as a blogpost) 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.

 KVRist
 Topic Starter
 60 posts since 28 Jul, 2016
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. 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 !
Signalsmith, I can't wait to see your maths explanation behind this. Awesome blog !
Louis Couka
http://louiscouka.net/ (under construction)
http://louiscouka.net/ (under construction)
 KVRAF
 7884 posts since 12 Feb, 2006 from Helsinki, Finland
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 signalflow graph that only consists of unitary transforms, pure delays and simple signalpaths (ie. no branches, merging paths or deadends; this is basically the same as a linear typesystem where every variable must be used exactly once) is necessarily an allpass in the MIMO sense (or "lossless" if connected into a closed loop).signalsmith wrote: ↑Tue Apr 20, 2021 2:45 am I'm writing up the generalised form of this (as a blogpost) 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.
These conditions are not necessary for a system to be allpass, but they are sufficient. For example a standard Schroeder allpass 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 allpass filter out of unitary transforms and puredelays (eg. normalized ladders are one simple way to do it), we can also allow arbitrary allpass 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 allpass filters) with unitary transforms like toy bricks and never get anything that isn't allpass (obviously ignoring numerical precision). Both FDNs and (lossless) figure8 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 Tue Apr 20, 2021 11:54 pm, edited 1 time in total.

 KVRist
 Topic Starter
 60 posts since 28 Jul, 2016
When you say you treat it as a 2D, was you thinking at one of the scheme bellow ?but one option is to use a feedforward network where you basically treat a (mono) signal as 2D vector
Code: Select all
0 1 2 3 4 5
Code: Select all
0 2 4
1 3 5
Code: Select all
0 1 2 3 4 5
0 1 2 3 4 5
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)
http://louiscouka.net/ (under construction)
 KVRAF
 7884 posts since 12 Feb, 2006 from Helsinki, Finland
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 2component vector. You can then rotate each of these vector valued samples and you can delay one component more than the other.Louis Couka wrote: ↑Tue Apr 20, 2021 11:29 amWhen you say you treat it as a 2D, was you thinking at one of the scheme bellow ?but one option is to use a feedforward network where you basically treat a (mono) signal as 2D vector

 KVRist
 Topic Starter
 60 posts since 28 Jul, 2016
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)
http://louiscouka.net/ (under construction)
 KVRAF
 7884 posts since 12 Feb, 2006 from Helsinki, Finland
Well, if you sum it back to 1D (or throw away one of the components) then it's no longer spectrally white.Louis Couka wrote: ↑Tue Apr 20, 2021 12:06 pm Ok got it thanks. And then finally you sum it I guess ? to get your 1D vector back.
 KVRian
 1091 posts since 8 Feb, 2012 from South  Africa
That sounds like Miller Puckette to me: http://msp.ucsd.edu/techniques/v0.11/bo ... de111.htmlLouis Couka wrote: ↑Mon Apr 19, 2021 1:35 pmI 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 ?edit: Not sure what Valhalla reverbs us for diffusion, but one option is to use a feedforward 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 "allpass" 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.

Richard_Synapse Richard_Synapse https://www.kvraudio.com/forum/memberlist.php?mode=viewprofile&u=245936
 KVRian
 1136 posts since 20 Dec, 2010
The filters (typically onepoles) 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 616 delays (not counting diffusion) should be totally fine, CPUwise. You could even use a lot more, but I doubt it will help perceptually.Louis Couka wrote: ↑Mon Apr 19, 2021 11:20 am 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.
Richard
Synapse Audio Software  www.synapseaudio.com