DSP Functions
All functions in this library use radix-4 FFT. This means that the signal length can be 64, 256, 1024 & so on.
Note: A length of 16 is not allowed.
Although split-radix requires a fewer number of additions & multiplications, it complicates addressing a lot, so I see radix-4 is fine.
The library follows the rules & conventions of Win32 API. This means that they use stdcall calling convention, and ebx,esi,edi & ebp are preserved.
ä I’ll use ‘Audio’ or ‘Signal’ to denote time-domain signals, & ‘Spectrum’ to denote frequency-domain signals.
ä I use ‘()’ to denote a function name. This of course doesn’t mean the function takes no arguments.
1. FFT()
This function computes Fast Fourier Transform for an input audio signal.
You call this function in MASM with something like this:
invoke FFT, pSignalIn, pSpectrumOut, dspstructs
pSignalIn: Pointer to audio (16-bit, of type SIGNAL) signal array. For N-pts FFT, the audio signal should be of length N (i.e. N* sizeof SIGNAL).
pSpectrumOut: Pointer to output spectrum, which is an array of COMPLEX points. This array should be N-pts (i.e. N* sizeof COMPLEX). This spectrum will have conjugate symmetry arround N/2, since input signal is real.
dspstructs: Structure (DSPSTRUCTs) containing parameters used internally by the function. The members of this structure are initialized in another function, described latter.
You may find it irregular to pass a whole structure on the stack rather than a pointer to it. But I made it this way because members of this structure are used frequently inside the function, so, keeping them in the stack is better than indirect-addressing them each time they’re needed. Anyway, it’s just a 4-members structure.
This function, as well as the coming DSP functions, has no return.
2. FFT_FloatIn()
Same as the previous function, except that here the input signal is float, i.e. of type FSIGNAL.
3. IFFT()
IFFT computes the Inverse FFT of the input signal. Call it in MASM with something like:
invoke IFFT, pSpectrumIn, pSignalOut, dspstructs
pSpectrumIn: Pointer to input spectrum array. This array contains the first N/2+1 points of the spectrum. I.e. from 0 hz to Sampling_Freq/2. The rest is redundant, so the function needs only this range.
pSignalOut: Pointer to output audio signal, which is array of N SIGNAL points.
dspstructs: Structure of type DSPSTRUCTs.
4. IFFT_FloatOut()
Same as the previous function, but here the output signal is float (of type FSIGNAL). The output signal is array of N FSIGNAL points.
Call it in MASM with something like:
invoke IFFT_FloatOut, pSpectrumIn, pSignalOut, dspstructs
5. FilterSignal()
Normally, to filter a signal using FFT, given the spectrum (freq. Response) of the filter, you would do the following 3 steps:
Ø Calculate spectrum of input signal using FFT.
Ø Multiply the signal spectrum by the filter spectrum.
Ø IFFT for the result to get the filtered signal back in time-domain.
FilterSignal() does these 3 steps, with a speed-up of about 30%, according to my tests.
Call it like this:
invoke FilterSignal, pSignalIn, pFilter, pSignalOut, dspstruct
pSignalIn: Pointer to audio input signal (N SIGNAL points).
pFilter: Pointer to filter spectrum, specified for first N/2+1 points (i.e. same as IFFT() & IFFT_FloatOut() ). So this filter should be an array of N/2+1 COMPLEX point.
pSignalOut: Pointer to audio output signal (N SIGNAL points).
dspstruct: a DSPSTRUCT structure (not DSPSTRUCTs), both are described later.
6. FilterSignal_FloatInOut()
Same as the previous function, but here both the input & output signals are float (arrays of FSIGNAL).
This function is faster than FilterSignal().
Generally, using floating-point variables in FPU operations is faster than integer variables.
7. FilterSignal_FloatIn()
Same as FilterSignal(), but here the input signal is float. The output signal is array of type SIGNAL.
8. FilterSignal_FloatOut()
Same as FilterSignal(), but here the output signal is float. The input signal is array of type SIGNAL.
9. FFT_1for2()
Now, the reason behind the “1for2” part in the library name: This function performs 2 FFTs for 2 input signals simultaneously. This saves about 33% of the computation time, according to my tests. So, if you have 2 signals instead of 1, it’s better to use this function than 2 calls to FFT().
Call it like this:
invoke FFT_1for2, pSignalIn1, pSignalIn2, pSpectrumOut1, pSpectrumOut2, dspstruct
dspstruct: A DSPSTRUCT structure.
I guess no further explanation is needed for the function arguments.
The 2 input signals should be 2 separate signals; they can’t be stored in a single buffer, as stereo wave files. Same for output signals.
10. FFT_1for2_FloatIn()
Same as the previous function, but here the two input signals are both float (arrays of type FSIGNAL).
11. FilterSignal_1for2()
Again, faster than FilterSignal() by about 33% according to my tests (if you have 2 signals to filter). Each signal is filtered with one filter.
Call it like this:
invoke FilterSignal_1for2, pSignalIn1, pSignalIn2, pFilter1, pFilter2, pSignalOu1, pSignalOut2, dspstruct
Note that the first filter operates on the first signal & the second filter operates on the second signal.
If you want to filter both signals with the same filter, then you can set pFilter1 & pFilter2 to the same value (pointer to that filter’s frequency response).
12. FilterSignal_1for2_FloatInOut()
Same as the previous function, but here all the input & output signals are float (arrays of FSIGNAL).
This function is faster than FilterSignal_1for2().
13. FilterSignal_1for2_FloatIn()
Same as FilterSignal_1for2(), but here the two input signals are float. The two output signals are arrays of type SIGNAL.
14. FilterSignal_1for2_FloatOut()
Same as FilterSignal_1for2(), but here the two output signals are float. The two input signals are arrays of type SIGNAL.
Notes about the above functions:
§ In all the above functions, the input signals (or spectrums) are not changed by the functions.
§ In FilterSignal() & FilterSignal_1for2(), you can filter the signals in-place. I.e., if you don’t need the input signals after filtering, then you can set the input & output pointers to the same value like this:
invoke FilterSignal, pSignal, pFilter, pSignal, dspstruct
§ Remember that all the Inverse FFT and filtering functions above introduce a gain of N. So, to obtain the actual output signal, you should multiply functions’ outputs by 1/N.