I have designed a simple dual channel filter to remove some noise at a given frequency.
#include "../include/Filter.h"
void Filter(int DataIn, int* DataOut, bool Enable)
{
static coef_t Coefficients[] = {
0.0076925293, -0.039817952, 0.018740745, 0.013075141, -0.052312399,
0.052374545, 0.017044802, -0.14227364, 0.26541378, 0.68194015, 0.26541378,
-0.14227364, 0.017044802, 0.052374545, -0.052312399, 0.013075141, 0.018740745,
-0.039817952, 0.0076925293
};
static data_t ShiftRegRight[LENGTH];
static data_t ShiftRegLeft[LENGTH];
acc_t AccRight = 0x00;
acc_t AccLeft = 0x00;
if(Enable == true)
{
Shift_Accum_Loop: for(int i = (LENGTH - 1); i >= 0; i--)
{
if(i == 0)
{
ShiftRegRight[0] = DataIn & 0x0000FFFF;
ShiftRegLeft[0] = (DataIn & 0xFFFF0000) >> 0x10;
}
else
{
ShiftRegRight[i] = ShiftRegRight[i - 1];
ShiftRegLeft[i] = ShiftRegLeft[i - 1];
}
AccRight += ShiftRegRight[i] * Coefficients[i];
AccLeft += ShiftRegLeft[i] * Coefficients[i];
}
*DataOut = ((AccLeft.range() >> 0x20) << 0x10) | (AccRight.range() >> 0x20);
}
else
{
*DataOut = DataIn;
}
}
This filter produce the following output on a given test signal:
0, 0, 0
1, 28377, 218
2, 0, 64405
3, 0, 531
4, 0, 370
5, 37159, 63833
6, 0, 2616
7, 37159, 65269
8, 0, 62257
9, 0, 8484
10, 0, 17494
11, 28377, 8750
12, 0, 62919
13, 28377, 58754
14, 0, 50948
15, 0, 48035
16, 0, 52449
17, 37159, 56833
18, 0, 0
19, 37159, 8484
20, 0, 14216
21, 0, 16968
22, 0, 14216
...
The test signal is generated with a testbench:
#include <math.h>
#include <stdio.h>
#include "../include/Filter.h"
#define SAMPLES 48000
#define FREQ_RIGHT_1 8000
#define FREQ_RIGHT_2 10000
#define FREQ_LEFT_1 50
FILE* File;
int main(void)
{
int Output;
int StreamData;
uint16_t RightChannel = 0x00;
uint16_t LeftChannel = 0x00;
File = fopen("Result.log", "w");
for(int i = 0x00; i < SAMPLES; i++)
{
// Generate the input data
RightChannel = 32767 * sin(2 * M_PI * i / (SAMPLES / FREQ_RIGHT_1)) * sin(2 * M_PI * i / (SAMPLES / FREQ_RIGHT_2));
StreamData = (LeftChannel << 0x10) | RightChannel;
// Execute the function with latest input
Filter(StreamData, &Output, true);
// Write the simulation results
fprintf(File, "%i, %d, %d\n", i, StreamData, Output);
}
fclose(File);
}
So why do I get a different output, when I change the for
loop in Filter
from a down counting loop into a upcounting loop?
if(Enable == true)
{
Shift_Accum_Loop: for(int i = 0; i < (LENGTH - 1); i++)
{
if(i == 0)
{
...
0, 0, 0
1, 28377, 27073
2, 0, 0
3, 0, 0
4, 0, 0
5, 37159, 38462
6, 0, 0
7, 37159, 38462
8, 0, 0
9, 0, 0
10, 0, 0
11, 28377, 27073
What is the difference between this? The loops do count from 0
to (LENGTH - 1)
in both cases and the filter is symetric. Why does the count direction has an impact on the result?
if(i == 0)
{
ShiftRegRight[0] = DataIn & 0x0000FFFF;
ShiftRegLeft[0] = (DataIn & 0xFFFF0000) >> 0x10;
}
else
{
ShiftRegRight[i] = ShiftRegRight[i - 1];
ShiftRegLeft[i] = ShiftRegLeft[i - 1];
}
When you count down i==0
evaluates to true last.
When you count up i==0
evaluates to true first.