8 years, 10 months ago.

time domain with correlation

i am using 2 sparkfun microphone to detect the direction of the speaker. i am using this https://www2.informatik.uni-hamburg.de/wtm/ps/murray_ulm04.pdf as my source of help.looking at this.i don't have to do fft since what i am doing is to making time domain and to do my cross correlationa and find my angle.i'm taking someones advice to take only 50 sample from the 1024 and check if sum of square of each microphone is over a certain value, then it will jump to cross correlation but its having some issues.i have to say the mic is very tricky and i need some help for someone to take a look where the mistake lies.code form would be a great help .thank you mbed for all the help.this is my code that i have come up with.

#include "mbed.h"
#include "math.h"

#define SAMPLE_PERIOD 60
#define SAMPLE 1024
#define PI  3.1416
#define freq 44100
#define sos 384 //m/s
#define WINDOWSIZE 128
#define  idlelevel

Serial pc(USBTX, USBRX);
DigitalOut myled(LED1);
AnalogIn  rightmic(p16);
AnalogIn  leftmic(p19);
BusOut    unused(p15,p17,p18,p20); 
Timer t;

double max1,min1; 
double max,min;
float left_results[SAMPLE];
float right_results[SAMPLE];
float timesampling;
int peakoffset;
int count;
float sumright[50],sumleft[50];

int correlate(float left_results[], float right_results[])
{
    float peakCorrelation = 0;
    int peakoffset = 0;
    float correlation;
    int firstLeftSample = SAMPLE/ 2 - WINDOWSIZE/2; // the first sample in the left data such that our window will be centered in the middle.
    int timeoffset = -firstLeftSample ;//minimum time test
    while ( (timeoffset + firstLeftSample  + WINDOWSIZE ) < SAMPLE) 
    {
        correlation = 0;
        for (int i = 0; i<WINDOWSIZE ; i++) 
        {
            correlation += left_results[firstLeftSample  + i] * right_results[firstLeftSample + timeoffset +i];
        }
        if (correlation  > peakCorrelation) // look for the peak..
        { 
            peakCorrelation = correlation;
            peakoffset = timeoffset;
            timeoffset++;
        }
        pc.printf("lag=%d \n\r",peakoffset);
    }
    return peakoffset;
}
int angle(int peakoffset)
{
    float c=0.15;//distance between two mics...
    float distance=(peakoffset*timesampling)*sos;//distance of unknown which is the speaker or length of 'a'..
    int theta=asin(distance/c)*180/PI;    //phase of the speaker   
    pc.printf("angle=%d",theta);
    return 0;
}
int main() 
{   
        for(int i=0;i<SAMPLE;i++)
        {
            t.start();
            while(t.read_ms()<i*SAMPLE_PERIOD)// wait until the next sample time....
            {
                left_results[i]=leftmic.read();
                right_results[i] = rightmic.read();
                
                if(i%50==0)
               {
                    for(a=0;a<=50;a++)
                    {
                    sumleft[a]+=left_results[i]*left_results[i];
                    sumright[a]+=right_results[i]*right_results[i];
                    if(sumleft[a]>1||sumright[a]>1)
                    {
                        correlate(left_results,right_results);
                        angle(peakoffset);
                        
                    }
                }
             }
          }  
        }

}

2 Answers

8 years, 10 months ago.

To start with, you now read as many values as it can while the time is smaller than i*Sample_Period, is that what you want?

In general this is very hard for us to debug. However since this then seems to be a student project, I assume you have some measurement equipment? Start easy: Apply sine waves from a function generator directly to your inputs (take into account they need to have their grounds connected to mbed ground, and they are not allowed to be negative in voltage, so it needs an offset).

If you get that to work, next step is connect a speaker to your function generator and just send a single tone with it. It will both be easier to debug and to perform cross correlation on a single tone.

You can then also try after sampling to send the values to your PC, so you can see what is happening.

8 years, 10 months ago.

 for(a=0;a<=50;a++)
  {
      sumleft[a]+=left_results[i]*left_results[i];
      sumright[a]+=right_results[i]*right_results[i];
      if(sumleft[a]>1||sumright[a]>1)
        {

This is not doing a sum of squares being over a certain value.

You are waiting until sample[0]^2 + sample[50]^2 + sample[100]^2...... goes over 1 which is probably going to happen after about 200 samples assuming an average of 0.5. No matter what it's going to happen at some point no matter how low the signals are.

However since you never initialize sumleft or sumright it could happen after the first sample.

Even if the maths was right it wouldn't work, it will trigger as soon as the first microphone hears the sound, there will be nothing to correlate it with on the other microphone.

As I said before, look for a rolling sum of squares over the last 50 samples to go over a certain threshold, start logging at that point and keep logging until you fill your buffer. That way you should have a nice loud non-noise signal from both buffers.

And check your idle input on the ADC, if idle is 0 or very close to it then you're only going to get half your signal. If idle is around 0.5 then you will get the full signal but need to subtract that from the ADC reading before doing anything else.

Finally you have a bug, when you call angle you always pass it 0. It should be

peakoffset = correlate(left_results,right_results);
angle(peakoffset);

when u said rolling sum of square, did u mean for every 50 samples then it will do the sum of square calculation and taking the sum of square array to do its correlation and angle.?when i do this it still shows me a lag 0 and angle was never printed out.

int main() 
{   
        for(int i=0;i<SAMPLE;i++)
        {
            t.start();
            while(t.read_ms()<i*SAMPLE_PERIOD)// wait until the next sample time....
            {
                left_results[i]=leftmic.read();
                right_results[i] = rightmic.read();
                //pc.printf(" %.1f, %.1f \n\r", left_results[i],right_results[i]);
            }
            t.reset();
            sumleft+=left_results[i]*left_results[i];
            sumright+=right_results[i]*right_results[i];
            pc.printf(" %.3f, %.3f \n\r", sumleft,sumright);
            if(i%50==0)
            {
                if(sumleft>0.5||sumright>0.5)
                {
                    peakoffset=correlate(left_results,right_results);
                    int angle=calc_angle(peakoffset); 
                    pc.printf("angle=%d",angle);
                               
                }
                sumleft=0;
                sumright=0;
            }
        }
}
posted by faris abdat 22 Jun 2015

No. Every sample take the sum of the squares of the last 50 samples (don't calculate from scratch, add the latest and subtract the value from 50 samples ago). If that total is over a threshold then log the next 1024 samples and correlate.

posted by Andy A 22 Jun 2015