2011-03-01 10 views
10

Hola amables personas del mundo de la informática de audio,incrementar el tono de programación de una serie de muestras de audio

tengo una serie de muestras que respresent una grabación. Digamos que son 5 segundos a 44100Hz. ¿Cómo jugaría esto con un tono aumentado? ¿Y es posible aumentar y disminuir el tono de forma dinámica? Al igual que el tono aumenta lentamente para duplicar la velocidad y luego retroceder.

En otras palabras, quiero tomar una grabación y reproducirla como si estuviera siendo 'arañada' por un d.j.

El seudocódigo siempre es bienvenido. Voy a escribir esto en C.

Gracias,


EDIT 1

Permítame aclarar mis intenciones. Quiero mantener la reproducción a 44100Hz y, por lo tanto, necesito manipular las muestras antes de la reproducción. Esto también se debe a que quisiera mezclar el audio que tiene un tono aumentado con audio que se ejecuta a una velocidad normal de.

Expresado de otra manera, ¿tal vez necesito reducir el audio en el mismo número de muestras de alguna manera? De esa manera, cuando se reproduce, ¿sonará más rápido?


EDIT 2

Además, me gustaría hacer esto por mí mismo. No hay bibliotecas, por favor (a menos que sienta que podría elegir el código y encontrar algo interesante).


EDITAR 3

Una pieza de muestra de código escrito en C que tiene 2 argumentos (matriz de muestras y factor de inclinación) y luego devuelve una matriz de la nueva de audio sería fantástico!


PS he comenzado una recompensa por esto, no porque no creo que las respuestas ya dadas no son válidos. Solo pensé que sería bueno obtener más comentarios sobre el tema.



PREMIO DE BOUNTY

Sinceramente me gustaría poder distribuir el botín lo largo de varias respuestas diferentes, ya que eran un buen número que pensé que era muy servicial. Grito especial a Daniel por pasarme un código y AShelly y Hotpaw2 por poner en tales respuestas detalladas.

Aunque finalmente utilicé una respuesta de another SO question referenciada por datageist, el premio es para él.

Gracias de nuevo a todos!

+0

Por favor, aclare EDIT 3. Raspar un registro como un DJ dará como resultado un archivo que no tiene la misma longitud. p.ej. Si un DJ hace girar un disco dos veces más rápido, un archivo de grabación de ese sonido sería la mitad de la longitud original en el tiempo. ¿Es esto lo que quieres? – hotpaw2

+0

@ hotpaw2. Sí, lo siento por eso. He corregido EDIT 3. De hecho, sería la mitad de longitud y eso es exactamente lo que estoy buscando. Gracias :) –

Respuesta

9

Eche un vistazo al artículo "Elefante" en la respuesta de Nosredna a esto (muy similar) SO pregunta: How do you do bicubic (or other non-linear) interpolation of re-sampled audio data?

implementaciones de ejemplo se proporcionan partir de la página 37, y para la referencia, la respuesta de AShelly corresponde a la interpolación lineal (en la misma página). Con un pequeño ajuste, cualquiera de las otras fórmulas en el documento podría ser conectada a ese marco.

Para evaluar la calidad de un método de interpolación dado (y la comprensión de los problemas potenciales con el uso de esquemas "más baratos"), echar un vistazo a esta página:

http://www.discodsp.com/highlife/aliasing/

Para más teoría que es probable que desee para hacer frente (con código fuente), esta es una buena referencia, así:

https://ccrma.stanford.edu/~jos/resample/

0

Para disminuir y aumentar el tono es tan simple como reproducir la muestra a una velocidad más baja o más alta que 44.1kHz. Esto producirá un sonido de grabación más lento/más rápido, pero deberá agregar el 'scratchiness' de los registros reales.

+0

Por favor, consulte mi EDITAR 1. –

+1

+1 Considero que esta es la solución más simple. La mayoría de los audífonos HW admiten el cambio de la velocidad de reproducción muy fácilmente. – user492238

+0

@ user492238 El hardware de audio común se comparte entre las aplicaciones y se ejecuta a una tasa fija. Los mezcladores de software son proporcionados por el SO para dar la impresión de que usted es el "propietario" del hardware. –

0

This me ayudó con el nuevo muestreo, que es la misma cosa que necesita sólo se veía desde el lado opuesto.

Si no puede encontrar el código, haga ping, tengo una buena rutina de C para esto.

+0

No puedo ver, ¿cómo podría ayudar FIR aquí? Lo que TH OP está buscando es alterar el audio de una manera * no lineal *. Básicamente, ¿para qué sirve FIR es para cambiar la magnitud de varias frecuencias en el audio, no para transformar las frecuencias inherentes, la señal está hecha? – user492238

8

Una forma es mantener un índice de punto flotante en la onda original, y mezclar las muestras interpoladas en la onda de salida.

//Simulate scratching of `inwave`: 
// `rate` is the speedup/slowdown factor. 
// result mixed into `outwave` 
// "Sample" is a typedef for the raw audio type. 
void ScratchMix(Sample* outwave, Sample* inwave, float rate) 
{ 
    float index = 0; 
    while (index < inputLen) 
    { 
     int i = (int)index;   
     float frac = index-i;  //will be between 0 and 1 
     Sample s1 = inwave[i]; 
     Sample s2 = inwave[i+1]; 
     *outwave++ += s1 + (s2-s1)*frac; //do clipping here if needed 
     index+=rate; 
    } 

}

Si desea cambiar rate sobre la marcha, se puede hacer eso también.

Si esto crea artefactos ruidosos cuando rate> 1, intente reemplazar *outwave++ += s1 + (s2-s1)*frac; con esta técnica (from this question)

