FFTRumble Measure the power below a given pitch
FFTRumble.kr(chain, pitch)
Given an FFT chain, this measures the amount of energy/power below a specified pitch. This pitch can vary dynamically - typically you would use the output from a pitch-tracker such as [Pitch] or [Tartini]. The UGen measures the amount of energy below the fundamental frequency, which you might call a measure of "growl" or "rumble". DC energy is not included.
The optional third argument mode can specify whether the linear (mode=0) or squared (mode=1) magnitudes should be summed.
The optional fourth argument normalise can specify whether the power is normalised, by dividing by the power for the whole spectrum.
You may wish to normalise this against the overall spectral power, using [FFTPower].
You may also wish to decrease the frequency argument a little (e.g. multiply by 0.9 as in the example below), to avoid accuracy- and bandwidth-related issues with the fundamental.
Example
// Very artificial example - we'll combine some home-made "rumble" with a sine wave
s.boot;
b = Buffer.alloc(s, 512, 1);
b = Buffer.alloc(s, 1024, 1);
b = Buffer.alloc(s, 2048, 1);
(
x = {
var in, chain, freq, addamount, rumble;
//freq = LFPar.kr(0.3).exprange(100, 1000);
freq = MouseY.kr(1000, 100, 1);
addamount = MouseX.kr(0, 1);
in = SinOsc.ar(freq) + LPF.ar(WhiteNoise.ar(2), freq, addamount);
chain = FFT(b.bufnum, in);
rumble = FFTRumble.kr(chain, freq * 0.9, 0);
Out.ar(0, in.dup * 0.1);
rumble.poll(10);
}.play(s);
)
x.free;
c = Buffer.read(s, Local.soundsamples ++ "voqual/mbfstrppbr.wav");
c = Buffer.read(s, Local.soundsamples ++ "ybd1.wav");
(
x = {
var in, chain, pitch, clarity, rumble, pow, ratio;
in = PlayBuf.ar(1, c.bufnum);
chain = FFT(b.bufnum, in);
# pitch, clarity = Tartini.kr(in);
pitch = OctCorr.kr(chain, pitch);
rumble = FFTRumble.kr(chain, pitch * 0.9, 0, 1);
Out.ar(0, in.dup * 0.8);
rumble.poll(10);
K2A.ar((rumble * (clarity>0) + 1).log)
//}.play(s); //{
}.plot(c.numFrames / c.sampleRate, s, minval:0, maxval: nil)
)
x.free;