denormals.h
ScopedNoDenormals: turn off denormal arithmetic for the length of a block.
#include <sonore/denormals.h>- 1type
- Guides: Getting started, MIDI and MPE
On this page
Design notes
What this costs when it is missing
A denormal is a floating-point number too small to represent normally, and on x86 the hardware handles them in microcode rather than in the pipeline. The result is not a rounding difference; it is a stall.
Measured on the machine this was written on, eight biquads decaying through silence:
denormals allowed : 5.80 ms FTZ + DAZ set : 2.06 ms ratio : 2.82x
Nearly three times the CPU, for audio nobody can hear -- the tail of a filter forty decades below full scale. And it appears exactly when a track goes quiet, so the plugin that spikes is the one that was doing nothing.
Why the per-sample flush is not enough
dsp.h has flushDenormal(), and the SDK's own filters call it. That protects the code that remembers to call it. It does nothing for a DSP somebody generates tomorrow, and the whole point of this SDK is that the DSP is written by something other than a person who knows about denormals.
A processor-wide flag protects everything in the block, including the arithmetic nobody thought about.
Why it is scoped
The audio thread belongs to the HOST. Leaving its floating-point mode changed after returning would alter arithmetic in code we do not own -- and silently, since flush-to-zero changes results rather than failing. Saved on entry, restored on exit, including when the block throws.
Types 1
Flush-to-zero for as long as this object lives.
Declare one at the top of a process block. It is a handful of cycles to set and a handful to restore, against a stall of hundreds of cycles per denormal operation.