Calculating average amplitude of frequency bands with ofxMaxim

edit:
i’ve managed to calcule the average of a frequency band writing this two functions:

int ofApp::freqToIndex(float freq) {
	int index;
	index = freq / sampleRate * (fftSize / 2);

	return index;
}

//--------------------------------------------------------------

float ofApp::calcAvg(float lowFreq, float highFreq) {

	float lowBound = freqToIndex(lowFreq);
	float highBound = freqToIndex(highFreq);

	float avg = 0;

	for (int i = lowBound; i <= highBound; i++) {
		avg += fft.magnitudesDB[i];
	}

	avg /= (lowBound - highBound + 1);

	return avg;
}

the results are useful, but im still trying to improve it, any suggestion will be well received.

thnaks!


hi,
im trying to migrate a processing sketch to of that i use for visuals while playing live. the processing sketch relies on the minim library for analysis on audio input, and then drawing to the screen using the average amplitude of different frequency bands. there is a function in minim that i use a lot along the sketch, calcAvg(), that let me calcule the average amplitud of the band bounded by the lower and higher frequency i pass as arguments for the function.

i’ve looked at all the examples and tutorials i found but still dont fully understad how fft works on maxim. any help on how i can get the average amplitude of a freq band of my choice?

here is the code i have so far. i can analyze the input, now i need to calcule the average amplitude of different frequency bands of my choice.

#pragma once

#include "ofMain.h"
#include "ofxMaxim.h"

class ofApp : public ofBaseApp{

	public:
		void setup();
		void update();
		void draw();
		void exit();

		void audioIn(ofSoundBuffer &buffer);

		vector <float> inputL;
		vector <float> inputR;
		int bufferSize = 256;
		int sampleRate = 44100;

		ofSoundStream soundStream;

		ofxMaxiFFT fft;
		ofxMaxiFFTOctaveAnalyzer octaveAnalyzer;
		int fftSize = 1024;

};
void ofApp::setup(){

	inputL.assign(bufferSize, 0.0); 
	inputR.assign(bufferSize, 0.0);

	// soundstream setup
	ofSoundStreamSettings settings;
	settings.setApi(ofSoundDevice::Api::JACK);
	auto devices = soundStream.getDeviceList();
	settings.setInDevice(devices[1]);
	settings.setInListener(this);
	settings.sampleRate = sampleRate;
	settings.bufferSize = bufferSize;
	settings.numInputChannels = 2;
	settings.numOutputChannels = 0;
	soundStream.setup(settings);

	// fft setup
	ofxMaxiSettings::setup(sampleRate, 2, bufferSize);
	fft.setup(fftSize, 512, 256);
	// oct setup
	octaveAnalyzer.setup(sampleRate, fftSize, 10);
}

void ofApp::audioIn(ofSoundBuffer &buffer) {
	
	for (int i = 0; i < buffer.size(); i++) {
		inputL[i] = buffer[i * 2];
		inputR[i] = buffer[i * 2 + 1];

		if (fft.process(buffer[i])) {
			fft.magsToDB();
			octaveAnalyzer.calculate(fft.magnitudesDB);
		}
	}
}

void ofApp::draw(){
	ofSetColor(255, 255, 255);
	for (int i = 0; i < fftSize; i++) {
		ofDrawRectangle(i * 2, ofGetHeight(), 2, -(fft.magnitudesDB[i]) * 8);
	}
}

any help on how to proceed from here would be great
thank you very much.

Hi @nzfs,

Have you tried storing the current value of each fft.magnitudesDB into a vector and get an other array which would be the average of the current value and the past value?

Basically, something like :

vector < float > averageVals;
averagesVals.resize(fft.magnitudesDB.size());

then in ofApp.cpp::draw():

for (int i = 0; i < fftSize; i++) {
averageVals[i]  = (averageVals[i] + fft.magnitudesDB[i] / 2);

Don’t forget to initialise them to 0 as well.

This will only average over the last value with a weight of .5, the second last 0.25, etc… so maybe it’s not what you are looking for, but as a crude star, I’d like in this direction.

Hope this helps,

P

1 Like

thank you! it’s a good starting point to experiment.