audio - transmiten - processing processing
Generación de forma de onda limitada (4)
Esto es lo que se me ocurrió, inspirado en las ideas de Nils. Pegarlo aquí en caso de que sea útil para otra persona. Simplemente recuadro filtrar una onda de diente de sierra analíticamente usando el cambio de fase de la última muestra como tamaño de núcleo (o punto de corte). Funciona bastante bien, hay un alias audible en las notas más altas, pero para el uso normal suena genial.
Para reducir aún más el alias, el tamaño del kernel puede aumentarse un poco, por lo que es 2 * phaseChange, por ejemplo, también suena bien, aunque se pierde un poco de las frecuencias más altas.
Además, aquí hay otro buen recurso de DSP que encontré al explorar SP para temas similares: Synthesis ToolKit en C ++ (STK) . Es una biblioteca de clases que tiene muchas herramientas DSP útiles. Incluso tiene generadores de forma de onda limitados a la banda listos para usar. El método que usan es para integrar el sinc como lo describí en mi primera publicación (aunque supongo que lo hacen mejor que yo ...).
float getSaw(float phaseChange)
{
static float phase = 0.0f;
phase = fmod(phase + phaseChange, 1.0f);
return getBoxFilteredSaw(phase, phaseChange);
}
float getPulse(float phaseChange, float pulseWidth)
{
static float phase = 0.0f;
phase = fmod(phase + phaseChange, 1.0f);
return getBoxFilteredSaw(phase, phaseChange) - getBoxFilteredSaw(fmod(phase + pulseWidth, 1.0f), phaseChange);
}
float getBoxFilteredSaw(float phase, float kernelSize)
{
float a, b;
// Check if kernel is longer that one cycle
if (kernelSize >= 1.0f) {
return 0.0f;
}
// Remap phase and kernelSize from [0.0, 1.0] to [-1.0, 1.0]
kernelSize *= 2.0f;
phase = phase * 2.0f - 1.0f;
if (phase + kernelSize > 1.0f)
{
// Kernel wraps around edge of [-1.0, 1.0]
a = phase;
b = phase + kernelSize - 2.0f;
}
else
{
// Kernel fits nicely in [-1.0, 1.0]
a = phase;
b = phase + kernelSize;
}
// Integrate and divide with kernelSize
return (b * b - a * a) / (2.0f * kernelSize);
}
Estoy escribiendo un sintetizador de software y necesito generar formas de onda sin alias y limitadas en banda en tiempo real a una frecuencia de muestreo de 44,1 kHz. Por ahora, la forma de onda del diente de sierra funcionaría, ya que puedo generar una onda de pulso al mezclar dos dientes de sierra, uno invertido y otro con fase.
Hasta ahora he intentado los siguientes enfoques:
Precompilando samples de forma de onda perfectamente limitados en banda de un ciclo a diferentes frecuencias de límite de banda en el inicio, y luego reproduciendo los dos más cercanos mezclados. Funciona bien, supongo, pero no se siente muy elegante. Se necesitan muchas muestras o se escucharán las "brechas" entre ellas. La interpolación y la mezcla también consumen mucha CPU.
Integrando un tren de pulsos sinc compensados DC para obtener una onda de diente de sierra. Suena genial, excepto que la ola se aleja de cero si no obtienes la compensación de CC exactamente correcta (lo cual me pareció realmente complicado). El problema de CC se puede reducir agregando un poco de fuga al integrador, pero luego pierde las bajas frecuencias.
Entonces, mi pregunta es: ¿Cuál es la forma habitual de hacerlo? Cualquier solución sugerida debe ser eficiente en términos de CPU, ya que debe hacerse en tiempo real, para muchas voces a la vez.
Hay muchas formas de acercarse a la generación de forma de onda de banda limitada. Terminará intercambiando el costo computacional con la calidad como de costumbre.
Le sugiero que eche un vistazo a este sitio aquí:
¡Mira el archivo! Está lleno de buen material. Acabo de hacer una búsqueda sobre la palabra clave "bandlimited". El material que aparece debe mantenerse ocupado durante al menos una semana.
Por cierto, no sé si eso es lo que estás buscando, pero al menos hice una generación de forma de onda reducida (por ejemplo, no muy limitada) hace un par de años. Acabo de calcular la integral entre la última y actual posición de muestra. Para las formas de onda de sintetizador tradicionales, puede hacerlo bastante fácil si divide el intervalo de integración en las singularidades (por ejemplo, cuando el diente de sierra obtiene su restablecimiento). La carga de la CPU era baja y la calidad aceptable para mis necesidades.
Tuve los mismos problemas de deriva, pero la aplicación de un pase alto con una frecuencia de corte muy baja en la integral eliminó ese efecto. Los sintetizadores analógicos reales no bajan a la región de subhertz de todos modos, por lo que no se perderá demasiado.
¡La compensación de CC de una blit puede reducirse con un filtro de paso alto simple! - ¡muy parecido a un circuito analógico real donde usan una tapa de bloqueo de CC!
Una forma rápida de generar formas de onda limitadas por banda es mediante el uso de pasos de banda limitada (BLEP). Generas el paso de banda limitada en sí mismo:
y almacenar eso en una tabla de ondas, luego reemplazar cada transición con un paso de banda limitada, para crear formas de onda que se ven así:
Vea el recorrido en Band-Limited Sound Synthesis .
Como este BLEP no es causal (lo que significa que se extiende al futuro), para generar formas de onda en tiempo real, es mejor usar el paso de banda mínima de fase limitada, llamado MinBLEP , que tiene el mismo espectro de frecuencia, pero solo se extiende en el pasado:
Los MinBLEPs llevan la idea más allá y toman un sinc con ventana, realizan una reconstrucción de fase mínima y luego integran el resultado y lo almacenan en una tabla. Ahora para hacer un oscilador, simplemente inserta un MinBLEP en cada discontinuidad en la forma de onda. Entonces para una onda cuadrada inserta un MinBLEP donde la forma de onda se invierte, para la onda de sierra se inserta un MinBLEP donde el valor se invierte, pero se genera la rampa como es normal.