*outwave++ = InterpolateHermite4pt3oX(inwave+i-1,frac); 

donde

public static float InterpolateHermite4pt3oX(Sample* x, float t) 
{ 
    float c0 = x[1]; 
    float c1 = .5F * (x[2] - x[0]); 
    float c2 = x[0] - (2.5F * x[1]) + (2 * x[2]) - (.5F * x[3]); 
    float c3 = (.5F * (x[3] - x[0])) + (1.5F * (x[1] - x[2])); 
    return (((((c3 * t) + c2) * t) + c1) * t) + c0; 
} 

Ejemplo de utilización de la técnica de interpolación lineal en " Windows Startup.wav "con un factor de 1.1. El original se encuentra en la parte superior, la versión acelerada está en la parte inferior:

puede que no sea matemáticamente perfecto, pero suena como debe ser, y debería funcionar bien para las necesidades de la OP ..

+0

Esto no puede funcionar, ya que el audio no tiene píxeles en la pantalla, y le proporcionará efectos de sonido e ruidos increíbles e insoportables en la señal de salida.Además, no necesitará recortar porque no puede haber desbordamiento ya que los pesos siempre suman 100%. –

+0

@Daniel Mošmondor, este _funciona_, suponiendo que 'inwave' es un solo canal pcm, y su factor no es tan extremo como para obtener aliasing. Tengo un programa de trabajo en ruby ​​para probarlo. Si trazas muestras en función del tiempo, obtienes una forma de onda. Es perfectamente válido para interpolar puntos para darle una representación diferente de esa forma de onda. – AShelly

+0

En cuanto al recorte, agregué ese comentario para tratar con la observación del OP de que quería mezclar la muestra estirada en otra pista. Este código maneja el caso donde 'outwave' ya contiene buenos datos. – AShelly

3

Sí, es posible.

Pero esto no es una pequeña cantidad de pseudo código. Usted está pidiendo un algoritmo de modificación de tono de tiempo, que es una cantidad bastante grande y complicada de código DSP para resultados decentes.

Aquí hay un Time Pitch stretching overview from DSP Dimensions. También puedes buscar algoritmos de vocoder de fase en Google.

añadido:

Si usted quiere "cero", como DJ podría hacer con un LP en una placa giratoria física, no es necesario la modificación de paso del tiempo. El rayado cambia el tono y la velocidad de juego en la misma cantidad (no de forma independiente, ya que requeriría una modificación de paso de tiempo).

Y la matriz resultante no será de la misma longitud, pero habrá más corto o más largo por el amont de cambio de tono/velocidad.

Puede cambiar el terreno de juego, así como hacer que el sonido se reproduzca más rápido o más lento en la misma proporción, con sólo volver a muestrear la señal filtrada mediante interpolación correctamente. Simplemente mueva cada punto de muestra, en lugar de 1.0, por suma de coma flotante según el cambio de velocidad deseado, luego filtre e interpole los datos en ese punto. La interpolación usando un kernel de interpolación Sinc con ventana, con una frecuencia de transición de filtro de paso bajo por debajo de la frecuencia de muestreo local original e interpolada, funcionará bastante bien. La búsqueda de "interpolación Sinc con ventana" en la web arroja muchos resultados adecuados.

Necesita un método de interpolación que incluya un filtro de paso bajo, de lo contrario escuchará un ruido de alias molesto. (La excepción a esto podría ser si su archivo de sonido original ya está severamente filtrado de paso bajo una década o más por debajo de la frecuencia de muestreo).

2

Si desea que este hecho fácilmente, ver la sugerencia de AShelly [editar: de hecho, pruébelo primero de todos modos]. Si necesita buena calidad, básicamente necesita un phase vocoder.

La idea básica de un vocoder de fase es encontrar las frecuencias en las que se compone el sonido, cambiar las frecuencias según sea necesario y resintetizar el sonido. Por lo tanto una simplificación brutal sería:

  1. plazo FFT
  2. cambio de todas las frecuencias por un factor
  3. FFT inversa de ejecución

Si va a implementar este mismo, que sin duda debe leer a thorough explanation of how a phase vocoder works. El algoritmo realmente necesita muchas más consideraciones que la simplificación de tres pasos anterior.

Por supuesto, ready-made implementaciones exist, pero de la pregunta que reúno, usted quiere hacer esto usted mismo.

+1

Me gusta el segundo enlace, está bien ilustrado. Pero estoy un poco confundido: en el algoritmo descrito, después de la FFT inversa, obtienes "una señal que ahora está estirada o comprimida en el tiempo y el tono no se cambia". ¿Estás diciendo que para cambiar también el tono (ya que eso es lo que quiere el OP), necesitas modificar los datos de frecuencia después de la FFT? ¿Es eso tan simple como volver a interpretar qué tan amplios son los contenedores cuando haces lo inverso? – AShelly

+0

@AShelly: Lo que pasa es que primero el audio se estira/comprime mientras se mantiene el tono, luego se acelera/se ralentiza para obtener la longitud adecuada. Esto da como resultado el cambio de tono deseado. Mi simplificación general probablemente no se puede implementar directamente; Creo que esa es la idea, pero está hecha de esta manera para obtener las fases correctas. No tengo experiencia en la implementación de un vocoder, pero sí en otros usos de FFT/DCT. Por lo tanto, traté de señalar una buena fuente. – dancek

+0

Además, definitivamente sugiero probar primero el algoritmo de AShelly, si es importante hacerlo usted mismo. – dancek

Cuestiones relacionadas