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:

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.wav

Example: 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.wav

Note: 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.wav

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.wav

To 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.