frac32buffer.bipolar input signal. should be dc-free, if you're not sure, put a highpass in front of it
int32 number of samples at s-rate sample rate
frac32.positive frequency in axoloti format
bool32.pulse trig
frac32.u.map tolerance for the mean value part, best set to intermediate values
spinner Maximum period allowed. Used to discard false readings
spinner Minimum period allowed. Used to discard false readings
float count = 0; // sample counter
float output = 0; // output reading. The period is stored here
int64_t integral = 0; // integral of the signal starting from 0-crossing
int32_t dx = 0; // derivative at zero crossing
int32_t x0 = 0; // value of the signal at previous zero crossing
int64_t ramp = 0; //"tolerance" ramp
bool sign_old = 0; // sign of previous sample
bool sign = 0; // sign of current sample
int32_t in_old; // old input
outlet_smp = output; // output the reading
outlet_f = 268435456.0f / output; // calculate the frequency and output it
outlet_trig = 0;
count += 1.0f; // increase the counter by 1
sign = inlet_in > 0 ? 1 : 0; // calculate the sign of curent input
integral += inlet_in; // integrate the input
ramp += ___SMMUL(
dx, param_tol
<< 2); // integrate the ramp, using the derivative at zero crossing
float intercept = ((float)inlet_in) / ((float)(in_old - inlet_in));
// calculating the exact zero crossing point -> we want higher precision!
// too early
bool trig = (count > attr_min) && ((ramp > 0) ? (integral < ramp ? 1 : 0)
: (integral > ramp ? 0 : 1));
// this condition serves to filter out meaningless zero crossings:
// if count<attr_min it means it's too early to provide a reading (maybe there's
// some noise in the signal) the second condition serves to test if the mean
// value of the signal is sufficiently close to 0 let's be honest: we'll never be
// so lucky to get it exactly to 0, so we'll settle at a sufficiently small value
// how small? it depends on how steep was the signal at zero crossing and on how
// happy we are with approximate readings
if (sign != sign_old) // a zero crossing has occurred
{
if (trig) // if the "condition zero" i've explained before is met, we have a
// readout!
{
outlet_trig = 1;
output = count +
intercept; // readout, accounting for the "snippet" between samples
count = -intercept; // resetting the counter, adding the snippet betweein
// samples
integral = 0; // resetting the integrator
ramp = 0; // resetting the ramp integrator
dx = inlet_in - in_old; // calculating a new derivative at 0x
}
if (count > attr_max) // the reading is taking too long. I'll start counting
// from here without passing the readout.
{
count = -intercept; // resetting the counter
integral = 0; // resetting the integrator
ramp = 0; // resetting the ramp integrator
dx = inlet_in - in_old; // calculating a new derivative at 0x
}
}
sign_old = sign;
in_old = inlet_in;