Audio Fader and Volume Meter Implementation with obs_fader_t and obs_volmeter_t in OBS Studio

OBS Studio implements audio level control and monitoring through thread-safe primitives obs_fader_t and obs_volmeter_t, which map UI deflection to decibel values and sample real-time audio levels through callback APIs.

The obsproject/obs-studio repository provides a robust audio control system that powers the mixer interface in OBS Studio. Understanding the audio fader and volume meter implementation with obs_fader_t and obs_volmeter_t is essential for developers building plugins, custom UI components, or integrating external control surfaces.

Core Audio Control Primitives

obs_fader_t: Mapping UI Deflection to Decibels

The obs_fader_t structure abstracts the mathematical relationship between a GUI slider position (deflection ∈ [0, 1]) and the actual audio gain applied to a source. According to the source code in libobs/obs-audio-controls.c, the fader supports three distinct mapping curves:

  • OBS_FADER_CUBIC: Uses cubic_def_to_db() and cubic_db_to_def() (lines 81‑99) to provide a smooth cubic curve suitable for general volume control.
  • OBS_FADER_IEC: Implements the piecewise mapping defined in IEC 60668‑18 (lines 50‑62), which mimics professional audio hardware behavior.
  • OBS_FADER_LOG: Applies a custom exponential curve (lines 66‑84) for logarithmic gain scaling.

obs_volmeter_t: Real-Time Audio Level Monitoring

The obs_volmeter_t primitive samples raw audio data from an attached source and computes normalized magnitude values (0 → 1) for UI display. As implemented in libobs/obs-audio-controls.c, the meter supports two operational modes:

  • SAMPLE_PEAK_METER: Standard peak detection per audio channel.
  • TRUE_PEAK_METER: Oversampled true-peak detection for compliance with loudness standards.

The structure maintains per-channel arrays for magnitude and peak values, protected by internal mutexes to ensure thread-safe access from the audio thread.

Creating and Configuring Faders and Meters

Both primitives are instantiated through the public API defined in libobs/obs-audio-controls.h. The creation functions allocate the structure, initialize mutexes, and store the selected mapping type:

// Create a logarithmic fader (typical for UI sliders)
obs_fader_t *fader = obs_fader_create(OBS_FADER_LOG);
if (!fader) return;

// Create a volume meter using the same mapping type
obs_volmeter_t *meter = obs_volmeter_create(OBS_FADER_LOG);
if (!meter) return;

Selecting the Fader Curve Type

The choice of curve affects the perceived responsiveness of the control:

  • OBS_FADER_CUBIC: Best for coarse adjustments; provides more resolution at lower volumes.
  • OBS_FADER_IEC: Required when emulating physical mixing consoles; follows the standard deflection-to-dB table.
  • OBS_FADER_LOG: Ideal for precise gain staging; maintains consistent relative changes across the range.

Attaching to Audio Sources

Linking obs_fader_t to obs_source_t

To synchronize the fader with an audio source, use obs_fader_attach_source(). This function registers the fader for the source’s "volume" signal, ensuring that UI sliders stay in sync when the source volume changes programmatically:

obs_source_t *source = obs_get_source_by_name("Desktop Audio");
obs_fader_attach_source(fader, source);
obs_source_release(source);

// Set the fader to -12 dB
obs_fader_set_db(fader, -12.0f);

// Retrieve current deflection (0-1 range) for UI positioning
float def = obs_fader_get_deflection(fader);
printf("Deflection = %.3f\n", def);

The counterpart obs_fader_detach_source() removes these connections when the UI component is destroyed.

Connecting obs_volmeter_t for Level Sampling

Similarly, obs_volmeter_attach_source() registers an audio capture callback (volmeter_source_data_received) that receives raw audio frames. The meter then updates per-channel magnitude and optionally computes true-peak values:

obs_volmeter_attach_source(meter, source);

// Register a callback to receive level updates
void meter_updated(void *param,
                   const float magnitude[MAX_AUDIO_CHANNELS],
                   const float peak[MAX_AUDIO_CHANNELS])
{
    // Print left/right levels (assuming stereo)
    printf("L: %.2f  R: %.2f\n", magnitude[0], magnitude[1]);
}
obs_volmeter_add_callback(meter, meter_updated, nullptr);

