Search code examples
copencllowpass-filter

Low Pass Filter in OpenCL


I am trying to implement a low pass filter in OpenCL and the theory behind all this has me confused a bit. I have attached my code at the bottom after my explanation of the scenario.

First off, let me try to explain the whole scenario in point form.

  • For the input, we have a cos signal with a sample size, frequency (Frequency sample obtained by multiplying sample size with frequency) and a step size.
  • The value of at each step size is stored in an array with the frequency and step size multiplied to the function
  • This array is then passed into the kernel, which then will execute the low pass filter function.
  • Kernel returns an output array with the new filtered values.

The cos function is always returning a value from (-1,1), the only thing that modifies this value is the frequency. So it may repeat faster or slower depending on the frequency BUT it is always between (-1,1).

This is where I am confused, I am not sure how to apply a low pass filter to these values. Let say the cutoff was 100Hz for the filter. I can't just say:

if(array[i] > 100 ) { //delete or ignore this value. Else store in a array }

The reason this won't work is because the value of array[i] ranges from (-1,1). So how then would I apply this filter? What values am I going to compare?

From a physical perspective, I can see how it works, a capacitor and a resistor to calculate the cut-off frequency and send the input through the circuit. But programmatically, I do not see how I can implement this. I have seen many implementations of this on-line but the code wasn't documented enough to get a good understanding of what was going on.

Here is the code on my host side:

//Array to hold the information of signal
float *Array;

//Number of sampling points 
int sampleSize = 100;
float h = 0;

//Signal Frequency in Hz
float signalFreq = 10;

//Number of points between 0 and max val (T_Sample)
float freqSample = sampleSize*signalFreq;

//Step = max value or T_Sample
float stepSize = 1.0 / freqSample;

//Allocate enough memory for the array
Array = (float*)malloc(sampleSize*sizeof(float));

//Populate the array with modified cosine
for (int i = 0; i < sampleSize; i++) {
    Array[0] = cos(2*CL_M_PI*signalFreq*h);
    h = h + stepSize;
    printf("Value of current sample for cos is: %f \n", Array[0]);
}

My kernel is only as follows: (Obviously this is not the code for the filter, this is where I am confused).

__kernel void lowpass(__global int *Array, __local float *cutOffValue, __global int *Output) { 
    int idx = get_global_id(0); 
    Output[idx] = Array[idx];
};

I found this PDF that implements a lot of filters. Near the end of the document you can find a float implementation of the Low Pass Filter.

http://scholar.uwindsor.ca/cgi/viewcontent.cgi?article=6242&context=etd

In the filter implementation in that pdf, the compare data[j] to value. Also I have no idea what numItems or workItems is.

If someone can provide some insight on this that would be great. I have searched a lot of other examples on low pass filters but I just can't wrap my head around the implementation. I hope I made this question clear. Again, I know how/what the low pass filter does. I just have no idea as to what values I need to compare in order for the filtering to take place.

Found this question aswell:

Low Pass filter in C


Solution

  • I have a possible solution. What I am attempting will be a moving average fir (which I am told is the easiest form of a lowpass filter that one can implement).

    What is required:

    • FIFO buffer
    • Coefficient values (I generated and obtained mine from matlab for a specific cut-off frequency)
    • Input and Output arrays for the program

    I have not implemented this code wise, but I do understand how to use it on a theoretical level. I have created a diagram below to try and explain the process.

    enter image description here

    Essentially, from another input array values will be passed into the FIFO buffer one at a time. Every time a value is passed in, the kernel will do a multiplication across the FIFO buffer that has 'n' taps. Each tap has a coefficient value associated with it. So the input at a particular element gets multiplied with the coefficient value and all the values are then accumulated and stored in one element of the output buffer.

    Note that the coefficients were generated in Matlab. I didn't know how else to grab these values. At first I was going to just use the coefficient of 1/n, but I am pretty sure that is just going to distort the values of the signal.

    And that should do the trick, I am going to implement this in the code now, but if there is anything wrong with this theory feel free to correct it.