PCM算法用于上采样

3

我有一份8k16bit pcm音频,想将其上采样为16k16bit。我需要手动完成此操作。

有人能告诉我线性插值的算法吗?我应该在每两个字节之间进行插值吗?

另外,当我进行上采样时,我必须对wav头文件进行更改 - 我应该改变什么?

4个回答

8

正如其他人所提到的,线性插值并不能提供最佳的音频质量,但它简单而且成本较低。

对于每个新创建的样本,只需与下一个样本取平均值,例如:

short[] source = ...;
short[] result = new short[source.length * 2];
for(int i = 0; i < source.length; ++i) {
  result[i * 2] = source[i];
  result[i * 2 + 1] = (source[i] + source[i + 1]) / 2;
}

你应该寻找一个能够帮助你处理WAV文件的库。虽然这是一个简单的格式,但如果有可用的代码可以完成你需要的工作,你不应该自己去做。顺便问一下,你为什么要这样做呢?也许你可以使用sox或类似的工具来完成这个任务。


3
可以有人告诉我线性插值算法吗?我应该在每两个字节之间进行插值吗?
当然可以:
double interpolate_linear(double a, double b, double x) {
    assert(0.0 <= x);
    assert(1.0 >= x);

    if (0.0 >= x)
        return a;
    else if (1.0 <= x)
        return b;
    else
        return (1.0 - x) * a + x * b;
}

线性插值虽然比没有好,但误差较大。如果有CPU时间,最好用零填充和窗口处理。

另外,当我进行上采样时,我需要对wav头进行更改-我该如何更改?

不确定Java怎么做。


1
请注意,“window”是另一种东西;这里应该使用“filter”这个术语... - Oliver Charlesworth

2

0

关于标题我不确定,但是我会建议你研究一下三次样条插值。你可以看看this website。它有一种非常简洁的方法来执行三次插值。我不确定如何修改标题,但我相信在 Stack Overflow 上已经有了相关的答案,你可以搜索一下。


好的,我正在使用线性插值,计算似乎是正确的,但我得到的只是一些静态噪音。我正在每两个字节之间进行插值,在它们之间添加一个新字节...但我认为这是我的错误。由于PCM是16位,这意味着每个样本有16位,所以也许我应该在每两个样本(16位的块)之间进行插值。这是正确的吗?还是我整个想法都错了? - gop
如果你展示你的代码,我可以看一下并检查是否有任何问题(只是插值部分)。 - Phonon
4
当然,你应该在样本对之间进行插值,而不是字节对之间进行插值。单独的字节没有意义。 - Oliver Charlesworth
1
是的。当进行线性插值时,每个新样本都是它所处位置两个样本的平均值。 - Phonon
再次感谢您的帮助,我会明天写信告诉您结果 - 希望成功 :) - gop
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接