FFTSubbandPower - Spectral power, divided into subbands


#[power1, power2, ... powerN+1] = FFTSubbandPower.kr(chain, [cutfreq1, cutfreq2, ... cutfreqN], square, scalemode)


Calculates the spectral power measure, in the same manner as FFTPower, but divides the spectrum into (adjacent, non-overlapping) subbands, so returns separate power measures for the different subbands.


The cutfreqs parameter must be an array of frequencies. For example, to divide a 44100Hz signal into three subbands we might specify  [ 5512, 11025 ]  as the cutfreqs, giving subbands of 0-5512Hz, 5512-11025Hz, and 11025-22050Hz. (Frequencies above the Nyquist frequency are not included.)


The third parameter square performs the same role as in FFTPower.


The fourth parameter scalemode specifies how the band powers are scaled:



cutfreqs, square and scalemode can only be specified on initialisation - they can't be modulated.



Examples


// Simple example

s = Server.local.boot; //Server.internal.boot;

b = Buffer.alloc(s,2048,1);

(

x = {

var in, chain, powers, cutfreqs;

in = LPF.ar(WhiteNoise.ar, MouseX.kr(10,10000, 1));

chain = FFT(b.bufnum, in);


powers = FFTSubbandPower.kr(chain, [100, 200, 400, 800, 1600, 3200, 6400, 12800]);


Out.ar(0, in * 0.1);

powers.collect{|pow, index| pow.poll(label: "band"+index)};

powers.sum.poll(label: "sum");

FFTPower.kr(chain).poll(label: "pow");

}.play(s);

)


x.free;



In this next example we create a graphic EQ meter. The subband power measurements are written out to a control bus, then on the language side we create a task which polls the values and updates a multi-slider to display the power distribution in the familiar home hi-fi style.


s = Server.local.boot;

b = Buffer.alloc(s,2048,1);

(

var win, size=8;

c = Bus.control(s, size); // Values will be written to control busses

win = SCWindow("EQ meter", Rect(100, 200, 360, 110));

~slider = SCMultiSliderView(win, Rect(0, 0, 350, 100));

~slider.value_(0.dup(size)).size_(size).isFilled_(true).indexThumbSize_(350/8);

win.front;

)

(

var size=8;

x = {

var in, chain, powers, cutfreqs;

in = BPF.ar(WhiteNoise.ar, MouseX.kr(10,14000, 1), MouseY.kr(0.1, 2, 1));

chain = FFT(b.bufnum, in);

cutfreqs = [100, 200, 400, 800, 1600, 3200, 6400];

powers = FFTSubbandPower.kr(chain, cutfreqs, 1, 2);

Out.ar(0, (in * 0.1).dup);

Out.kr(c.index, powers);

}.play(s);


t = Task({

loop{

0.1.wait;

c.getn(size, {|vals| {

~slider.value_((vals.log2 + 7 * 0.08).max(0).min(1));

}.defer});

};

}).start;

)


x.free;

t.stop;