A real-time binaural spatial audio engine written in C++ that makes mono audio sound like it's spinning around your head in 3D space. Built from scratch with minimal dependencies — only miniaudio for audio I/O.
Feed any audio file in and hear it orbit continuously around your head through standard stereo headphones. No special hardware required.
The pipeline encodes mono audio into First Order Ambisonics (FOA), rotates the sound field using a continuously advancing LFO, then decodes to binaural stereo via HRTF convolution:
mono audio
↓
SH Encoder — encodes to 4 FOA channels (W, X, Y, Z) using spherical harmonic basis functions
↓
Rotation — LFO advances azimuth each block, set_direction() updates encoding coefficients
↓
HRTF Decoder — decodes FOA to 8 virtual speaker signals via decode matrix,
convolves each with left/right HRTF using overlap-save FFT convolution
↓
binaural stereo (L / R) → headphones
Every component is implemented from scratch:
- FFT — Cooley-Tukey radix-2 with precomputed twiddle and bit-reversal tables
- Overlap-save convolution — block-by-block FFT convolution with history buffer for continuous output
- Spherical harmonic encoding — FOA basis functions evaluated at source direction
- Binaural decoding — virtual loudspeaker decode matrix + HRTF convolution
- HRTF dataset — SADIE II KU100 dummy head, 9201 directions at 48kHz
| Dependency | Version | Purpose |
|---|---|---|
| miniaudio | 0.11+ | Cross-platform audio I/O, file decoding |
That's it. No FFTW, no libspatializer, no game engine SDK.
Requirements
- CMake 3.20+
- C++17 compiler (clang++ or g++)
- Python 3 + numpy + scipy (one-time HRTF generation only)
Clone and build
git clone https://github.com/vidhu-vv/VASE
cd VASE
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel 4Generate the HRTF header (first time only)
Download the SADIE II dataset:
curl -L -o data/SADIE2.zip "https://zenodo.org/records/10886409/files/D2.zip?download=1"
unzip data/SADIE2.zip -d data/SADIE2Generate src/hrtf_data.h:
pip install numpy scipy
python tools/gen_hrtf_header.pyThen rebuild:
cmake --build build --parallel 4./build/VASE path/to/audio.mp3Supports any format miniaudio can decode — WAV, MP3, FLAC. Output is always stereo 48kHz through your default audio device. Use headphones for the spatial effect.
Press Enter to quit.
VASE/
├── CMakeLists.txt
├── deps/
│ └── miniaudio.h — single-header audio library
├── src/
│ ├── main.cpp — entry point, miniaudio device + callback
│ ├── ambi_engine.h / .cpp — pipeline coordinator
│ ├── fft.h / .cpp — Cooley-Tukey radix-2 FFT
│ ├── fft_convolver.h / .cpp — overlap-save FFT convolution
│ ├── sh_encoder.h / .cpp — spherical harmonic FOA encoder
│ ├── hrtf_decoder.h / .cpp — virtual loudspeaker binaural decoder
│ ├── hrtf_data.h — SADIE II HRTF table (auto-generated)
│ └── rotation.h / .cpp — LFO phase accumulator
├── data/
│ └── test.wav — example audio file
└── tools/
└── gen_hrtf_header.py — converts SADIE II WAVs → hrtf_data.h
Implements the Cooley-Tukey radix-2 decimation-in-time FFT. A single call to fft_precompute(N) at startup builds two lookup tables — twiddle factors (fft() and ifft() operate in-place on a Complex[] array of size N (must be a power of two).
Each Convolver instance holds the precomputed FFT of one HRTF impulse response (H[k]), a history buffer of M-1 samples, and a working buffer. Every process() call:
- Builds an extended block:
[history (M-1) | input (L) | zero pad]of length FFT_SIZE - FFTs the extended block →
X[k] - Pointwise multiplies
X[k] * H[k] - IFFTs back to time domain
- Discards the first M-1 contaminated samples, writes L valid samples to output
- Saves last M-1 input samples as history for the next block
With M=256 and L=512, FFT_SIZE=1024.
Encodes a mono source at direction (azimuth φ, elevation θ) into four FOA channels using the real-valued spherical harmonic basis functions:
W = 0.7071
X = cos(θ) · cos(φ)
Y = cos(θ) · sin(φ)
Z = sin(θ)
set_direction() precomputes these four coefficients. process() multiplies every input sample by them — four multiplications per sample.
Places 8 virtual speakers on a sphere (cube arrangement, ±35° elevation, 45°/135°/225°/315° azimuth). For each speaker a decode matrix row is computed from the same SH basis functions, normalised by N_FOA_CHANNELS / N_SPEAKERS. Each block:
- Matrix multiply: FOA channels → 8 mono speaker signals (dot product per sample)
- Convolve each speaker signal with its left and right HRTF via
Convolver - Sum all left outputs → L channel, all right outputs → R channel
16 Convolver instances run simultaneously — one per speaker per ear.
Generated from the SADIE II KU100 dataset (Neumann dummy head, 48kHz, 24-bit). gen_hrtf_header.py reads the WAV files, converts SADIE II's anti-clockwise azimuth convention to standard clockwise, truncates IRs to 256 samples, and writes a static C array hrtf_irs[9201][2][256]. find_closest_hrtf() does a linear search over the direction table to find the nearest measured direction to any requested azimuth/elevation.
A phase accumulator that advances by 2π · f_spin · L / f_s radians per block, wraps at 2π, and returns the current azimuth in degrees. At 0.5 Hz with block size 512 and sample rate 48kHz, the increment is 1.92°/block and one full orbit takes ~2 seconds.
This project uses the SADIE II Database (Subject D2, KU100 Neumann dummy head).
Amengual Garí, S. V., Kearney, G., Nando Ferrer, J., & McKenzie, T. (2024). SADIE II: A Binaural Database Including Measurements of Head-Related Transfer Functions and Headphone Impulse Responses. Zenodo. https://doi.org/10.5281/zenodo.10886409
Licensed under Apache 2.0.
- Cooley, J.W. & Tukey, J.W. (1965). An Algorithm for the Machine Calculation of Complex Fourier Series. Mathematics of Computation.
- Gardner, W.G. (1995). Efficient Convolution without Input-Output Delay. JAES 43(3).
- Zotter, F. & Frank, M. (2019). Ambisonics: A Practical 3D Audio Theory. Springer Open.
- Ivanic, J. & Ruedenberg, K. (1996). Rotation Matrices for Real Spherical Harmonics. Journal of Physical Chemistry A.
- Møller, H. (1992). Fundamentals of binaural technology. Applied Acoustics.
MIT