我的低通滤波器出了什么问题?
我有一系列范围从 32766 到 -32767 的 int 样本。在尝试创建包络检测器的过程中,我编写了一个低通滤波器,但它似乎没有完成这项工作。请记住,我正在尝试一次性过滤整个数组(无缓冲区)。
这不是流式传输,而是应用于录制的音频以供以后播放。它是用 C 语言编写的。截止参数的示例是 0.5。
void lopass(int *input, float cutoff, int *output)
{
float sample = 0;
for (int i=1 ; i < (1430529-10); i++) // we will go through all except the last 10 samples
{
for (int j = i; j < (i+10); j++) { // only do this for a WINDOW of a hundred samples
float _in = (float)input[j];
float _out = (float)output[j-1];
sample = (cutoff * _in) + (32766 - (32766*cutoff)) * _out;
}
output[i] = (int)sample;
}
}
我想我会在 10 个样本的窗口上运行我的过滤语句。它不仅超级慢,而且实际上并没有多大作用,但似乎降低了整体幅度。 \
如果您对如何正确执行此操作有任何建议或建议(或代码!),那就太好了!
I have an array of int samples ranging from 32766 to -32767. In part of trying to create an envelope detector I've written a low pass filter, but it doesn't seem to be doing the job. Please keep in mind I'm trying to filter an entire array in one shot (no buffers).
This is not streamed, but applied to recorded audio for later playback. It is written in C. An example cutoff argument would be 0.5.
void lopass(int *input, float cutoff, int *output)
{
float sample = 0;
for (int i=1 ; i < (1430529-10); i++) // we will go through all except the last 10 samples
{
for (int j = i; j < (i+10); j++) { // only do this for a WINDOW of a hundred samples
float _in = (float)input[j];
float _out = (float)output[j-1];
sample = (cutoff * _in) + (32766 - (32766*cutoff)) * _out;
}
output[i] = (int)sample;
}
}
I thought that I would run my filtering statement on a window of 10 samples. Not only is it super slow, but it doesn't really do much but seemingly lower the overall amplitude. \
If you have any advice, or suggestions (or code!) on how to do this properly, that would be great!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
低通滤波器基本上是对多个值进行平均的某种变体。这意味着至少在正常情况下,您的内部循环将累积一个值。很难从代码中猜测出确切的意图,但最终会得到以下极其一般的结果:
就目前而言,这个只是进行平均,没有指定截止值 - 这意味着它有一个固定的(而且相当慢)的截止曲线。截止值仅由窗口中的样本数量决定。
为了控制截止值,您不必(至少通常)将所有输入值乘以相同的量 - 这基本上只会修改比例因子。相反,您获取要应用的截止曲线的一组样本(在您的情况下为 10 个),通过逆 FFT 运行它们,并获得一组 10 个系数。然后,您将这些系数应用到循环中:
窗口中的样本数量通常不是设计过程的输入,而是输出。首先指定截止频率(作为采样频率的一部分)和截止宽度,然后根据这些值计算必要的窗口大小。
有很多不同的技术可用于计算系数。然而,无论您如何计算它们,您通常都会得到一般顺序的结果 - 累积窗口中样本的总和,每个样本乘以各自的系数。
EE Times 有一篇关于滤波器设计的非常好的文章几年前。
A low-pass filter is basically some variant of averaging a number of values together. That means at least in the normal case your inner loop will accumulate a value. It's hard to guess the exact intent from your code, but you end up with something on the extremely general order of:
As it stands right now, this just does averaging, with no cutoff specified -- that means it has a fixed (and fairly slow) cuttoff curve. The cutoff is governed only by the number of samples in the window.
To control the cutoff, you do not (at least normally) multiply all the input values by the same amount -- that would basically just modify the scale factor. Instead, you take a set of samples (10 of them, in your case) of the cutoff curve you want to apply, run them through an inverse FFT, and get a set of 10 coefficients. You then apply those coefficients in your loop:
The number of samples in your window isn't normally an input to the design process -- rather, it's an output. You start by specify the cutoff frequency (as a fraction of the sampling frequency) and the cutoff width, and based on those you compute the necessary window size.
There are quite a few different techniques for computing your coefficients. Regardless of how you compute them, however, you normally end up with something on this general order -- accumulate the sum of the samples in the window, each multiplied by its respective coefficient.
The EE times had a pretty good article on filter design a few years ago.
不知道它是否相关,但在您的代码中,内部循环什么也不做,
与
Don't know if it's relevant, but in your code the inner loop is doing nothing
is the same as
过滤器中的算术看起来是错误的,正如 @pmg 已经指出的那样,您没有正确存储输出值。可能应该是:
仍然有一些小问题需要解决,但这至少应该作为一个相当粗糙的单极递归(IIR)滤波器工作。
The arithmetic in the filter looks wrong, and as @pmg already pointed out, you are not storing output values correctly. It should probably be:
There are still a few minor issues to be fixed but this should at least work as a fairly crude single pole recursive (IIR) filter.
这是一个内部循环中包含 10 个样本的损坏的移动窗口过滤器(实际上您只使用了 10 个样本中的最后一个样本),而在您的评论中您说您希望在矩形过滤器窗口中使用 100 个样本。
第一个错误将使您的滤波器转换频率高出 10 倍。
It's a broken moving-window filter of 10 samples in the inner loop (where you actually use only the last sample of the 10), when in your comments you say you want 100 samples in your rectangular filter window.
The first error will give you a filter transition frequency 10X too high.