Real-Time Room Correction in FFmpeg Using afir

This article explains how to apply real-time acoustic room correction to a live audio stream using FFmpeg's afir (Audio Finite Impulse Response) filter. By convolving an incoming live audio feed with a pre-measured Room Impulse Response (RIR) file, you can neutralize room resonances, flatten frequency response, and correct phase anomalies on the fly. You will learn the required prerequisites, the syntax for the afir filter graph, and a complete command configured for low-latency streaming.

Prerequisites

To perform real-time room correction, you need:

  1. A Room Impulse Response (RIR) file: A standard stereo or mono WAV file generated using acoustic measurement software such as Room EQ Wizard (REW). The sample rate of the IR file must match the sample rate of your audio stream to avoid processing artifacts or pitch shifts.
  2. FFmpeg: A modern build with libavfilter enabled.
  3. A low-latency audio subsystem: ALSA or PulseAudio/PipeWire on Linux, CoreAudio on macOS, or DirectShow/WASAPI on Windows.

How the afir Filter Works

The afir filter applies an impulse response to an audio signal via convolution. It requires two input streams:

  • Stream 0: The live audio stream that needs correction.
  • Stream 1: The correction impulse response file.

By default, the filter convolves corresponding channels (e.g., Left with Left IR, Right with Right IR).

Basic Command Structure

Below is an example using Linux's PulseAudio input and output devices. It reads audio from the default input monitor (or capture device), convolves it with room_ir.wav, and outputs the corrected stream to the default audio output:

ffmpeg -fflags nobuffer -flags low_delay \
  -f pulse -i default \
  -i room_ir.wav \
  -filter_complex "[0:a][1:a]afir=gtype=gn:irnorm=1[out]" \
  -map "[out]" \
  -f pulse default

Command Breakdown and Key Parameters

  • -fflags nobuffer and -flags low_delay: Reduces internal buffering in FFmpeg to keep real-time latency as low as possible.
  • -f pulse -i default: Captures the real-time audio stream from your system's default input or virtual sink monitor.
  • -i room_ir.wav: Loads the impulse response measurement.
  • -filter_complex "[0:a][1:a]afir=...[out]":
    • gtype=gn: Applies auto-gain normalization to prevent the convolved signal from clipping.
    • irnorm=1: Normalizes the IR gain based on its energy level.
    • dry=0:wet=1: Ensures 100% of the output is the corrected signal (default behavior).
  • -map "[out]": Routes the filtered audio output directly to the output device.
  • -f pulse default: Sends the corrected audio to your output device or DAC.

Platform-Specific Input/Output Adjustments

To adapt the command to different operating systems, change the input (-f ... -i ...) and output formats:

Windows (WASAPI / DirectShow)

ffmpeg -fflags nobuffer -flags low_delay ^
  -f dshow -i audio="Microphone (Realtek Audio)" ^
  -i room_ir.wav ^
  -filter_complex "[0:a][1:a]afir=gtype=gn:irnorm=1[out]" ^
  -map "[out]" ^
  -f wasapi default

macOS (AVFoundation / CoreAudio)

ffmpeg -fflags nobuffer -flags low_delay \
  -f avfoundation -i ":0" \
  -i room_ir.wav \
  -filter_complex "[0:a][1:a]afir=gtype=gn:irnorm=1[out]" \
  -map "[out]" \
  -f coreaudio default

Optimizing Latency and Performance

Real-time convolution is computationally heavy. To prevent buffer underruns, crackling, or high latency:

  1. Truncate the Impulse Response: Keep the length of room_ir.wav reasonably short (typically 100ms to 500ms). While longer IR files capture low-frequency room modes better, they introduce higher computational overhead.

  2. Match Sample Rates Explicitly: Force both the input stream and the filter to run at the exact sample rate of the IR file using the aresample filter or the -ar flag:

    ffmpeg -ar 48000 -f pulse -i default -i room_ir_48k.wav -filter_complex "[0:a]aresample=48000[a0];[a0][1:a]afir=gtype=gn[out]" -map "[out]" -f pulse default
  3. Partitioned Convolution: The afir filter handles partitioning automatically, but minimizing background processes will ensure uninterrupted audio processing.