153 lines
3.2 KiB
C
153 lines
3.2 KiB
C
/*
|
|
* vumeter.c:
|
|
* Simple VU meter
|
|
*
|
|
* Heres the theory:
|
|
* We will sample at 4000 samples/sec and put the data into a
|
|
* low-pass filter with a depth of 1000 samples. This will give
|
|
* us 1/4 a second of lag on the signal, but I think it might
|
|
* produce a more pleasing output.
|
|
*
|
|
* The input of the microphone should be at mid-pont with no
|
|
* sound input, but we might have to sample that too, to get
|
|
* our reference zero...
|
|
*
|
|
* Copyright (c) 2013 Gordon Henderson
|
|
***********************************************************************
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <wiringPi.h>
|
|
#include <gertboard.h>
|
|
|
|
#ifndef TRUE
|
|
#define TRUE (1==1)
|
|
#define FALSE (!TRUE)
|
|
#endif
|
|
|
|
#define B_SIZE 1000
|
|
#define S_SIZE 128
|
|
|
|
static int buffer [B_SIZE] ;
|
|
static int bPtr = 0 ;
|
|
|
|
/*
|
|
* ledPercent:
|
|
* Output the given value as a percentage on the LEDs
|
|
*********************************************************************************
|
|
*/
|
|
|
|
static void ledPercent (int percent)
|
|
{
|
|
unsigned int output = 0 ;
|
|
|
|
if (percent > 11) output |= 0x01 ;
|
|
if (percent > 22) output |= 0x02 ;
|
|
if (percent > 33) output |= 0x04 ;
|
|
if (percent > 44) output |= 0x08 ;
|
|
if (percent > 55) output |= 0x10 ;
|
|
if (percent > 66) output |= 0x20 ;
|
|
if (percent > 77) output |= 0x40 ;
|
|
if (percent > 88) output |= 0x80 ;
|
|
|
|
digitalWriteByte (output) ;
|
|
}
|
|
|
|
static unsigned int tPeriod, tNextSampleTime ;
|
|
|
|
/*
|
|
* sample:
|
|
* Get a sample from the Gertboard. If not enough time has elapsed
|
|
* since the last sample, then wait...
|
|
*********************************************************************************
|
|
*/
|
|
|
|
static void sample (void)
|
|
{
|
|
unsigned int tFuture ;
|
|
|
|
// Calculate the future sample time
|
|
|
|
tFuture = tPeriod + tNextSampleTime ;
|
|
|
|
// Wait until the next sample time
|
|
|
|
while (micros () < tNextSampleTime)
|
|
;
|
|
|
|
buffer [bPtr] = gertboardAnalogRead (0) ;
|
|
|
|
tNextSampleTime = tFuture ;
|
|
}
|
|
|
|
|
|
int main ()
|
|
{
|
|
int quietLevel, min, max ;
|
|
int i, sum ;
|
|
unsigned int tStart, tEnd ;
|
|
|
|
printf ("\n") ;
|
|
printf ("Gertboard demo: VU Meter\n") ;
|
|
printf ("========================\n") ;
|
|
|
|
wiringPiSetup () ;
|
|
gertboardSPISetup () ;
|
|
|
|
ledPercent (0) ;
|
|
for (i = 0 ; i < 8 ; ++i)
|
|
pinMode (i, OUTPUT) ;
|
|
|
|
for (bPtr = 0 ; bPtr < B_SIZE ; ++bPtr)
|
|
buffer [bPtr] = 99 ;
|
|
|
|
tPeriod = 1000000 / 1000 ;
|
|
|
|
printf ("Shhhh.... ") ; fflush (stdout) ;
|
|
delay (1000) ;
|
|
printf ("Sampling quiet... ") ; fflush (stdout) ;
|
|
|
|
tStart = micros () ;
|
|
|
|
tNextSampleTime = micros () ;
|
|
for (bPtr = 0 ; bPtr < B_SIZE ; ++bPtr)
|
|
sample () ;
|
|
|
|
tEnd = micros () ;
|
|
|
|
quietLevel = 0 ;
|
|
max = 0 ;
|
|
min = 1024 ;
|
|
for (i = 0 ; i < B_SIZE ; ++i)
|
|
{
|
|
quietLevel += buffer [i] ;
|
|
if (buffer [i] > max) max = buffer [i] ;
|
|
if (buffer [i] < min) min = buffer [i] ;
|
|
}
|
|
quietLevel /= B_SIZE ;
|
|
|
|
printf ("Done. Quiet level is: %d [%d:%d] [%d:%d]\n", quietLevel, min, max, quietLevel - min, max - quietLevel) ;
|
|
|
|
printf ("Time taken for %d reads: %duS\n", B_SIZE, tEnd - tStart) ;
|
|
|
|
for (bPtr = 0 ;;)
|
|
{
|
|
sample () ;
|
|
sum = 0 ;
|
|
for (i = 0 ; i < S_SIZE ; ++i)
|
|
sum += buffer [i] ;
|
|
sum /= S_SIZE ;
|
|
sum = abs (quietLevel - sum) ;
|
|
sum = (sum * 1000) / quietLevel ;
|
|
ledPercent (sum) ;
|
|
if (++bPtr > S_SIZE)
|
|
bPtr = 0 ;
|
|
}
|
|
|
|
|
|
return 0 ;
|
|
}
|