Audio 引入噪声的切比雪夫低通滤波器

Audio 引入噪声的切比雪夫低通滤波器,audio,filter,signal-processing,downsampling,Audio,Filter,Signal Processing,Downsampling,我根据这个站点生成的系数创建了一个简单的切比雪夫低通滤波器:,我正在使用它过滤掉16kHz采样率音频信号中4kHz以上的频率,然后再向下采样到8kHz。这是我的代码(它是C#,但这个问题不是C#特有的,请随意使用不同语言中的其他语言) // ///切比雪夫,低通,-0.5dB纹波,4阶,16kHz采样rte,4kHz截止 /// 类ChebyshevLpf4Pole { 常数int NZEROS=4; const int NPOLES=4; 常数浮动增益=1.403178626e+01f; 私

我根据这个站点生成的系数创建了一个简单的切比雪夫低通滤波器:,我正在使用它过滤掉16kHz采样率音频信号中4kHz以上的频率,然后再向下采样到8kHz。这是我的代码(它是C#,但这个问题不是C#特有的,请随意使用不同语言中的其他语言)

//
///切比雪夫,低通,-0.5dB纹波,4阶,16kHz采样rte,4kHz截止
/// 
类ChebyshevLpf4Pole
{
常数int NZEROS=4;
const int NPOLES=4;
常数浮动增益=1.403178626e+01f;
私人浮动汇率[]xv=新浮动汇率[NZEROS+1];
私有浮动[]yv=新浮动[NPOLES+1];
公共浮动过滤器(浮动无效)
{
xv[0]=xv[1];xv[1]=xv[2];xv[2]=xv[3];xv[3]=xv[4];
xv[4]=无效/增益;
yv[0]=yv[1];yv[1]=yv[2];yv[2]=yv[3];yv[3]=yv[4];
yv[4]=(xv[0]+xv[4])+4*(xv[1]+xv[3])+6*xv[2]
+(-0.1641503452f*yv[0])+(0.4023376691f*yv[1])
+(-0.9100943707f*yv[2])+(0.531638826F*yv[3]);
返回yv[4];
}
}
为了测试它,我使用Audacity创建了一个从20Hz到8kHz的正弦波“啁啾”。测试信号如下所示:

过滤后,我得到:

波形显示,滤波器确实降低了4kHz以上频率的振幅,但我的信号中添加了大量噪声。无论我尝试实现哪种类型的滤波器(例如巴特沃斯、升余弦等),情况似乎都是如此


是我做错了什么,还是这些滤波器只是在其他频率引入了人工制品?如果我使用平均每对样本的简单方法来减少样本,我根本不会得到这种噪声(但明显的是,混叠更糟糕)。

在第一次使用
xv
yv
数组之前,您没有正确初始化它们。在大多数语言中,这意味着它们的值未定义,这可能会导致像您这样的意外结果。将它们初始化为正确的值(如0)可能会解决您的问题。

在首次使用它们之前,您尚未正确初始化
xv
yv
数组。在大多数语言中,这意味着它们的值未定义,这可能会导致像您这样的意外结果。将它们初始化为适当的值(如0)可以解决您的问题。

我在Mathematica中检查了您的过滤代码,它在这里工作正常,没有引入噪声,因此噪声可能来自代码的其他部分


我在Mathematica中检查了你的过滤代码,它在这里工作得很好,没有引入噪声,因此噪声可能来自代码的其他部分


可能存在数值稳定性问题,特别是当任何极点靠近单位圆时。试着让你所有的中间术语都达到双精度,然后在最后回到单精度。我对C不太熟悉,但在C中这将是:

yv[4] = (float)(((double)xv[0] + (double)xv[4]) + 4.0 * ((double)xv[1] + (double)xv[3]) + 6.0 * xv[2]
             + (-0.1641503452 * (double)yv[0]) + (0.4023376691 * (double)yv[1])
             + (-0.9100943707 * (double)yv[2]) + (0.5316388226 * (double)yv[3]));

可能存在数值稳定性问题,特别是当任何极点靠近单位圆时。试着让你所有的中间术语都达到双精度,然后在最后回到单精度。我对C不太熟悉,但在C中这将是:

yv[4] = (float)(((double)xv[0] + (double)xv[4]) + 4.0 * ((double)xv[1] + (double)xv[3]) + 6.0 * xv[2]
             + (-0.1641503452 * (double)yv[0]) + (0.4023376691 * (double)yv[1])
             + (-0.9100943707 * (double)yv[2]) + (0.5316388226 * (double)yv[3]));

好吧,是我太傻了。我的LPF的创建发生在一个处理循环内部而不是外部,这意味着每512个样本我创建一个新样本,这意味着我将丢失保存的状态。只要在整个文件中运行一个过滤器实例,噪声就会消失,正如预期的那样,由于过滤器无法完全删除截止点以上的所有内容,我会得到锯齿频率


好吧,是我太傻了。我的LPF的创建发生在一个处理循环内部而不是外部,这意味着每512个样本我创建一个新样本,这意味着我将丢失保存的状态。只要在整个文件中运行一个过滤器实例,噪声就会消失,正如预期的那样,由于过滤器无法完全删除截止点以上的所有内容,我会得到锯齿频率


它是C#,因此它们将包含零。将编辑问题。我不想把它标记为C,因为我会用任何编程语言回答它是C,所以它们将包含零。我将编辑问题。我不想给它贴上C的标签,因为出于兴趣,我会用任何编程语言回答,你是否将中间项的精度限制为24位(即单精度浮点)?不,Mathematica默认使用双机精度,所以我使用了它。我会试试看是否可以用单精度重复过滤。谢谢,你是对的,出于兴趣,这是我代码的另一部分(见我的答案),你是否将中间项的精度限制为24位(即单精度浮点)?不,Mathematica默认使用双机精度,所以我使用了它。我会试试看是否可以用单精度重复过滤。谢谢,你是对的,这是我代码的另一部分(请参见我的答案)谢谢,我在调查时尝试了双精度版本的过滤器,但最终证明这是一个简单得多的问题(请参见我的答案)谢谢,在调查过程中,我确实尝试了双精度版本的过滤器,但最终证明这是一个简单得多的问题(见我的答案)