【问题标题】:Resampling a sound sample, what filter do I use?重新采样声音样本,我使用什么过滤器?
【发布时间】:2011-05-22 13:38:07
【问题描述】:

我正在尝试将信号(声音样本)从一个采样率重新采样到更高的采样率。 不幸的是,它需要某种过滤器,因为似乎会出现一些“混叠”,而且我不熟悉过滤器。这是我想出的:

int i, j, a, b, z;

a = 44100;
b = 8363;

// upsample by a
for(i = z = 0; i < samplen; i++)
    for(j = 0; j < a; j++)
        cbuf[z++] = sampdata[i];

// some filter goes here???

// downsample by b
for(j = i = 0; i < z; i += b)
    buf[j++] = cbuf[i];

新样本与原始样本非常相似,但有一些噪音。 你能告诉我我需要添加什么过滤器,最好是一些与该过滤器相关的代码?

原声:http://www.mediafire.com/?9gnga1in52d6t4x 重采样声音:http://www.mediafire.com/?x34h7ggk8n9k8z1

【问题讨论】:

  • 从简单的线性插值开始:不要将cbuf[z] 设置为sampdata[i],而是将其设置为sampdata[i] + (j/(double)a)(sampdata[i+1] - sampdata[i])。我对声音处理知之甚少,不知道这是否足够,但它会让你很忙,直到有人知道他们的东西:-)你可能还需要对下采样进行抗锯齿处理。

标签: c audio filter signal-processing sampling


【解决方案1】:

线性插值在这里工作得很好。问题在于作者的代码,它不是线性插值 - 它只是采用最接近的值,根本没有任何插值。

这是一个线性插值示例,源采样率 = 5,目标采样率 = 6

src val:    5    10   5    0    5    (this is our audio data, 5 samples)
src idx:    0    1    2    3    4    (source positions for 5 samples)

dst idx:    0   1   2   3   4   5    (destination positions for 6 samples)
dst val:    ?   ?   ?   ?   ?   ?

首先让我们计算比例因子:

scaleCF = srcSampleRate / dstSampleRate             = 0.83333334

让我们看看 dst[2] 对于 dst 索引 2,我们需要从 src[1] 和 src[2] 中参与 让我们找到最近的源索引及其贡献系数:

idxD = (double)idx * cf;  = 0.833333334 * 2         = 1.6666668

a = (int)idxD = (int)(1.6666668)                    = 1
b = a + 1                                           = 2


bCF = idxD - a = 1.6666668 - 1                      = 0.6666668
aCF = 1.0 - bCF = 1.0 - 0.6666668                   = 0.3333332

res = (float)(aCF * Data[a] + bCF * Data[b])
    = 0.3333332 * 10 + 0.6666668 * 5                = 6.6666666

所以我们在位置 2 的目标值将是 6.6666666 算法可用于下采样/上采样。 可能不是最有效的解决方案,也不是最准确的解决方案,但仍然易于实施并且效果很好。

【讨论】:

    【解决方案2】:

    在重新采样到较低的采样率之前,您必须对原始采样率进行低通滤波,低于采样率的 1/2 倍,否则您将引入失真伪影。对于超过采样率 1/2 的频率,频谱将自行折叠。因此,如果您想从 44100 重新采样到 11025,您必须在 11025 或 5500 Hz 的 1/2 处过滤 44100 低通滤波器,因为再现的忠实度会随着较低的带宽而降低,最好使用最大幅度(如 -10Db 的幅度)来执行此操作。对于带符号的 16 位,该值类似于 10^(-10/20)*2^(16-1) 或 10362 +/- 用于最大幅度。确切的算法可以在网上找到,因为这些旧的和基本的想法不应该有知识产权。在没有舍入双精度浮点进行所有计算之后,然后将结果四舍五入到它们正确的整数值,并在时间尺度上准确插值一组与另一组相交的位置。它需要相当大的想象力和记忆力以及以前的经验,然后将您带入数学家物理程序员的领域。 :-O :-)

    【讨论】:

      【解决方案3】:

      我遇到过的最好的重采样代码:http://shibatch.sourceforge.net/

      获取源代码,并尝试从中学习一些东西。它处于恶劣的状态,但该重采样器的结果远远高于其他一切。

      【讨论】:

        【解决方案4】:

        直接使用 FFMpeg 和 avcodec。这是一个很好的例子,展示了如何做到这一点:

        http://tdistler.com/projects/audio-resampling-with-ffmpeg

        【讨论】:

          【解决方案5】:

          除非采样率(源和目标)都远高于数据中的最高频率,否则不要使用线性插值。这是一个很差的低通滤波器。

          您需要的是一个内插低通滤波器,其阻带开始低于您正在处理的两个采样率中较低的一半。实现这一点的常用方法是使用 IIR 滤波器进行上采样/下采样,以及使用多相 FIR 滤波器。如果您不需要实时性能并且不想上采样/下采样,则窗口式 Sinc 插值器也适用于此。这是一个Windowed Sinc interpolating low-pass filter in Basic,转换成C应该很简单。

          如果您想使用 IIR 过滤,这里是规范的 Cookbook for biquad IIR filters

          如果您想了解音频重采样理论的最佳解释,这里是Stanford CCRMA's Resampling page

          【讨论】:

          • 谢谢。我对过滤器一无所知,但我确实需要运行时性能,因为我正在制作一种音乐播放器。老实说,我不认为从一种采样率转换为更高的采样率会这么复杂。
          • @X-N2O :如果您希望结果听起来不错,这只会很复杂。 :)
          【解决方案6】:

          几个cmets,虽然我只是猜测你的实际意图:

          • 您正在以原始采样率 44100 倍 的速率进行上采样。例如,如果您的输入是 10kHz,那么您的中间 cbuf[] 将是 441MHz,这对于大多数音频分析来说有点高。假设您希望 cbuf[] 的频率为 44100Hz,那么您只需在 cbuf[] 中创建 44100/OrigSampleRate 的样本 sampdata[] 中的每个样本。
          • 您在上采样循环中将z 增加了两次。这导致cbuf[] 的所有奇数元素都具有其原始值。我相信这最终会导致最终的buf[] 包含无效的奇数元素,这可能是您噪音的来源。如果您创建的 cbuf 中的元素数量没有至少是所需数量的两倍,那么它还存在潜在的缓冲区溢出。
          • 正如 Steve 所提到的,线性插值通常是最简单的,可以在上采样时产生良好的结果。如果需要,可以进行更复杂的上采样(多项式、样条等)。同样,在进行下采样时,您可能希望对样本进行平均而不是截断。

          【讨论】:

          • 哦,我没有注意到我将 z++ 增加了两次。感谢您指出这一点。
          【解决方案7】:

          您是否考虑过为此使用专门的库,例如 libsamplerate

          它非常便携,它是由知道如何正确执行此类操作的人开发的。即使你不直接使用它,你也可能会发现它实现的算法非常有趣。

          【讨论】:

          • 如果独立程序就足够了,SoX (sox.sourceforge.net) 是另一种选择。它内置了采样率转换。简单如sox file1 -r [newsamplerate] file2
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-05-07
          • 2012-10-25
          • 2020-07-20
          • 2022-01-11
          • 2010-10-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多