Hi
I got my Axoloti this week and I am really impressed, especially by the audio quality, the live mode and how fast a patch is compiled and downloaded.
Today I wrote my first custom object. I used bp.axo and the function biquad_bp_coefs from axoloti_filters.h as starting point and was able to make a notch-filter object
... but without understanding al lot of the code, especially the fractional numbers.
Near the surface, the Q5.27-format seems to be used. I came to this conclusion while playing with controlls and hex-displays, where:0x07FFFFFF * 0x07FFFFFF == 0x07FFFFFE
... so 0x07FFFFFF must be interpreted as one.
I come to the same conclusion while looking at the s-rate code in STAR.axo:outlet_result= ___SMMUL(inlet_a<<3,inlet_b<<2);
... so during multiplication a left-shift of 5 positions is needed.
But when I look at method biquad_bp_coefs in axoloti_filters.h, then the term
(1.0 + alpha)
is implemented as: (HALFQ31 + alpha)
,
where the constant HALFQ31 has the value 0x40000000,
so this calculation seems to use the Q2.30-format.
And finally in method biquad_dsp in axoloti_filters.h, the Q4.28-format seems to be used, because after the SMMLA-sequence, the result is shifted to the left about 4 positions:
for (i = 0; i < BUFSIZE; i++) {
int32_t filterinput = inbuffer[i];
int32_t accu = ___SMMUL(coefs->cxn_0, filterinput);
accu = ___SMMLA(coefs->cxn_1, filter_x_n1, accu);
accu = ___SMMLA(coefs->cxn_2, filter_x_n2, accu);
accu = ___SMMLS(coefs->cyn_1, filter_y_n1, accu);
accu = ___SMMLS(coefs->cyn_2, filter_y_n2, accu);
int32_t filteroutput;
filteroutput = accu << 4;
filter_x_n2 = filter_x_n1;
filter_x_n1 = filterinput;
filter_y_n2 = filter_y_n1;
filter_y_n1 = filteroutput;
outbuffer[i] = __SSAT(filteroutput, 28);
}
On the other hand, the filter-output is saturated on position 28, as in the saturation object sat.axo (which would indicate Q5.27).
I need some help to see the concept, e.g. where the format has to be converted. Thanx very much.
Jan
P.S. My next goal is to implement a parametric equalizer object