Skip to content
gregormcwPublic

About

Real-time binaural spatializer VST3/AU plugin — C++, JUCE, MIT KEMAR HRTFs, 1,800+ embedded impulse responses

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ELEV8

A binaural spatializer audio plugin built with C++ and the JUCE framework. ELEV8 places any mono audio source in three-dimensional space around the listener by convolving the input signal with Head-Related Transfer Function (HRTF) impulse responses.

ELEV8 Plugin UI


Demo

ELEV8 Demo


Overview

Binaural audio simulates how humans perceive the direction and elevation of sound sources using the shape of the outer ear, head, and torso. HRTFs encode these acoustic filtering properties for a dense grid of spatial positions. ELEV8 loads the appropriate impulse response for a given azimuth and elevation, then applies it to the input in real time using frequency-domain convolution. This is the same core technique behind Apple Spatial Audio, Meta's VR audio pipeline, and binaural streaming formats — implemented here from first principles as a native audio plugin.

Formats: VST3, AU, Standalone Channel layout: Mono in → Stereo out Platform: macOS (Xcode build via JUCE Projucer)


Features

  • Real-time binaural spatialization using measured HRTFs
  • Independent azimuth (−180° to +180°) and elevation (−40° to +90°) controls
  • Over 1,800 embedded HRTF impulse responses covering 14 elevation planes
  • Nearest-neighbor HRTF selection with per-elevation azimuth resolution tables
  • Frequency-domain convolution via juce::dsp::Convolution

HRTF Dataset

The impulse responses are sourced from the MIT Media Lab KEMAR HRTF dataset (Gardner & Martin, 1994) — one of the most widely used public-domain HRTF databases in spatial audio research.

Measurements are taken at:

Elevation Azimuth samples Resolution
−20° to +20° 74 5°
±30° 62 6°
±40° 58 ~6.2°
50° 48 ~7.5°
60° 40 9°
70° 28 ~13°
80° 14 ~26°
90° 2 —

All impulse responses are embedded as binary resources at compile time, so the plugin has no runtime file dependencies.


How It Works

HRTF Selection

When a slider value changes, updateParameters():

  1. Finds the closest valid elevation in the 14-entry lookup table
  2. Selects the corresponding azimuth table for that elevation
  3. Finds the closest valid azimuth in that table
  4. Constructs the HRTF filename: H{elevation}e{azimuth}a.wav
  5. Locates the matching entry in BinaryData and flags the convolution object for reload

Audio Processing

On each processBlock call:

  1. If a new HRTF was selected, it is loaded into juce::dsp::Convolution
  2. A gain factor is applied to the mono input buffer
  3. The mono signal is copied to both output channels
  4. Stereo convolution is performed against the selected HRTF, producing the binaural output
Mono input
    │
    ├─ applyGain()
    │
    ├─ copyFrom(ch 1 ← ch 0)
    │
    └─ dsp::Convolution::process()  ←  HRTF impulse response
           │
    Stereo binaural output

Building

Prerequisites

  • macOS with Xcode installed
  • JUCE framework (version used during development: JUCE 6)
  • Projucer to regenerate the Xcode project if needed

Steps

  1. Clone the repository:

    git clone https://github.com/gregormcw/elev8.git
    cd elev8
  2. Open elev8.jucer in Projucer and click Save and Open in IDE, or open the existing Xcode project directly:

    open Builds/MacOSX/ELEV8.xcodeproj
  3. Select the desired build target (VST3, AU, or Standalone) and build with ⌘B.

  4. The compiled plugin will be placed in the standard macOS plugin directories:

    • AU: ~/Library/Audio/Plug-Ins/Components/
    • VST3: ~/Library/Audio/Plug-Ins/VST3/

Note: BinaryData.cpp and BinaryData.h are generated by Projucer from the HRTF WAV files in Source/compact/. If regenerating, ensure the compact directory is included as a resource in the Projucer project.


Project Structure

elev8/
├── elev8.jucer                   # JUCE Projucer project file
├── Source/
│   ├── PluginProcessor.h/cpp     # DSP logic, HRTF selection, convolution
│   ├── PluginEditor.h/cpp        # Plugin UI (sliders, layout, painting)
│   ├── BinaryData.h/cpp          # Auto-generated embedded HRTF resources
│   └── compact/                  # Source HRTF WAV files (MIT KEMAR dataset)
│       ├── elev-40/              # 58 impulse responses at −40° elevation
│       ├── elev0/                # 74 impulse responses at 0° elevation
│       └── ...                   # One directory per elevation plane
└── Builds/
    └── MacOSX/
        └── ELEV8.xcodeproj       # Xcode project (generated by Projucer)

Limitations & Roadmap

  • No HRTF interpolation — parameters snap to the nearest measured position rather than blending between adjacent HRTFs, which can produce audible artifacts when sweeping angles quickly. Planned fix: linear interpolation between the four nearest HRTF measurements.
  • Hardcoded gain — output gain is fixed at 10× and cannot be adjusted from the UI. Planned fix: expose a gain parameter via AudioProcessorValueTreeState.
  • No preset saving — getStateInformation / setStateInformation are not yet implemented, so DAW automation and preset recall are unsupported. Planned fix: serialize parameters using JUCE's ValueTree.
  • macOS only — no Windows or Linux builds are currently provided. Planned fix: CMake-based cross-platform build replacing the Projucer/Xcode workflow.

References

  • Gardner, W. G., & Martin, K. D. (1994). HRTF Measurements of a KEMAR Dummy-Head Microphone. MIT Media Lab Perceptual Computing Technical Report #280.
  • JUCE Framework — https://juce.com
  • Smith, J. O. (2010). Physical Audio Signal Processing. W3K Publishing. https://ccrma.stanford.edu/~jos/pasp/

Author

Gregor McWilliam — gregormcw.com · g@gregormcw.com

About

Real-time binaural spatializer VST3/AU plugin — C++, JUCE, MIT KEMAR HRTFs, 1,800+ embedded impulse responses

Topics

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages