Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Module name: `dixwaveform` · target: **VLC 3.0.x**, macOS **arm64** (portable t
- Reads the live 32-bit-float PCM buffer, computes real-time analysis, renders a 1280x720 analyzer frame, and **passes the audio through untouched**.
- Shows engineering views: scrolling log spectrogram, FFT magnitude/peak-hold spectrum, stereo waveform/oscilloscope, and stereo phase + peak/RMS/crest/clip meters.
- Plus a **`compose` view** that *hears the music*: a live chromagram (12 pitch classes), circle-of-fifths **key detection**, a nearest-note + cents tuning readout, and an **energy/build-drop ribbon** — grounded in the Dix music library (pitch math from *Mathematics and Music*; groove/structure from *Unlocking the Groove*).
- **Switch views in-window** — a row of clickable tabs across the top (`DASH · KEYS · SPECTRO · SPECTRUM · WAVE · STEREO`) lets you jump between layouts with a mouse click, no VLC menus. (`KEYS` = the compose/key view.)
- **Switch views in-window** — a row of clickable tabs across the top (`DASH · KEYS (COMPOSE) · SPECTRO · SPECTRUM · WAVE · STEREO`) lets you jump between layouts with a mouse click, no VLC menus. (`KEYS (COMPOSE)` = the key/compose view.)
- Selectable via **Audio ▸ Visualizations ▸ Dix Analyzer**, or `--audio-visual=dixwaveform`.

## Install (macOS / Linux)
Expand Down Expand Up @@ -104,7 +104,7 @@ The **`lufs`** panel is a real ITU-R BS.1770-4 / EBU R128 loudness meter: moment

The music theory is grounded in the Dix library: pitch math (A440, `midi = 69 + 12·log2(f/440)`, cents) from *Mathematics and Music*; key/groove framing from *Unlocking the Groove* and the *Complete Idiot's Guide to Music Composition*. The DSP lives in `dix_pitch.h` and is unit-tested (see **Tests**).

**Access it:** click the **KEYS** tab at the top of the Dix window, launch with `--dix-layout=compose`, or set the layout in the plugin's advanced preferences.
**Access it:** click the **KEYS (COMPOSE)** tab at the top of the Dix window, launch with `--dix-layout=compose`, or set the layout in the plugin's advanced preferences.

## Tests & CI

Expand Down
30 changes: 22 additions & 8 deletions waveform.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "dix_pitch.h" /* pure pitch/chroma/key DSP (unit-tested standalone) */
#include "dix_lufs.h" /* ITU-R BS.1770 loudness (unit-tested standalone) */

#define DIX_VERSION "3.5.1"
#define DIX_VERSION "3.5.2"
#define DIX_W 1280
#define DIX_H 720
#define DIX_MAX_FFT 8192
Expand Down Expand Up @@ -1559,20 +1559,34 @@ static const int dix_tab_layout[] = {
DIX_LAYOUT_SPECTRUM, DIX_LAYOUT_WAVEFORM, DIX_LAYOUT_STEREO
};
static const char *const dix_tab_label[] = {
"DASH", "KEYS", "SPECTRO", "SPECTRUM", "WAVE", "STEREO"
"DASH", "KEYS (COMPOSE)", "SPECTRO", "SPECTRUM", "WAVE", "STEREO"
};
#define DIX_TAB_COUNT 6
#define DIX_TAB_Y 8
#define DIX_TAB_H 28
#define DIX_TAB_X0 60
#define DIX_TAB_X1 ( DIX_W - 308 ) /* tabs end here; the info block sits beyond */
#define DIX_TAB_GAP 6
#define DIX_TAB_PAD 15 /* px of padding on each side of a label */

/* Pixel width of a label at the tab text scale (2), matching draw_text()'s
* advance: 12 px per glyph, 8 px per space. */
static int dix_text_w2( const char *t )
{
int w = 0;
for( const char *p = t; *p; p++ ) w += ( *p == ' ' ) ? 8 : 12;
return w;
}

/* Tabs are sized to their labels (so "KEYS (COMPOSE)" isn't clipped) and laid
* out left to right. Both the renderer and the click hit-test call this, so
* drawing and hit-testing can never drift. */
static int dix_tab_w( int i ) { return dix_text_w2( dix_tab_label[i] ) + DIX_TAB_PAD * 2; }

static rect_t dix_tab_rect( int i )
{
int span = DIX_TAB_X1 - DIX_TAB_X0;
int tw = ( span - DIX_TAB_GAP * ( DIX_TAB_COUNT - 1 ) ) / DIX_TAB_COUNT;
rect_t r = { DIX_TAB_X0 + i * ( tw + DIX_TAB_GAP ), DIX_TAB_Y, tw, DIX_TAB_H };
int x = DIX_TAB_X0;
for( int k = 0; k < i; k++ ) x += dix_tab_w( k ) + DIX_TAB_GAP;
rect_t r = { x, DIX_TAB_Y, dix_tab_w( i ), DIX_TAB_H };
return r;
}

Expand All @@ -1584,8 +1598,8 @@ static void draw_tab_bar( filter_sys_t *s )
int active = ( s->dash_count == 0 && s->layout == dix_tab_layout[i] );
fill_rect( s, r, active ? rgb( 34, 88, 74 ) : rgb( 15, 19, 27 ) );
draw_rect( s, r, active ? rgb( 120, 226, 180 ) : rgb( 52, 62, 78 ) );
int lw = (int)strlen( dix_tab_label[i] ) * 12; /* scale-2 glyph = 12 px wide */
int tx = r.x + ( r.w - lw ) / 2; if( tx < r.x + 4 ) tx = r.x + 4;
int lw = dix_text_w2( dix_tab_label[i] );
int tx = r.x + ( r.w - lw ) / 2;
int ty = r.y + ( r.h - 14 ) / 2; /* scale-2 glyph = 14 px tall */
draw_text( s, tx, ty, dix_tab_label[i],
active ? rgb( 230, 255, 240 ) : rgb( 150, 166, 182 ), 2 );
Expand Down
Loading