The purpose of this tutorial is not to train you to be an expert in Digital Signal Processing. Howver, to grasp the basics of FIR filtering, it is necessary to understand the computations that are required, and the data that is consumed and produced by the compute block.
A digital signal is an analog signal (audio, radio frequencies) that has been received by a converter (Analog to Digital Converter: ADC), which performs two operations:
Slicing: The impinging signal is sliced into very small time slots on which its amplitude is approximated by a constant value.
Quantizing: Digital systems understand only bits. The constant value at the output of the slicer is transformed into an integer value whose maximum represents the maximum amplitude that the system can receive.
As a result, the digital signal at the output of the ADC is simply a series of N-bits values (called samples) that can be processed to extract some useful information. The most basic operation is to multiply some samples by some specific coefficients and accumulate these values to create a “summary” of this part of the signal.
A filtering operation performs this using a sliding window on the signal as shown in the following figure:
Input data samples are in general called x (blue squares), the coefficients c (green squares) and the output samples y:
DSP experts may say that this equation represents a correlation and not a convolution, which is the mathematical expression of the filtering operation. The easy answer may be to say that it is simply a question of coefficients ordering (and perhaps conjugation for complex coefficients).
That is why you always see the two lines at the beginning of the various graph.h files:
std::vector<cint16> taps = std::vector<cint16>({
...
});
std::vector<cint16> taps_aie(taps.rbegin(),taps.rend());
The first line is the taps vector definition in the correct order for a DSP expert, and the second line defines the vector that is used in the AI Engine implementation as the same vector but in the reverse order.