FFT Spectrum VuMeters


#1

Hi all,

Some very nice small classes of FFT Meters. The 64 bands meters is an adaptation of a work of kraken in jucetice : HighQualityMeter (thanks a lot for this great class). Based on a FFT computed by AudioCallback with short size (<1024). The better result come with a FFT Size of 1024, under 256 the quality is really too bad in the low-end frequencies.

The trick is in this function, it compensates for the loss of resolution with a short FFT :

//======================================================================
/**
	float getInterpolatedResponseAtFrequency (const float frequency);
	--------------------------------------------------------------------
	Returns spectrum or response data interpolated to a selected
	ISO R Series preferred frequency format. 

	The frequency range is limited to the range	from 1 Hz to 100 kHz. 
	The conversion is performed as straight-line interpolation on a 
	semi-log axes, i.e. a log frequency axis. This conversion can be 
	applied to magnitude or phase data.

	The point-point form of the Equation of a Line, in semi-log coordinates:
	------------------------------------------------------------------------

		40	|					o (f2, Y2)
			  |				  /
		30	|				/
			  |			  o (f, y)
		20	|			/ 
			  |		  /
		10	|		o (f1, Y1)
			  |
		 0	|-----------------------------------
		dB	 100        Frequency (Hz)		1000


					 log(f)  - log(f1)
			y = Y1 + ----------------- x (Y2 - Y1)
					 log(f2) - log(f1)
*/
//======================================================================
inline float getInterpolatedResponseAtFrequency (const float f)
{
	resolution = (sampleRate / 2) / spectrumSize; /* Nyquist / FFT Size */

	const int b1 = roundFloatToInt (f / resolution);
	const double f1 = b1 * resolution;
	const float y1 = (spectrum[0][jlimit(0, spectrumSize, b1)] +
					  spectrum[1][jlimit(0, spectrumSize, b1)]) / 2;

	const int b2 = b1 + 1;
	const double f2 = b2 * resolution;
	const float y2 = (spectrum[0][jlimit(0, spectrumSize, b2)] +
					  spectrum[1][jlimit(0, spectrumSize, b2)]) / 2;

	return y1 + 
		 ((fast_log10(f) -fast_log10(f1))  / 
		  (fast_log10(f2)-fast_log10(f1))) * 
		  (y2 - y1);
}
//======================================================================

The implementation is not finish, that can be good to use the normalized ISO-R series (cf. include file).

ISO Series | Frequency Resolution

R 10 | 1/3 octave (1/10 decade)
R 20 | 1/6 octave (1/20 decade)
R 40 | 1/12 octave (1/40 decade)
R 80 | 1/24 octave (1/80 decade)

The project contain 4 main classes :

SpectrumAudio : Is the main JUCE audio process management.
SpectrumCallback : The processor for the spectrum computation during audio callback.
SpectrumFFT : The FFT class himself.
SpectrumComponent : The 64-Band component.

The 64-Band component is ressource costly because i’ve decorated the component using trick by alpha channel. Can be largely optimised. So i’ve limited the size of the window. The CPU information is the audio-callback-cpu not the application-cpu.

Download the demo project executable with 4 short FLAC samples for testing : HERE

Hope you like that !

Regards,
Max

[attachment=0]SpectrumVumeter-src.zip[/attachment]


#2

Thanks! A lovely app :slight_smile:
BTW: I had to change one of the compiler options (Omit Default Library Names) to “Yes” to get this to build on my machine


#3

Wow!


#4

cool stuff !