Software "pseudo-float": a real number represented as a signed 16-bit mantissa plus a 16-bit exponent (value = mantissa * 2^exponent), computed with integer multiply/shift/compare only – no hardware floating-point instructions. This generalizes speexdsp's classic fixed-point trick of tracking a handful of wide-dynamic-range control variables as a normalized mantissa+exponent pair into a full, operator-overloaded numeric type usable as a drop-in replacement for float (see MDFFixedPoint in MDFEchoCancellation.h, which uses this class as the element type for the MDF echo canceller's sample/spectrum arrays and internal state, so the whole algorithm runs without native float arithmetic).
More...
Software "pseudo-float": a real number represented as a signed 16-bit mantissa plus a 16-bit exponent (value = mantissa * 2^exponent), computed with integer multiply/shift/compare only – no hardware floating-point instructions. This generalizes speexdsp's classic fixed-point trick of tracking a handful of wide-dynamic-range control variables as a normalized mantissa+exponent pair into a full, operator-overloaded numeric type usable as a drop-in replacement for float (see MDFFixedPoint in MDFEchoCancellation.h, which uses this class as the element type for the MDF echo canceller's sample/spectrum arrays and internal state, so the whole algorithm runs without native float arithmetic).
Unlike a plain fixed Q-format (a fixed number of fractional bits, which only covers a fixed range/precision trade-off and would over/underflow badly across this algorithm's actual value range – audio samples, FFT magnitudes in the thousands, and adaptation-rate fractions near zero, all flowing through the same arrays), this type renormalizes on every operation, so it tolerates the same wide dynamic range as float, at roughly the precision of a 16-bit mantissa (a relative error on the order of 2^-15, i.e. about 4-5 significant decimal digits – comparable to a compressed/half-precision float).
- Note
- Comparison operators (
<, >, etc.) convert both sides to float and compare natively – they're scalar, infrequent control-flow checks, not the per-element array math this class exists to keep off the FPU, so trading a little purity there for simpler, more obviously correct code is a reasonable trade. Arithmetic that mixes a PseudoFloat with a plain float/double literal (e.g. 0.7f * pseudoFloatValue) also still executes that specific operation using native float arithmetic via the implicit conversions below – avoiding all native float instructions everywhere would require rewriting every numeric literal in the algorithm as a PseudoFloat, which isn't done here. What this class does guarantee is that PseudoFloat-to-PseudoFloat arithmetic – the tight inner loops over whole arrays (FFT bins, filter weights, correlations) that dominate the algorithm's cost – runs on integer mantissa/exponent math throughout.