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

> Learn how OBS Studio implements audio fader and volume meter functionality using obs_fader_t and obs_volmeter_t. Explore thread-safe primitives and callback APIs for precise audio control and monitoring.

- Repository: [OBS Project/obs-studio](https://github.com/obsproject/obs-studio)
- Tags: 
- Published: 2026-03-03

---

**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`](https://github.com/obsproject/obs-studio/blob/main/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`](https://github.com/obsproject/obs-studio/blob/main/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`](https://github.com/obsproject/obs-studio/blob/main/libobs/obs-audio-controls.h). The creation functions allocate the structure, initialize mutexes, and store the selected mapping type:

```cpp
// 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:

```cpp
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:

```cpp
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`](https://github.com/obsproject/obs-studio/blob/main/frontend/components/VolumeSlider.hpp) and implemented in [`frontend/components/VolumeSlider.cpp`](https://github.com/obsproject/obs-studio/blob/main/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`](https://github.com/obsproject/obs-studio/blob/main/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`](https://github.com/obsproject/obs-studio/blob/main/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`](https://github.com/obsproject/obs-studio/blob/main/libobs/obs-audio-controls.c) cleanly separates audio mathematics from state management, while the frontend components in [`frontend/components/VolumeSlider.cpp`](https://github.com/obsproject/obs-studio/blob/main/frontend/components/VolumeSlider.cpp) and [`VolumeMeter.cpp`](https://github.com/obsproject/obs-studio/blob/main/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`](https://github.com/obsproject/obs-studio/blob/main/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.