aboutsummaryrefslogtreecommitdiffstats
path: root/examples/3_fir.cpp
blob: b6d8751e5e4c6bbc182ff0117d10f10fcce5581e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/**
 * 3_fir.cpp
 * Written by Clyne Sullivan.
 *
 * The below code was written for applying FIR filters. While this is still essentially an overlap-
 * save convolution, other optimizations have been made to allow for larger filters to be applied
 * within the available execution time. Samples are also normalized so that they center around zero.
 */

Sample* process_data(Samples samples)
{
    static Samples buffer;

	// Define the filter:
	constexpr unsigned int filter_size = 3;
	static float filter[filter_size] = {
        // Put filter values here (note: precision will be truncated for 'float' size).
        0.3333, 0.3333, 0.3333
	};

    // Do an overlap-save convolution
    static Sample prev[filter_size];

    for (int n = 0; n < SIZE; n++) {
        // Using a float variable for accumulation allows for better code optimization
        float v = 0;

        for (int k = 0; k < filter_size; k++) {
            int i = n - (filter_size - 1) + k;

            auto s = i >= 0 ? samples[i] : prev[filter_size - 1 + i];
			// Sample values are 0 to 4095. Below, the original sample is normalized to a -1.0 to
            // 1.0 range for calculation.
            v += (s / 2048.f - 1) * filter[k];
        }

        // Return value to sample range of 0-4095.
        buffer[n] = (v + 1) * 2048.f;
    }

    // Save samples for next convolution
    for (int i = 0; i < filter_size; i++)
        prev[i] = samples[SIZE - filter_size + i];

    return buffer;
}