Decode Ambisonics in FFmpeg with Custom Channel Map
Decoding Higher-Order Ambisonics (HOA)—such as 2nd-order (9 channels)
and 3rd-order (16 channels) audio—requires precise channel routing and
matrix manipulation to ensure accurate spatial reproduction. This guide
demonstrates how to use FFmpeg’s powerful audio filters, specifically
pan and channelmap, to decode these
multi-channel streams and apply custom channel maps for virtual speaker
layouts or custom hardware configurations.
Understanding Ambisonic Orders and Channel Counts
Before writing the FFmpeg commands, you must identify the Ambisonics format (typically AmbiX, which uses ACN channel ordering and SN3D normalization) and the channel count:
- 2nd-Order Ambisonics: 9 channels (ACN index 0 to 8)
- 3rd-Order Ambisonics: 16 channels (ACN index 0 to 15)
In FFmpeg, these channels are indexed starting from c0
(the 1st channel, which is the W/Omni channel) up to c8
(for 2nd-order) or c15 (for 3rd-order).
Method 1:
Decoding to Speakers Using the pan Filter
The pan filter is the most effective tool in FFmpeg for
decoding Ambisonics because it allows you to define a custom decoding
matrix. You can specify exactly how much of each Ambisonic input channel
(\(c0, c1, c2...\)) feeds into each
output speaker channel.
Example: Decoding 2nd-Order (9 Channels) to 5.1 Surround
To decode a 2nd-order Ambisonics file into a standard 5.1 speaker layout, use a decoding matrix. Below is an example command using illustrative coefficients:
ffmpeg -i input_2nd_order.wav -af "pan=5.1|FL = 0.35*c0 + 0.35*c1 + 0.15*c3 + 0.15*c4|FR = 0.35*c0 - 0.35*c1 + 0.15*c3 - 0.15*c4|FC = 0.5*c0 + 0.3*c3|LFE = 0.1*c0|BL = 0.35*c0 + 0.35*c2 + 0.15*c8|BR = 0.35*c0 - 0.35*c2 - 0.15*c8" output_51.wavExample: Decoding 3rd-Order (16 Channels) to 7.1 Surround
For 3rd-order Ambisonics, you have access to all 16 channels
(c0 to c15). You can map these higher-order
components to a 7.1 layout to achieve sharper spatial localization:
ffmpeg -i input_3rd_order.wav -af "pan=7.1|FL = 0.3*c0 + 0.2*c1 + 0.1*c3 + 0.1*c9|FR = 0.3*c0 - 0.2*c1 + 0.1*c3 - 0.1*c9|FC = 0.4*c0 + 0.3*c3 + 0.2*c15|LFE = 0.1*c0|BL = 0.3*c0 + 0.2*c2 + 0.1*c8|BR = 0.3*c0 - 0.2*c2 - 0.1*c8|SL = 0.3*c0 + 0.2*c1 + 0.2*c2|SR = 0.3*c0 - 0.2*c1 - 0.2*c2" output_71.wavNote: You should replace the coefficient values (e.g.,
0.35, 0.15) in these examples with the
specific math derived from your target speaker positions and your chosen
decoding equations (e.g., basic sampling, max rE, or in-phase).
Method
2: Reordering Channels Using the channelmap Filter
If you already have a pre-decoded multi-channel stream or need to
rearrange/remap the raw Ambisonic channels (for example, converting from
FuMa channel order to ACN channel order), use the
channelmap filter.
Example: Custom Reordering of a 3rd-Order Stream
This command takes a 16-channel input and remaps the sequence of the
channels. The map syntax 0-2 means “route input channel
index 0 to output channel index 2”.
ffmpeg -i input_3rd_order.wav -filter_complex "channelmap=map=0-0|1-2|2-1|3-3|4-5|5-4|6-6|7-7|8-8|9-10|10-9|11-11|12-12|13-13|14-14|15-15:channel_layout=hexadecagonal" output_reordered.wavhexadecagonalis the FFmpeg layout name for a standard 16-channel stream.- For 2nd-order (9 channels), use the layout name
octagonal+LFEor a custom channel layout definition.
Method 3: Decoding 2nd/3rd-Order to Binaural via SOFA
For headphone playback, you can decode HOA streams directly to
binaural stereo using custom HRTF (Head-Related Transfer Function)
profiles in .sofa format. FFmpeg achieves this via the
sofalizer (or binauralhrft) filter.
To decode a 3rd-order, 16-channel Ambisonics file to binaural stereo:
ffmpeg -i input_3rd_order.wav -af "sofalizer=sofa=/path/to/your_hrtf.sofa:type=ambisonics:order=3" output_binaural.wavTo run this command with a 2nd-order file, simply change
order=3 to order=2. Ensure your
.sofa file supports the corresponding Ambisonic order for
accurate spatial virtualization.