RGB Sunglasses Animation Extension API fw-v3.8.1-1-geacf2f0
rgbx ABI + C++ wrapper for sandboxed .llext animations
Loading...
Searching...
No Matches
rgbx_audio_bars.h File Reference

SPDX-License-Identifier: MIT Copyright (c) 2026 Stuart Alldritt. More...

#include <math.h>
#include <rgbx/rgbx_api.h>
#include <stddef.h>

Go to the source code of this file.

Macros

#define RGBX_AUDIO_BAR_FLOOR_DB   (-36.0f)
 Default floor: bucket power (dB) at which a bar starts to light.
 
#define RGBX_AUDIO_BAR_RANGE_DB   (36.0f)
 Default range: dB from an empty bar to a full one (3 dB per row on the 12-row proto0 panel).
 
#define RGBX_AUDIO_BAR_TILT_DB_PER_OCTAVE   (3.0f)
 Default treble lift: dB added per octave above bucket 0 (pink-noise slope).
 
#define RGBX_AUDIO_BAR_POWER_FLOOR   (1e-9f)
 Power below this reads as -90 dB, so a silent bucket stays finite.
 

Functions

static float rgbx_audio_bar_power_db (float energy)
 Bucket power to dB, floored at RGBX_AUDIO_BAR_POWER_FLOOR.
 
static float rgbx_audio_bar_height (float energy, size_t bucket, float floor_db, float range_db, float tilt_db_per_octave)
 Bar-height fraction for one bucket under a dB window.
 

Variables

static const float rgbx_audio_bar_octaves [RGBX_AUDIO_NUM_DISPLAY_BUCKETS]
 log2(centre_b / centre_0) for each display bucket.
 

Detailed Description

SPDX-License-Identifier: MIT Copyright (c) 2026 Stuart Alldritt.

Turn rgbx_inputs.audio_display_bucket[] into bar heights the same way the built-in FFT Bars animation does — a dB meter, not a linear clamp.

The 20 display buckets are raw power: the mean |X_k|^2 over each bucket's FFT bins from an unscaled 512-point Hann FFT of the ±1-normalised PCM (see audio_display_bucket in rgbx_api.h). They are NOT normalised to 0..1. On real audio the bass bucket sits near 0.04–1.0 while the treble buckets sit near 1e-5 — a ~60 dB tilt, on top of ~30 dB of dynamics within a bucket. Drawing bucket * 255 therefore pins the bass bar and never lights anything above 600 Hz; that was the firmware's own bug until 2026-09.

This header is the fix, header-only and import-free apart from logf (which is on the SDK allow-list, see rgbx_sys.h):

dB = 10 * log10(max(E, 1e-9)) height = clamp((dB + tilt * octaves[bucket] - floor_db) / range_db, 0, 1)

with the defaults below: a 36 dB window whose ceiling is 0 dB (E = 1.0 — the level at which the device's automatic gain is about to turn the microphone down, so "full bar" keeps its VU meaning), and a 3 dB/octave treble lift so the mid and high buckets get usable height.

Usage (C or C++):

#include <rgbx/rgbx_audio_bars.h>

for (size_t b = 0; b < RGBX_AUDIO_NUM_DISPLAY_BUCKETS; b++) {
    float h = rgbx_audio_bar_height(rgbx_inputs.audio_display_bucket[b], b,
                                    RGBX_AUDIO_BAR_FLOOR_DB,
                                    RGBX_AUDIO_BAR_RANGE_DB,
                                    RGBX_AUDIO_BAR_TILT_DB_PER_OCTAVE);
    // h is 0..1: draw h * rows of the bar
}

Smooth h yourself if you want the built-in look (it runs an exponential moving average on the HEIGHT, weight 0.3, three steps per analysis frame).

Macro Definition Documentation

◆ RGBX_AUDIO_BAR_RANGE_DB

#define RGBX_AUDIO_BAR_RANGE_DB   (36.0f)

Default range: dB from an empty bar to a full one (3 dB per row on the 12-row proto0 panel).

floor + range = 0 dB = E 1.0.

◆ RGBX_AUDIO_BAR_TILT_DB_PER_OCTAVE

#define RGBX_AUDIO_BAR_TILT_DB_PER_OCTAVE   (3.0f)

Default treble lift: dB added per octave above bucket 0 (pink-noise slope).

Bucket 19 (2.9 kHz, 4.72 octaves up) gets +14 dB. 0 disables it.

Function Documentation

◆ rgbx_audio_bar_height()

static float rgbx_audio_bar_height ( float energy,
size_t bucket,
float floor_db,
float range_db,
float tilt_db_per_octave )
inlinestatic

Bar-height fraction for one bucket under a dB window.

Parameters
energyOne audio_display_bucket[] value (mean bin power).
bucketIts index, 0 .. RGBX_AUDIO_NUM_DISPLAY_BUCKETS-1 (an index past the table gets no tilt rather than reading off its end).
floor_dbPower (dB) at which the bar starts to light.
range_dbdB from empty to full; values <= 0 are treated as 1.
tilt_db_per_octaveTreble lift per octave above bucket 0.
Returns
Height in [0, 1]; exactly 0 for zero, negative or NaN energy.

◆ rgbx_audio_bar_power_db()

static float rgbx_audio_bar_power_db ( float energy)
inlinestatic

Bucket power to dB, floored at RGBX_AUDIO_BAR_POWER_FLOOR.

Parameters
energyOne audio_display_bucket[] value (mean bin power).
Returns
10*log10(energy), or -90 for zero, negative or NaN input.

Variable Documentation

◆ rgbx_audio_bar_octaves

const float rgbx_audio_bar_octaves[RGBX_AUDIO_NUM_DISPLAY_BUCKETS]
static
Initial value:
= {
0.0000f, 1.0995f, 1.5850f, 1.8931f, 2.1468f, 2.3626f, 2.6521f, 2.9206f, 3.1234f, 3.3424f,
3.5677f, 3.7318f, 3.8791f, 4.0000f, 4.0753f, 4.1584f, 4.2907f, 4.4500f, 4.5935f, 4.7240f}

log2(centre_b / centre_0) for each display bucket.

Bucket 0 (bins 2–5, 109 Hz) is the reference. The centre frequencies come from the firmware's bucket bin table (audio_display_bucket_start/end in the DSP); the firmware's own test recomputes this array from that table.