Development of Iguanamente: The Delay Section
When I was originally coming up with the algorithm for the Iguanamente, it featured a notch filter that was based on one pole allpass filters you get from differencing the low pass and high pass outputs from a one pole SVF, or by subtracting the input from double the normalized bandpass output from a two pole SVF. I’ll call these integrator based allpass filters, and where I grew up, the notch filters you made with these were usually called phasers. Since I normally do prototyping things in Reaktor 6 before putting code into embedded hardware, I just assumed that when I went to write the C++ code for the daisy that everything would more or less work out the same.
I wanted to try out the fancy DSP library that the Electrosmith built, Daisy SP, so I went ahead and threw in their phaser effect. It seemed like a pretty simple implementation so I thought nothing of it, and booted up the first hardware Iguanamente prototype, only to find it sounded nothing like how I designed it in Reaktor.
Since the phaser is modulated at audio rates, I first assumed that this was just an audio rate limitation on the patch submodule. If the software requires computation time that lowers the sampling rate, it’s not like the daisy is going to tell you after all. But after a bit more time poking and prodding, I began to realize that the phaser in the DaisySP library was not actually a phaser at all, and instead was a type of flanger! I.e. a delay line based notch filter.
How does this change things? Well for starters, check out the difference between their graphs.
And immediately we see the fact that when we use delays to build up our notch filter, we get repeating, harmonically spaced notches! Not the end of the world, just a bit of a timbre change.
Just to be sure though, we can look at the DaisySP source code and see the PhaserEngine class declares a DelayLine variable in Phaser.h:
DelayLine<float, kDelayLength> del_;
And then here is the code where we actually process it:
float PhaserEngine::Process(float in)
{
float lfo_sig = ProcessLfo();
fonepole(deltime_, sample_rate_ / (lfo_sig + ap_freq_ + os_), .0001f);
last_sample_ = del_.Allpass(in + feedback_ * last_sample_, deltime_, .3f);
return (in + last_sample_) * .5f; //equal mix
}
But wait, let’s take a closer look at the Allpass method whose value is assigned to last_sample_.
In the delayline file we have this snippet:
inline const T Allpass(const T sample, size_t delay, const T coefficient)
{
T read = line_[(write_ptr_ + delay) % max_size];
T write = sample + coefficient * read;
Write(write);
return -write * coefficient + read;
}
So what’s going on here?
From line one, we read from our delay line:
We then write our input, added together with the value we just read, multiplied by a constant:
And then finally, we take that value we just wrote, scale it by the negative of that coefficient, and add it to the value we read earlier, which was just the output of the delay line before we moved the index around:
Now the astute observer might recognize this as a Schroeder Allpass Section which is used in reverb algorithms! (And Iguanamentes of course) You can read more about those here: https://ccrma.stanford.edu/~jos/pasp/Schroeder_Allpass_Sections.html
So then, to go from this allpass filter to the multinotch filter that we saw earlier, all that’s required is to average this output with the dry signal, and the phases will cancel as we expect!
So in the end, I actually really enjoyed the character of the full Iguanamente algorithm with this delay based notch filter, and it made it into the middle filter section (shown below) of the final product!
Also note that this post was written in May 2026, so the good people at Electrosmith may decide to update this in the future. https://github.com/electro-smith/DaisySP/tree/master