Preparation Functions
Now, what about DSPSTRUCT & DSPSTRUCTs?
As you may know, FFT functions in general, need a table of twiddle factors. And in my implementation, I use a table for reverse-addressing & other memory blocks for computation. These structures hold pointers to these memory blocks.
Here are the structures definitions:
DSPSTRUCT STRUCT ;2 computation blocks
N dword ?
pTwiddles dword ?
pIndexTable dword ?
pBlock1 dword ?
pBlock2 dword ?
DSPSTRUCT ENDS
DSPSTRUCTs STRUCT ;1 computation block
N dword ?
pTwiddles dword ?
pIndexTable dword ?
pBlock dword ?
DSPSTRUCTs ENDS
The only difference between the two structures is that DSPSTRUCT has one extra member more than DSPSTRUCTs. DSPSTRUCT is used with the functions that require two computation blocks. In general, two computation blocks are required with the filtering functions & the functions having the ‘1for2’ part. These include FilterSignal(), FilterSignal_FloatInOut(), FilterSignal_1for2(), FFT_1for2() & so on...
In the remaining functions, only one block is required, so, those functions use a DSPSTRUCTs structure.
The first member in either structure (N) is the FFT length.
Now comes the question: When are these memory blocks allocated & twiddle table filled & so on? The answer is the following function: NewDSP().
NewDSP()
As I pointed out above, this function allocates memory for computation, twiddles, & reverse-addressing table. It also fills these tables & fills a DSPSTRUCT struct with pointers to these blocks. Call this function like this:
invoke NewDSP, N, pDspStruct, nBlocks
N: a dword value, = FFT length that you want to use (64, 256 …)
pDspStruct: a pointer to an uninitialized DSPSTRUCT structure. This structure will be filled with FFT parameters (N & pointers).
nBlocks: A dword value, should be either 1 or 2. If 1, then function will allocate only one computation block & set the pBlock1 member as pointer to it. pBlock2 will be set to NULL (0) in this case. If you pass 2 instead, then two computation blocks will be allocated. If you’ll only use functions that require only one computation block, then you need to allocate only one, so, pass a 1 in nBlocks. These of course are the functions that use a DSPSTRUCTs.
Now, you have a filled DSPSTRUCT, so how to use it with function that take a DSPSTRUCTs (as FFT()) ?
The answer is that you pass only the first 4 members of the DSPSTRUCT structure by using the ‘PTR’ assembly keyword.
The last section in this guide contains some basic code examples.
NewDSP() should be called only once of course.
Return:
NewDSP() returns one of the following possible values:
Ø 0 if succeeds.
Ø DSP_ERR_BADARG (defined in DSP_1for2.inc as 1) if you call it with a bad N value or an nBlocks value other than 1 or 2. No memory is allocated in this case & function returns immediately
Ø DSP_ERR_MEMALLOC (defined as 2) if not enough memory is available from Windows. No memory is allocated in this case too.
DeleteDSP()
Call it once (typically before program terminates). It takes only one argument: a pointer to a DSPSTRUCT structure. Call it like this:
invoke DeleteDSP,pDspStruct
The function operates as follows:
ü It frees all memory allocated by NewDSP().
ü It sets all members of the passed structure to NULL (except N). This indicates that the memory blocks are freed. So if you call DeleteDSP() another time (say by mistake), then it will return without doing anything.
You don’t have to edit the DSPSTRUCT members yourself. Just let NewDSP() & DeleteDSP() do this for you.