Haven’t tried it out, but I think the way you use the coefficient is unlikely to work. It’s not simply a “frequency” inpup which one would modulate directly, but rather you need to calculate the coefficent from the corner frequency, according to some function that one usually looks up somewhere. So if that function is c, then modulation would work something like c(freq + mod), not (as I think you did) mod + c.
I’m not terribly competent with dsp stuff but I’ve just reviewed basic filters a few weeks ago, and I also like phasers so I did some messing around with allpasses, too.
As a collection of formulas, this one is good: Audio EQ Cookbook; it’s what SC’s BEQsuite uses.
As for the math, I’ve found the relevant chapters in Pirkle’s “DSP in cpp” book helpful and “accessible”… but what’s accessible always depends on where one is at.(Pirkle’s allpass formulas seem to be broken, though, at least for the edition I have).
It’s now working quite nicely and I’ve updated the git repo. Feel free to give it a go and let me know what you think. There is also an argument for the number of stages, for now I’ve limited it to be between 2 and 8. So my next question would be - if you change the number of stages while a synth is running, the phaser seems to “start again” - anyone have any ideas how to make it crossfade from one to the other?
EDIT: seems like this would be computationally pretty expensive for what i assume would be quite a marginal gain…but if anyone wants to correct me on this please feel free
@dietcv - I tried out that formula but it didn’t work initially and I didn’t spend too much time on it. Is it possible it should be (input + (prevInput * coef)) * coef.neg + prevOutput;
The formula as you had it at the beginning is correct for a first-order allpass.
For all passes of order n, there’s this neat rule that the i-th feedback coefficient is the m-i th feedworward coefficient, so the transfer function will always look like
and also, the first feedback coefficient (a_0 here) is always 1 for these, so for your one pole, that gets you
1 + a_1 * z^-1
------------------
a_1 + 1 * z^-1
And for the DE, that gets you:
y[n] = a_1*x[n] + x[n-1] - a_1*y[n-1]
where a_1 is your coeff, y[n] is out, y[n-1] is prevOut, x[n] is in ; which you can rewrite as
out = (in - prevout) * coeff + prevIn
which is what you had at the beginning…
As for the changing no of stages while synth is running, I don’t think that will ever really work smoothly. It’s also not so important, because afaik all that additional cascaded stages will do is add more phase shift. (I.e., two first-order apfs in series would be the same amount of phase shift as one second order apf.) What you might be able to do is build the thing with second order filters, which have a “Q” parameter, and cascade a bunch of them; then just increasing the Q on all of them simultaneously (which can be done more or less smoothly) should get you roughly (or exactly?) the same outcome as if you were continuously increasing the number of stages.
Ive looked at the EQ cookbook once more and the go biquad allpass, the cofficients for the biquad allpass (2nd-order) should be correct like this (b2 collapses to 1)
(
var biquadAllpassCoeffs = { |freq = 440, q = 0.5|
var omega = freq.abs * 2pi / s.sampleRate;
var alpha = (0.5 * sin(omega)) / q.abs;
var a0 = 1 + alpha;
var b0 = (1 - alpha) / a0;
var b1 = (-2 * cos(omega)) / a0;
var b2 = 1;
var a1 = (-2 * cos(omega)) / a0;
var a2 = (1 - alpha) / a0;
(
b0: b0,
b1: b1,
b2: b2,
a1: a1,
a2: a2
);
};
biquadAllpassCoeffs.(440, 0.5);
)
I think that the Number of Filters don’t have to be modulatable. Would be Fine if you select those with synthdef Evaluation. Whats probably more interesting is to put some non-linearity into the Feedback path.
It’s working ok now. Up to 8 2nd Order APFs with a q parameter, I haven’t tested this much yet.
Instead of a rate argument, there’s now a freq argument, so you can BYO LFO and freq range.
I also included three potential different nonlinearities in the feedback path - cubic, tanh and wavefolding similar to Fold.ar. It can generate some pretty cool sounds but please be careful with volume, I haven’t yet worked out how to get the cubic distortion to behave itself. If you (or anyone) wants to test it out I’d love that.
I haven’t added proper sloping yet so I’m not sure if modulating certain parameters might be an issue but my first tests haven’t found anything.
I’m wary of using too much from Jatin, since his ChowPhase is also an 8 stage phaser with a nonlinearity in the feedback path…getting close to plagiarism here
I need to get better at understanding max patches but the idea of putting an allpass with non-linearity in the feedback path is pretty funny, might try it out the next few days.