Moving Average of a variable frequency signal

58 Views Asked by At

I was using this code to get the moving average of a sinusoidal Realtime wave with a constant frequency. (test_ sin being a sin wave with a constant frequency). I was sampling 100 samples as it can be seen in LENGTH_X = 100 and Buffer_X[100].

static double test_sin = 0; 
static double sum_x = 0 , filter_out_X = 0 ;
static int LENGTH_X = 100 , counter_filter_X = 0 ;
static double Buffer_X[100]= {0} ;
.
.
.
sum_x = sum_x + test_sin - Buffer_X\[counter_filter_X\];
filter_out_X = sum_x / LENGTH_X ;
Buffer_X\[counter_filter_X\] = (test_sin);
counter_filter_X = counter_filter_X+1 ;
if (counter_filter_X == LENGTH_X)
{
counter_filter_X = 0 ;
}

Basically i followed this reference to make the algorithm here on Youtube: efficient Moving Average Filter

The question i want to ask is how can I alter this code such that i can change the samples.

My sin wave has a variable frequency so i want to keep the LENGTH_X and BUffer_X[] variable or changing as well not just 100 samples. i already know the samples how much to keep.

Once I set Length_X =100 and Buffer_X[100]= {0} it gets stuck to 100 samples even if later i try to re initialize it,it does not re initialize as well.

I tried simple things like initializing in a different manner:

if(freq>1000)
{
static int LENGTH_X = 100 , counter_filter_X = 0 ;
static double Buffer_X[100]= {0} ;
}
else
{
static int LENGTH_X = 10 , counter_filter_X = 0 ;
static double Buffer_X[10]= {0} ;
}
1

There are 1 best solutions below

1
Support Ukraine On BEST ANSWER

The posted code for changing number of samples won't work. The variables defined inside the if-else part will not be accessible after the if-else.

If supported on your system you could use variable length arrays and memset. Like:

int LENGTH_X;
int counter_filter_X = 0;
if(freq>1000)
{
    LENGTH_X = 100;
}
else
{
    LENGTH_X = 10;
}
double Buffer_X[LENGTH_X];  // variable length array
memset(Buffer_X, 0, LENGTH_X * sizeof Buffer_X[0]); // zero initialize

Or you can go for dynamic allocated memory. Like

int LENGTH_X;
int counter_filter_X = 0;
if(freq>1000)
{
    LENGTH_X = 100;
}
else
{
    LENGTH_X = 10;
}
double* Buffer_X = calloc(LENGTH_X, sizeof Buffer_X[0]);  // dynamic zero-initialized memory

That said I would consider if there is a reason for changing array size at run time. If you know a maximum for LENGTH_X just make the array that maximum size and only use the part of the array you currently want. Re-initializing can be done using memset as shown above.

Maybe your code could look like:

#define MAX_LENGTH 1000
...
...
double test_sin = 0; 
double sum_x = 0;
double filter_out_X = 0 ;
int LENGTH_X = 100;
int counter_filter_X = 0;
double Buffer_X[MAX_LENGTH]= {0} ;

while(keep_running)
{
    if (change_length)
    {
        sum_x = 0;
        counter_filter_X = 0;
        if(freq>1000)
        {
             LENGTH_X = 100;
        }
        else
        {
            LENGTH_X = 10;
        }
        memset(Buffer_X, 0, LENGTH_X * sizeof Buffer_X[0]);
    }

    test_sin = get_sample();

    sum_x = sum_x + test_sin - Buffer_X[counter_filter_X];
    filter_out_X = sum_x / LENGTH_X ;
    Buffer_X[counter_filter_X] = test_sin;
    counter_filter_X = counter_filter_X+1 ;
    if (counter_filter_X == LENGTH_X)
    {
        counter_filter_X = 0 ;
    }

    ...
    ...

    freq = ...;
    change_length = ...;
}

Here you'll have add some code for updating freq and change_length