Es un proyecto hecho por mí.
- Biblioteca que reimplementa en C puro el runtime de FastEnhancer-Medium (modelo de mejora de voz en streaming a 48 kHz)
- Modelo original: https://github.com/aask1357/fastenhancer (Ahn et al., 2025)
- Usa tal cual los pesos a 48 kHz que el repositorio original publicó adicionalmente después del paper (16 kHz). Sin reentrenamiento, fine-tuning ni calibration set
- El modelo y los pesos son de los autores originales; lo optimizado aquí es la parte del runtime
■ Rendimiento
- En un solo núcleo de Apple M2 da un real-time factor de 0.069. En la misma máquina, ejecutar el mismo grafo con ONNX Runtime da 0.230, así que es 3.3 veces más rápido
- En un Galaxy S23+ (Snapdragon 8 Gen 2) da 0.096
- Casi no hay pérdida de calidad. En 824 utterances de VoiceBank-DEMAND, frente al modelo fp32, se queda en -0.006 PESQ. No es un nivel de diferencia que se pueda distinguir al oído
■ Optimizaciones aplicadas
No salió 3 veces más rápido por una sola técnica; se ajustaron varias capas por separado.
- Cuantización: el rango de activaciones se recalcula en cada frame. Por eso no hace falta ajustar ni distribuir un calibration set, y no se rompe aunque cambie la distribución de entrada
- Convolución: se aplica Winograd F(2,3) a conv con k=3, y hasta el epílogo que sigue (
dequant + bias + SiLU + fp16 write) se pliega en el mismo pase para eliminar buffers intermedios - Recurrencia: el GRU se fusiona por completo en un kernel por tier. La multiplicación de matrices del lado de entrada, la del estado oculto, las tres compuertas r/z/n y la actualización del hidden se resuelven en un solo kernel, así que el acumulador int32 no se derrama a memoria
- Atención: softmax procesa directamente puntajes int32. Como no se crea en absoluto una matriz de puntajes fp32, se elimina ese tráfico de memoria de ida y vuelta
- Memoria: los estados cross-stage (GRU hidden, encoder skip) se guardan en fp16 para reducir a la mitad el ancho de banda entre frames
- Kernels: se escribieron manualmente 6 kernels int8 GEMM por ISA y se seleccionan automáticamente al inicializar (ARM NEON/DOTPROD/I8MM, x86 AVX2/AVX-VNNI/AVX-512)
- El resto de la lista de optimizaciones puede verse en el Github del proyecto
■ Estabilidad en tiempo real
- No se dio por terminado con un solo benchmark de 37 segundos; se verificó ejecutándolo durante 30 minutos continuos con el ciclo real de callback de audio
- El M2 se mantuvo dentro del presupuesto por frame durante los 30 minutos completos (p99 0.56)
■ Otros
- 0 dependencias externas. Se compila con cmake + make y la biblioteca estática pesa 162 KiB
- La API pública tiene 4 funciones (
fe_init/fe_run/fe_reset/fe_free) - Blob de pesos de 565 KB, 511,754 parámetros
- Licencia MIT
Aún no hay comentarios.