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
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
uint32_t count = 0; // sample counter
uint32_t 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
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_trig = 0;
count++; // 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
// 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!
{
output = count; // readout
count = 0; // 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
outlet_trig = 1 << 27;
}
if (count > attr_max) // the reading is taking too long. I'll start counting
// from here without passing the readout.
{
count = 0; // 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;