OpenCL中的低通滤波器

时间:2016-05-12 18:18:00

标签: c opencl lowpass-filter

我正在尝试在OpenCL中实现一个低通滤波器,所有这些背后的理论让我感到困惑。在我解释了这个场景后,我在底部附上了我的代码。

首先,让我尝试以点的形式解释整个场景。

  • 对于输入,我们有一个带有样本大小,频率(通过将样本大小乘以频率得到的频率样本)和步长的cos信号。
  • 每个步长的值存储在一个数组中,其频率和步长乘以函数
  • 然后将该数组传递给内核,然后执行低通滤波器函数。
  • 内核返回带有新过滤值的输出数组。

cos函数始终从(-1,1)返回一个值,唯一修改此值的是频率。因此它可能会更快或更慢地重复,具体取决于频率,但它始终在(-1,1)之间。

这是我感到困惑的地方,我不知道如何对这些值应用低通滤波器。假设滤波器的截止频率为100Hz。我不能只说:

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

这不起作用的原因是因为array [i]的值的范围是(-1,1)。那么我怎么应用这个过滤器呢?我要比较什么价值?

从物理角度来看,我可以看到它是如何工作的,一个电容器和一个电阻来计算截止频率并通过电路发送输入。但是以编程方式,我不知道如何实现这一点。我已经看到了很多这种在线实现,但代码没有足够的文档记录,无法理解发生了什么。

以下是我主机端的代码:

//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]);
}

我的内核只有如下:(显然这不是过滤器的代码,这是我感到困惑的地方)。

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

我发现这个PDF实现了很多过滤器。在文档末尾附近,您可以找到低通滤波器的浮动实现。

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

在该pdf的过滤器实现中,将数据[j]与值进行比较。我也不知道numItems或workItems是什么。

如果有人可以提供一些有用的见解,那就太棒了。我已经在低通滤波器上搜索了很多其他的例子,但我无法绕过实现。我希望我明白这个问题。我再次知道低通滤波器的工作原理。我只是不知道我需要比较什么值才能进行过滤。

发现这个问题:

Low Pass filter in C

1 个答案:

答案 0 :(得分:1)

我有一个可能的解决方案。我正在尝试的是移动平均冷杉(我被告知是最简单的低通滤波器形式,可以实现)。

需要什么:

  • FIFO缓冲区
  • 系数值(我从matlab生成并获得特定截止频率)
  • 程序的输入和输出数组

我没有实现这个代码,但我确实理解如何在理论层面上使用它。我在下面创建了一个图表来尝试解释这个过程。

enter image description here

基本上,从另一个输入数组中,值将一次一个地传递到FIFO缓冲区。每次传入一个值时,内核都将在具有'n'抽头的FIFO缓冲区中进行乘法运算。每个抽头都有一个与之关联的系数值。因此,特定元素的输入与系数值相乘,然后累计所有值并将其存储在输出缓冲区的一个元素中。

请注意,系数是在Matlab中生成的。我不知道如何抓住这些价值观。起初我只想使用1 / n的系数,但我很确定这只会扭曲信号的值。

这应该是诀窍,我现在要在代码中实现这个,但如果这个理论有任何问题,请随时纠正它。