FFTComplexDev - Measure complex deviation of signal
FFTComplexDev.kr(chain, rectify=0, powthresh=0.1)
Calculates the complex deviation of the signal, which is a measure of the total rate of change of the complex spectral components, across all the FFT bins. A stationary signal (such as a steady sine wave) should exhibit zero deviation, because its magnitude remains constant and its phase changes linearly, whereas a non-stationary signal (such as a sine wave of modulating frequency, or more complex changing sound) should exhibit a positive complex deviation.
This measure can be used as a component in onset detection - see [OnsetsDS] - but may also have other applications.
The comparison is frame-by-frame, so its behaviour will depend to some extent upon your frame size. Also note that this measure only makes sense when used with a continuous stream of FFT frames - so it should be used with the normal [FFT] UGen, not with [FFTTriggered].
The optional second argument rectify specifies (at creation time - cannot be modulated) whether all bins whose power is decreasing should be ignored. Set it greater than zero to activate the rectification feature (it's either on or off; no shades of gray).
The other optional argument powthresh tells the UGen to ignore FFT bins where the power is lower than a threshold. (This option can be modulated at control rate.)
For more details about both algorithms (rectified and non-rectified) see
Dixon, S. (2006) Onset Detection Revisited. In Proceedings of the 9th International Conference on Digital Audio Effects (DAFx-06), Montreal, Canada. pp. 133-137.
Examples
These examples use the standard unrectified measure, with a fixed powthresh value. Feel free to dabble with the parameters.
s.boot;
b = Buffer.alloc(s, 512, 1);
// Move the mouse to vary the frequency, and the amount of noise added.
// Watch the scope/post window to see the change in complex deviation.
(
x = {
var in, chain, flux;
in = SinOsc.ar(MouseX.kr(50, 500, 1), 0, 0.1) + WhiteNoise.ar(MouseY.kr(0, 0.1));
chain = FFT(b.bufnum, in);
flux = FFTComplexDev.kr(chain);
flux.poll(10, "Complex deviation");
Out.ar(0, in.dup);
Out.kr(0, flux);
}.play(s);
)
x.free;b.free;
// Load an audio file and plot the complex deviation as a function of time
b = Buffer.alloc(s, 512, 1);
c = Buffer.read(s, "sounds/a11wlk01.wav");
(
x = {
var in, chain, cxdev;
in = PlayBuf.ar(1, c.bufnum, BufRateScale.kr(c.bufnum));
chain = FFT(b.bufnum, in);
cxdev = FFTComplexDev.kr(chain, 0, 10) * 0.1;
cxdev.poll(10, "Complex deviation");
Out.ar(0, in.dup * 0.1);
K2A.ar(cxdev)
}.plot(c.numFrames/c.sampleRate, s);
)
x.free; b.free; c.free;