9.4. EFFICIENT C CODE WRITING 135
e array window is stored in heap memory using the previously defined FIRFilter structure
as these values need to be retained between calls to the compute method. Memory allocation is
time consuming and multiple repeated allocations should be avoided if possible.
Another way to improve code performance is to reduce the logic necessary for the loop to
operate. Although the above two loops may appear fine, it still takes extra operations to compute
the array index and thus the memory address of the desired value. A method involving pointer
manipulation can be used as shown in the following code block:
void computeFIR(FIRFilter* fir, float* input) {
int i, j;
float temp;
float* windowPtr = fir->window;
for(i=0; i<fir->numCoefficients; i++) {
*windowPtr = windowPtr[fir->frameSize];
windowPtr++;
}
for(i=0; i<fir->frameSize; i++) {
temp = 0;
*windowPtr = input[i];
for(j=0; j<fir->numCoefficients; j++) {
temp += windowPtr[-j] * fir->coefficients[j];
}
windowPtr++;
fir->result[i] = temp;
}
}
Using this technique, the memory address of the array is loaded one time before variable over-
writes or computations take place. Coming out of the shifting loop, the pointer windowPtr
refers to the memory location of the first array index that receives a sample from the new frame
of audio data due to the post-update incrementing. Using the pointer also removes the need for
some logic to accomplish array indexing. In terms of actual instructions generated by the com-
piler, this version of the code has six operations in the second loop as opposed to the original
version of the code having ten operations. Also note, unlike the previous case where the window
array was accessed from low index values to high index values, the window array is now being
accessed in reverse order.
e instructions to compute the result can be generalized into core instructions, e.g., the
multiply-accumulate instruction in linear convolution. Supporting instructions, which add com-