take a look at raspberry-vu project, it's a similar function with the cpu intensive parts written in C. that's fairly important on an RPi.
you can modify the src/impulse.c
and src/test-impulse.c
to do what you want if you also link in gsl
and cblas
(dep of gsl) and include <gsl/gsl_statistics_double.h>
. you'll notice that you get an array[256] back from im_getSnapshot()
which holds the FFT magnitudes. pass that array to your desired function. for me that's sd = gsl_stats_sd(array, 1, 256)
, and it'll pass back the standard deviation as a simple double. for you, you'll want to use mean = gsl_stats_mean(array, 1, 256)
which will give you the average value of all the spectral distribution. you can then do something based on the value of mean
.
i'm doing a similar project to suspend/unsuspend an RTP source based on white noise detection (SD is very low for white noise). if the SD is very low, the RTP sink is suspended. otherwise it's enabled. this means a flood of RTP packets only happens when non-whitenoise is found.
this may be your easiest method of reacting to an audio level signal. i've made a snippet here that represents both the stddev and mean of the audio i'm monitoring.
#include <unistd.h>
#include "impulse.h"
#include <stdio.h>
#include <gsl/gsl_statistics_double.h>
int main( ) {
int i;
double stddev, stddev_max=0, mean;
im_start( );
while ( 1 ) {
usleep( 1000000 / 10 );
double *array = im_getSnapshot( IM_FFT );
for ( i = 0; i < 256; i+=16 )
{
printf( " %.3f,", array[ i ] );
}
stddev = gsl_stats_sd(array, 1, 256);
mean = gsl_stats_mean(array, 1, 256);
if (stddev > stddev_max)
stddev_max = stddev;
printf(" = [%.05f, %.05f] %.05f\n", stddev, stddev_max, mean);
fflush( stdout );
// if (mean > some_value) { do_something(); }
// else { do_something_else(); }
}
im_stop( );
return 0;
}