你怎么做双三次(或其他非线性)重新采样的音频数据的插值?你怎么做双三次(或其他非线性)重新采样的音频

2019-06-14 09:18发布

我正在写一些代码,播放WAV文件,以不同的速度,使波或者是缓慢,低沉的,或者更快和更高的音调。 我目前使用简单的线性插值,就像这样:

            int newlength = (int)Math.Round(rawdata.Length * lengthMultiplier);
            float[] output = new float[newlength];

            for (int i = 0; i < newlength; i++)
            {
                float realPos = i / lengthMultiplier;
                int iLow = (int)realPos;
                int iHigh = iLow + 1;
                float remainder = realPos - (float)iLow;

                float lowval = 0;
                float highval = 0;
                if ((iLow >= 0) && (iLow < rawdata.Length))
                {
                    lowval = rawdata[iLow];
                }
                if ((iHigh >= 0) && (iHigh < rawdata.Length))
                {
                    highval = rawdata[iHigh];
                }

                output[i] = (highval * remainder) + (lowval * (1 - remainder));
            }

这工作得很好,但它往往OK音响只有当我降低了播放的频率(即慢下来)。 如果我提高对再现的音高,这种方法倾向于产生大概是因为样本信息的丢失的高频假象。

我知道双三次和其他插值方法重新取样使用不仅仅是最近的两个样本值作为我的代码例子更多,但我找不到任何好的代码样本(C#最好),我可以插入到这里取代我的直线内插法。

有谁知道任何很好的例子,或任何人都可以写一个简单的双三次插值方法? 如果我有,我会赏金这一点。 :)

更新 :这里有几个插值方法(感谢甄子丹德波尔的第一个和nosredna第二)C#实现的:

    public static float InterpolateCubic(float x0, float x1, float x2, float x3, float t)
    {
        float a0, a1, a2, a3;
        a0 = x3 - x2 - x0 + x1;
        a1 = x0 - x1 - a0;
        a2 = x2 - x0;
        a3 = x1;
        return (a0 * (t * t * t)) + (a1 * (t * t)) + (a2 * t) + (a3);
    }

    public static float InterpolateHermite4pt3oX(float x0, float x1, float x2, float x3, float t)
    {
        float c0 = x1;
        float c1 = .5F * (x2 - x0);
        float c2 = x0 - (2.5F * x1) + (2 * x2) - (.5F * x3);
        float c3 = (.5F * (x3 - x0)) + (1.5F * (x1 - x2));
        return (((((c3 * t) + c2) * t) + c1) * t) + c0;
    }

在这些功能中,X1是未来你想估计和x2是你的点之后的采样值的点的采样值。 X0是左X1的,而X3是正确的X2的。 吨从0到1,并且你估计点和点X1之间的距离。

埃尔米特方法似乎工作得很好,似乎在一定程度上降低了噪音。 更重要的是它似乎更好的声音时,波加快。

Answer 1:

我最喜欢的音频插值(特别是在重采样应用)资源是奥利Niemitalo的“大象”的论文 。

我已经使用了这些夫妇和他们的声音了不起的(比直立方体的解决方案,这是比较嘈杂的要好得多)。 有花键形式,埃尔米特形式,Watte,抛物线形等,并它们从音频点的视图讨论。 这不仅是典型的天真的多项式拟合。

和代码包含!

要决定使用哪一种,你可能要到60页开始的表,组算法到操作的复杂性(多少乘法,多少增加了)。 那么最好的信号与噪声的解决方案中进行选择 - 用你的耳朵为指导,以做出最终选择。 注:一般情况下, 较高的信噪比,效果更好。



Answer 2:

double InterpCubic(double x0, double x1, double x2, double x3, double t)
{
   double a0, a1, a2, a3;

   a0 = x3 - x2 - x0 + x1;
   a1 = x0 - x1 - a0;
   a2 = x2 - x0;
   a3 = x1;

   return a0*(t^3) + a1*(t^2) + a2*t + a3;
}

其中x1和x2之间进行插值的样本,X0为X1的左邻,和X3是X2的右邻。 t为[0,1],表示x1和x2之间的内插位置。



Answer 3:

老实说,立方插值不一般比线性更好的音频。 提高你的线性插值一个简单的建议是使用抗混叠滤波器(插值之前或之后,这取决于你是否缩短信号或延长它)。 另一种选择(虽然比较耗费计算)为正弦插值,可以用非常高的质量完成。

我们已经发布了一些简单的,LGPL代码重新取样,可以做这两个作为一部分WDL (见resample.h)。



Answer 4:

你要找的多项式插值 。 这个想法是,你挑一些围绕要插补点是已知的数据点,利用数据点计算插值多项式,然后找出多项式的值和插补点。

还有其他的方法。 如果你能忍受算算,看信号重构 ,或谷歌“信号插值”。



文章来源: How do you do bicubic (or other non-linear) interpolation of re-sampled audio data?