Callback Architecture and Thread Safety

Both obs_fader_t and obs_volmeter_t implement a thread-safe callback system using dynamic arrays (DARRAY) protected by dedicated mutexes (callback_mutex). This design allows UI widgets to react to audio changes without polling:

  • Adding callbacks: obs_fader_add_callback() (lines 706‑717) and obs_volmeter_add_callback() append function pointers to the array.
  • Removing callbacks: obs_fader_remove_callback() (lines 722‑733) safely removes entries without disrupting active signal emissions.
  • Signaling: When state changes (e.g., obs_fader_set_db at lines 578‑595), the implementation iterates the callback array while holding the mutex, invoking each registered function with the new decibel value.

The internal state (current dB, deflection, magnitude arrays) is protected by separate mutexes, ensuring safe concurrent access from the audio thread, UI thread, and API callers.

UI Integration in the OBS Frontend

The OBS Studio frontend composes these primitives into the mixer interface through Qt widgets defined in the frontend/components directory.

VolumeSlider and Fader Control

The VolumeSlider class (defined in frontend/components/VolumeSlider.hpp and implemented in frontend/components/VolumeSlider.cpp) encapsulates an obs_fader_t* (fad). It translates Qt slider integer values to fader deflection via obs_fader_set_deflection(), and registers callbacks to update its visual position when the underlying source volume changes externally.

The higher-level VolumeControl widget (frontend/components/VolumeControl.cpp) creates both a fader and meter for each source:

  • Instantiates obs_fader_create(OBS_FADER_LOG) for logarithmic volume control.
  • Instantiates obs_volmeter_create(OBS_FADER_LOG) for consistent level display.
  • Wires callbacks to update the mute button state, decibel label, and meter display.

VolumeMeter Display

The VolumeMeter widget (frontend/components/VolumeMeter.cpp) draws the bar-graph visualization. It receives per-channel magnitude arrays from the obs_volmeter_t callback (meter_updated), scales the values to pixel coordinates, and renders peak hold indicators according to the IEC standard colors (green, yellow, red).

Summary

  • obs_fader_t maps GUI slider deflection (0‑1) to decibel values using cubic, IEC, or logarithmic curves, providing a thread-safe volume control primitive.
  • obs_volmeter_t samples audio data from sources to provide real-time magnitude and true-peak levels per channel, enabling accurate UI metering.
  • Both structures use mutex-protected callback arrays (DARRAY) to notify UI widgets of state changes without polling.
  • The implementation in libobs/obs-audio-controls.c cleanly separates audio mathematics from state management, while the frontend components in frontend/components/VolumeSlider.cpp and VolumeMeter.cpp compose these primitives into the mixer interface.

Frequently Asked Questions

What is the difference between obs_fader_t and obs_volmeter_t?

obs_fader_t is a control primitive that converts UI slider positions into decibel values and linear multipliers to set source volume, while obs_volmeter_t is a metering primitive that analyzes incoming audio buffers to calculate per-channel magnitude and peak levels for display. The fader affects audio gain; the meter observes it.

Which fader curve type should I use for a volume slider?

For most UI volume sliders, OBS_FADER_LOG (logarithmic) provides the most natural perceptual response, matching how human hearing perceives loudness. If emulating professional hardware mixers, use OBS_FADER_IEC to follow the IEC 60668‑18 standard deflection curve. OBS_FADER_CUBIC offers more resolution at low volumes for fine gain staging.

How do I receive real-time audio level updates in my plugin?

Create an obs_volmeter_t using obs_volmeter_create(), attach it to your target source with obs_volmeter_attach_source(), and register a callback using obs_volmeter_add_callback(). Your callback function will receive const float magnitude[MAX_AUDIO_CHANNELS] and const float peak[MAX_AUDIO_CHANNELS] arrays whenever new audio data is processed.

Are obs_fader_t and obs_volmeter_t thread-safe?

Yes, both primitives are fully thread-safe. The implementation in libobs/obs-audio-controls.c protects internal state with mutexes (mutex for value state and callback_mutex for the callback DARRAY). This allows safe concurrent access from the audio thread, UI thread, and API callers without external synchronization.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →