Convolución ACM
La convolución ACM ejecuta en la CPU la reverberación particionada de FMOD. Los lotes de entrada compartida transforman una señal seca, aplican particiones de impulso en float o half-float y hacen overlap-add del resultado húmedo.
Notas del repositorio hasta el 10 de octubre de 2026
El fallo que cerró
Subnautica: Below Zero podía arrancar con un crepitar, quedarse en silencio y recuperarse minutos después. El PCM que llegaba al dispositivo del anfitrión contenía flotantes no finitos. Una traza en memoria de los callbacks de DSP de FMOD mostraba audio finito entrando en la reverberación por convolución y basura saliendo. Las funciones HLE sceAcm_ConvReverb_SharedInput, el envío del lote y sceAcmBatchWait devolvían éxito sin escribir una salida.
FMOD mezclaba después ese búfer húmedo sin escribir en el grafo. Los NaN se propagaban por los efectos posteriores. El saneador de AudioOut los sustituía por silencio y no podía reparar el historial de filtro envenenado. Un segundo error hacía que la espera sobre el identificador de lote inicial -1 tuviera éxito. FMOD trata una espera inicial fallida como que todavía no hay un búfer húmedo anterior, y solo mezcla después de un trabajo realmente completado.
Convolución particionada
La disposición del descriptor coincide con la observada en el backend ACM de FMOD. Las particiones de la respuesta al impulso son bins complejos intercalados. Un bloque de B bins pertenece a una transformada de longitud 2B. Los búferes de entrada, de salida y de solape son distintos y planares. Solo se aceptan las disposiciones de espectro float32 y float16 con desplazamiento cero que se observaron.
Un lote se ejecuta en la CPU. El historial de entrada se conserva entre granos y a través de la vuelta del anillo, y el solape se arrastra al grano de salida siguiente. Varias salidas pueden compartir una transformada de entrada y un avance del historial. Una entrada mono puede alimentar más de un canal. La transformada inversa está normalizada. Una inversa independiente de una partición de impulso real colocó su energía en la primera mitad del bloque con relleno de ceros, lo que confirma el signo del espectro. El impulso empaquetado que usa el juego omite el bin de Nyquist.
Esperas, límites y la repetición
Los constructores capturan arrays de punteros y ganancias en un registro de comandos acotado. El PCM en sí se lee cuando empieza el lote. Una espera tiene éxito solo para un lote que ese contexto completó de verdad. Destruir el contexto libera el historial. Los límites no válidos, las codificaciones de comando desconocidas y los layouts no admitidos devuelven errores.
Las operaciones autónomas de FFT, IFFT y de panoramizador de ACM no están implementadas. Los canales tienen un tope de 8, las salidas de 32 y el bloque de 1024. El almacenamiento del historial está acotado. En el runner firmado, 90 instantáneas de PCM de una por segundo no contenían muestras no finitas, con un pico de 0.1255 y el primer audio por encima de 0.001 a los 11.03 segundos. El responsable confirmó el sonido. Las muestras son una sonda, no cada muestra que emitió el juego.
Qué está implementado
- Convolución FFT particionada para los lotes de reverberación de entrada compartida y de IR compartida de FMOD.
- Espectros complejos float32 y float16, overlap-add e historial entre granos.
- Esperas que tienen éxito solo para un lote completado de ese contexto. El identificador inicial -1 falla.
- PCM finito en la repetición de Subnautica, sin el crepitar ni el silencio posterior.
Qué falta todavía
- Las llamadas autónomas de FFT, IFFT y de panoramizador de ACM no están implementadas.
- Los desplazamientos de espectro distintos de cero y los layouts de enrutado no medidos se rechazan.
- La convolución se ejecuta en la CPU. No hay una ruta de FFT en la GPU.
Mecanismos relacionados
Qué describen estas páginas