Ayuda a implementar compresión de rango dinámico de audio

8

Estoy tratando de implementar la compresión de rango dinámico de audio en JavaScript (sin utilizar la API de audio web).

Hay muchos artículos para técnicos de sonido y documentación de alto nivel, pero no pude encontrar ninguna referencia útil para implementar realmente la compresión digital de rango dinámico.

Por lo que entiendo, hay al menos 3 pasos en el cálculo de la señal rectificada.

  1. calcular el nivel de entrada
  2. calcular la ganancia para aplicar a la señal
  3. aplicando la ganancia

Proceso el audio en bloques, así que para 1) estaba pensando en calcular el RMS de un bloque

¿Algún puntero a una buena referencia? ¿O alguien dispuesto a explicarme un poco los pasos necesarios para implementar esto?

sebpiq
fuente
1
Solo para estar seguro: desea implementar algo como esto: waves.com/plugins/c1-compressor , ¿verdad?
Deve
sí :) pero mucho más simple! Los controles que necesito serían umbral, rodilla, relación, ataque, liberación. Pero puedo comenzar con algo aún más simple
sebpiq

Respuestas:

4

Aquí hay algunas sugerencias:

  • Hay muchas implementaciones de código abierto (Sox, Audacity, etc.). Incluso si no los comprende, es posible que pueda traducir el código de C a javascript.
  • No conozco una buena explicación del proceso en línea, pero hay muchos libros sobre el tema:
    • El procesamiento de la señal de audio digital cubre este tema y está bien escrito. (Al igual que DAFX , pero DAFX está mal organizado y la cobertura es menos directa)
    • El audio digital con Java también cubre este tema y viene con un código Java que debería ser fácil de traducir a otros idiomas, como JavaScript. Este libro tiene muchos defectos, pero es bueno para alguien sin experiencia en programación de audio.

El principio es crear una envolvente de la señal (controlada por ataque y liberación), dar forma a esa envolvente utilizando alguna función de transferencia (controlada por relación, umbral y rodilla), y luego aplicar ese resultado a la señal original. A menudo sigue una etapa de ganancia de maquillaje.

La respuesta de @ Deve sugiere algunas posibles funciones de transferencia.

Bjorn Roche
fuente
La cuestión es que no conozco C, y sí, eso es un gran obstáculo cuando trabajo con dsp de audio, porque no puedo verificar las implementaciones existentes. De lo contrario, gracias por los libros, definitivamente comprobaré el primero al menos.
sebpiq
El libro DAFX tiene código matlab. IDK si tiene código matlab para un compresor.
Bjorn Roche
Para el libro "Procesamiento de señal de audio digital", los comentarios en Amazon dicen que es mejor para las personas con experiencia en ingeniería eléctrica. ¿Conoces algún libro que se centre más en algoritmos, el mejor sería, por ejemplo, en pseudocódigo?
sebpiq
1
De una forma u otra, tendrá que aprender algunas habilidades nuevas, creo.
Bjorn Roche
¡Sí, lo sé! Y estoy listo para eso. Es solo que realmente no quiero el código matlab, por ejemplo, ya que no quiero pagar por matlab para poder probarlos. Es por eso que le pregunté si conoce otros libros con, por ejemplo, pseudocódigo, en lugar de un lenguaje específico (como Java, que realmente no me interesa aprender).
sebpiq
2

Para un comienzo simple, usaría una característica no lineal sol(X) que comprime su señal de entrada:

y=sol(X)

donde (como lo señala el endolito en los comentarios) Xes la envolvente de la señal de audio de entrada yy es la envolvente de salida que se aplica a la señal de audio real. sol(X)puede ser cualquier función que atenúe los valores de entrada grandes más fuertes que los valores de entrada pequeños. La ley A yμ-Las funciones legales se han desarrollado para comprimir señales de voz para telefonía, por ejemplo. Sin embargo, no sé qué tan bueno suena esto para la música.

Otra función de compresión muy simple sería atenuar todas las amplitudes por encima de cierto umbral. δ:

sol(X)={XparaXδunaX+(1-una)δparaX>δ
dónde una<1Es atenuación. Pero esto no funcionará muy bien ya que nuestro sentido del oído es logarítmico, por lo que la atenuación podría ser demasiado fuerte. Esta es la razón por la cual los compresores de audio funcionan en una escala logarítmica y llevan a la misma función que la anterior, pero todos los valores son logarítmicos y con respecto al valor máximo posible. porX>0 0:
Iniciar sesión(sol(X))={Iniciar sesión(X)paraXδ1rIniciar sesión(X)+(1-1r)Iniciar sesión(δ)paraX>δ

Para compresores de audio, δ generalmente se da en dB y r se expresa como alguna relación, por ejemplo, 3: 1 (es decir r=3) Esto produce una función exponencial, cuando se expresa linealmente (espero que sea correcto, verifíquelo tambiénX>0 0):

sol(X)={XparaXδδ1-1/ /rX1/ /rparaX>δ
Esta función tiene una "rodilla dura", lo que significa que la función Iniciar sesiónsol(X) no es diferenciable en X=δ. Para una "rodilla suave" necesitaría una transición suave en ese punto. La extensión de las funciones anteriores para negativoX es sencillo, simplemente multiplique con la función signum y tome el valor absoluto de X.

El ataque y la liberación tienen un impacto en diferentes sonidos como patadas, trampas y voces. Determinan cuánto tiempo antes de alcanzar el umbral el compresor debería comenzar a funcionar y cuánto tiempo debería seguir funcionando después de que la señal haya caído por debajo del umbral. Para implementar esto, tendrá que usar algún tipo de anticipación.

Como todas las amplitudes a continuación δestán atenuados, el rango dinámico disponible no está completamente explotado. Esto se corrige con la llamada "ganancia de maquillaje", que es solo una simple multiplicación de la señal comprimida con un factor de gananciasol>1. Al reducir primero el rango dinámico y luego amplificar los compresores de señal puede hacer que la música parezca "más fuerte".

Deve
fuente
¡Gracias! Gran explicación Llegué a una función de transferencia cercana a la que usted proporcionó, pero la mía no incluyó el umbral (simplifiqué con el umbral = 0), por lo que tengo que volver a calcular.
sebpiq
En realidad, la función de transferencia que obtengo al agregar el umbral es x ^ (1 / r) * 10 ^ (- sigma / (20 * r))
sebpiq
Lo siento, mis definiciones de funciones fueron un desastre porque olvidé agregar el sesgo constante. Lo he corregido. La última expresión, sin embargo, es correcta en mi opinión. Debe cumplirsol(δ)=δ. No hay un factor de 20 involucrados aquí porque estamos tomando el logaritmo del lado izquierdo y derecho para que cualquier factor constante se cancele.
Deve
Parecen distorsión, no compresión. La distorsión es un cambio de nivel que se produce muestra por muestra, mientras que la compresión es algo que ocurre durante muchos ciclos de la forma de onda (cada uno de los cuales está compuesto por muchas muestras). La distorsión no lineal va a sonar horrible.
endolito
@endolith Tienes razón, gracias por la pista. He actualizado mi respuesta en consecuencia.
Deve