Best way to divide harmonic spectra

Hi,

For my projects I did an FFTOscMaster thing, which sits on the end of an audio chain (inspired by StageMaster quark) and sends the FFT analysis via osc.

The main aim of this is for audio-interactive visuals. I am thinking now, what should be the best way to divide this spectra for eq. bass, midds, trebles, or maybe if I want to have 5 o 7 or more ‘ranges’.
For now I have 255 frequencies, and it not seems to be a good idea do divide it linearily. eq (sum of first 50)/50, and so on…

Do you have any clue where to look for ?
thank you
paum

Our hearing system is very much tuned to frequency ratios. As such it’s probably best to divide the logarithm of frequency in equal bands.

Suppose you consider frequencies between 50Hz and 20000Hz and you want to divide these into 4 bands (I’m just making up numbers for the sake of an example, you can change for your situation).

Then:

log10(50) = 1.7
log10(20000) = 4.3

to divide [1.7, 4.3] into 4 equal parts, you calculate (4.3-1.7)/4 = 0.65 so the four bands will be formed by
1.7 + (0 * 0.65) = 1.7
1.7 + (1 * 0.65) = 2.35
1.7 + (2 * 0.65) = 3.0
1.7 + (3 * 0.65) = 3.65
1.7 + (4 * 0.65) = 4.3

This is still the logarithm of the frequency. To go back to frequency, we need to exponentiate again:

10^(1.7)= 50 Hz
10^(2.35) = 224 Hz
10^(3.0) = 1000 Hz
10^(3.65) = 4467 Hz
10^(4.3) = 20000 Hz

So the four bands are:
50 Hz → 224 Hz
224Hz → 1000Hz
1000Hz → 4467 Hz
4467 Hz → 20000 Hz

If you have frequencies from FFT bins, you can choose the ones that are closest to these calculated results.

Maybe others will have other ideas!

1 Like

Are you computing the FFT specifically for this purpose? If so, then you probably don’t need to take the FFT — just use BPFs and Amplitude.ar. In my experience, people are sometimes too quick to jump to FFT when time-domain methods work perfectly well.

To get equal-sounding frequency spacing, use the Mel scale: Mel scale - Wikipedia

Thank you all guys!
Dividing the frequency spectra based on logarithms looks nice, also skipping FFT and use just BPF seems relevant to me . I have not checked the CPU usage, but somehow I feel that it shoul be cheaper, thanks @nathan

I am attaching an example code, with 5 bands spectrum based on @shiihs calculation.

// 5 bands

(
Ndef(\a, {
	var sig = Mix(SoundIn.ar(0,2))/2;
	//41 - 139
	var sublows = Amplitude.ar(BPF.ar(sig, 89,   rq: 49/89));
	//139 - 481
	var lows    = Amplitude.ar(BPF.ar(sig, 310 , rq: 171/310));
	//481 - 1666
	var lowmids = Amplitude.ar(BPF.ar(sig, 1073.5 , rq: 592.5/1073.5));
	//1666 - 5771
	var mids    = Amplitude.ar(BPF.ar(sig, 3718.5 , rq: 2052.5/3718.5));
	//5771 - 20000
	var highmids= Amplitude.ar(BPF.ar(sig, 12885.5, rq: 7114.5/12885.5));
	SendReply.kr(Impulse.kr(10), '/fft2', [sublows, lows, lowmids, mids, highmids]*300);
	Silent.ar;
}).play
)


(
~pl = Plotter("", Rect(600,30,376,142) );
~pl.setValue(
	[0,0,0,0,0,0],
        minval: 0,
	maxval: 100
);
~pl.setProperties(
	\backgroundColor, Color.black,
	\plotColor, [Color.white],
	\gridOnX, false,
	\gridOnY, false
  ).plotMode = \bars;
)

(
OSCdef(\a,{|m| 
	{~pl.setValue(
		[m[3], m[4], m[5], m[6], m[7], 1], // lebo nezobrazuje posledny
		minval: 0,
		maxval: 100)
	}.defer
},'/fft2')
)

now, my mind is occupied by russian agression :frowning: I am very sorry for all the Ukrainians and maybe for all the democratic world. Fuck you Mr.Putin.

2 Likes

I’d also recommend tuning the attack/release parameters of Amplitude. Typically you want the release longer than the attack, such as Amplitude.ar(sig, 0.01, 0.05);.

1 Like

Consider using the BandSplitter quark (https://github.com/scztt/bandsplitter.quark), which uses Linkwitz–Riley filters (basically combinations of butterworths) to do lossless band splitting - meaning when you split your signal and then sum the bands back together again, you should get your original signal (albeit delayed by a very small amount).

2 Likes

hey @scztt thank for recomendation. I have not heard about this quark, so it is good to know that something like this exists. In my case, I needed to make an analysis on the end of my chain, so I don’t need to pack the signal back again. Anyway, thanks for a tip.

paum

One interesting idea might be to use the Cepstrum as well as the spectrum…