Pregunta

Estoy escribiendo un código que reproduce archivos WAV a diferentes velocidades, por lo que la onda sea más lento y es de baja frecuencia, o más rápido y más aguda. Actualmente estoy usando interpolación lineal simple, así:

            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));
            }

Esto funciona bien, pero tiende a sonar bien sólo cuando me baja la frecuencia de la reproducción (es decir, lento hacia abajo). Si levanto el terreno de juego en la reproducción, este método tiende a producir artefactos de alta frecuencia, presumiblemente debido a la pérdida de la información de la muestra.

Sé que bicúbica y otros métodos de interpolación Volver a muestrear utilizando algo más que los dos valores de las muestras más cercanas como en mi ejemplo de código, pero no puedo encontrar buenos ejemplos de código (C # preferentemente) que podría conectar a sustituir a mi lineales método de interpolación aquí.

¿Alguien sabe de ningún buenos ejemplos, o cualquiera puede escribir un simple método de interpolación bicúbica? Voy a Bounty Esta si tengo que hacerlo. :)

Actualizar : aquí hay un par de C # implementaciones de métodos de interpolación (gracias a Donnie DeBoer para la primera y Nosredna para el segundo):

    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;
    }

En estas funciones, x1 es el valor de la muestra antes del punto que está tratando de estimar y X2 es el valor de la muestra después de su punto. x0 se deja de x1, x3 y es derecha de x2. t va de 0 a 1 y es la distancia entre el punto de que está realizando la estimación y el punto x1.

El método de Hermite parece que funciona bastante bien, y parece reducir el ruido un poco. Más importante aún, parece sonar mejor cuando la onda se acelera.

¿Fue útil?

Solución

Mi recurso favorito para audio interpolación (especialmente en aplicaciones de remuestreo) es papel del "elefante" de Olli Niemitalo .

He usado un par de estos y suenan excelente (mucho mejor que una solución cúbico recta, que es relativamente ruidoso). Hay formas spline, formas de Hermite, Watte, parabólicas, etc., y que se discuten de un audio punto de vista. Esto no es sólo el ajuste polinómico ingenua típico.

Y el código está incluido!

Para decidir cuál usar, es probable que desee comenzar con la tabla de la página 60, que agrupa a los algoritmos en la complejidad del operador (cuántos multiplica, y cuántos añade). A continuación, elija una de las mejores soluciones de señal a ruido - utilizar sus oídos como una guía para tomar la decisión final. Nota:. En general, la mayor SNR, mejor

Otros consejos

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;
}

donde X1 y X2 son las muestras que se están interpolados entre, x0 es vecino de la izquierda de x1, x3 y es vecino de la derecha de x2. t es [0, 1], que denota la posición de la interpolación entre x1 y x2.

Sinceramente, interpolación cúbica generalmente no es mucho mejor para el audio que lineal. Una simple sugerencia para la mejora de su interpolación lineal sería el uso de un filtro antialiasing (antes o después de la interpolación, dependiendo de si se está acortando o alargando la señal de ella). Otra opción (aunque más costoso computacionalmente) es SINC-interpolación, lo que se puede hacer con muy alta calidad.

Hemos lanzado un código nuevo muestreo simple, LGPL que puede hacer ambas cosas, como parte de WDL (ver resample.h).

polinomio de interpolación . La idea es que usted escoja un número de puntos de datos conocidos alrededor del punto que desea interpolar, calcular un polinomio de interpolación utilizando los puntos de datos y, a continuación, averiguar el valor del polinomio y el punto de interpolación.

Hay otros métodos. Si puede soportar la matemáticas, mira reconstrucción de la señal , o google de "interpolación de señal".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top