The allpass filter is known as a filter which has unity gain at each frequency, while whose phase response can be arbitrary. There are many types of implementation of the allpass filter, while some of them seem to be strane of wrong. I would like to introduce some of them in this article.
The original Freeverb's reverb implementation is based on the algorithm proposed by Schroeder and has eight parallel comb filters followed by four series allpass filters. But the allpass implementation code below in Freeverb seem to be strange.
// FreeverbSource/Components/allpass.hpp inline float allpass::process(float input) { float output; float bufout; bufout = buffer[bufidx]; undenormalise(bufout); output = -input + bufout; buffer[bufidx] = input + (bufout*feedback); if(++bufidx>=bufsize) bufidx = 0; return output; }
The frequency response of this code (feedback=0.5) is shown below, which should be flat.
After some research, you will notice that the original freeverb's allpass is just an sum of inverse input plus positive feedback comb filter. I do not know why Jezar has implemented the allpass filter in this way, but this is not the true allpass filter. The calculation reduction may be the reason. In conclusion, the code below sould be the right implementation, whose frequency response is flat.
// FreeverbSource/Components/allpass.hpp inline float allpass::process(float input) { float output; float bufout; bufout = buffer[bufidx]; undenormalise(bufout); buffer[bufidx] = input + (bufout*feedback); output = -buffer[bufidx]*feedback + bufout; if(++bufidx>=bufsize) bufidx = 0; return output; }
This strange implementation is decribed here. It says that the true allpass filter is obtained if g = (sqrt(5)-1)/2 ~ 0.618 (reciprocal of the golden ratio) while that of freeverb is 0.5.
inline _fv3_float_t process(_fv3_float_t input) { if(bufsize == 0) return input; _fv3_float_t bufout = buffer[bufidx]; UNDENORMAL(bufout); buffer[bufidx] = input + bufout * feedback; _fv3_float_t output = bufout - buffer[bufidx] * feedback; bufidx ++; if(bufidx >= bufsize) bufidx = 0; return output; }