Documentation Index
Fetch the complete documentation index at: https://mintlify.com/kepabilbao67-bot/musicplayer2/llms.txt
Use this file to discover all available pages before exploring further.
NEON DJ’s interface is organised as three vertical columns inside a single browser viewport: Deck A on the left, the Center Mixer in the middle, and Deck B on the right. Above all three columns runs a full-width spectrum analyzer canvas, and below them sits the FX pad bar. The header strip at the very top holds the logo, the AUTO MIX button, the RECORD button, and the master volume slider. Everything is wired together through a shared Web Audio API graph that keeps all signals in sync at the sample level.
Three-Column Console Layout
┌─────────────────────────────────────────────────────┐
│ NEON DJ logo AUTO MIX REC MASTER VOL │ ← header
├─────────────────────────────────────────────────────┤
│ SPECTRUM ANALYZER (full-width) │
├──────────────┬────────────────┬─────────────────────┤
│ │ VU-A CH-A CH-B VU-B │
│ DECK A │ ───── │ │ ───── DECK B │
│ │ CROSSFADER │
│ vinyl, EQ, │ vinyl, EQ, │
│ transport │ CENTER MIXER transport │
│ hot cues │ hot cues │
└──────────────┴────────────────┴─────────────────────┘
│ FX: RISER AIRHORN IMPACT ZAP FLANGER TAPE STOP ECHO │
└─────────────────────────────────────────────────────────────┘
The console uses a CSS grid with grid-template-columns: 1fr 240px 1fr. The center mixer column is fixed at 240 px; the two deck panels flex to fill the remaining space equally.
At viewport widths of 880 px or below, the three-column grid collapses to a single column (grid-template-columns: 1fr), stacking Deck A, the mixer, and Deck B vertically. All controls remain fully functional in the stacked layout.
Spectrum Analyzer
The spectrum analyzer <canvas id="spectrum"> sits between the header and the console. It is full-width up to 1 180 px and 46 px tall, with a dark background (#0a0d15) and a rounded border.
| Property | Value |
|---|
| Audio source | Master limiter output (finalNode()) |
| Analyser FFT size | 512 bins |
| Smoothing time constant | 0.8 |
| Bar count | 72 |
| Bar color | hsl(285 − (i/bars)*250, 90%, 42%+v*22%) — sweeps from purple through magenta to cyan |
Each animation frame (requestAnimationFrame) reads byte frequency data and draws 72 vertical bars. The bar height is proportional to the frequency magnitude; the hue shifts across the bar row to create the signature neon gradient. Only the lower 70 % of the FFT bins are displayed to avoid a flat high-frequency tail.
Channel Faders
The two channel faders (<input type="range" class="chfader">) live in the center mixer panel, one per deck. They are rendered as vertical sliders (range 0 – 100, default 100) using writing-mode: vertical-lr; direction: rtl.
- Deck A fader — colored magenta via
accent-color: var(--a)
- Deck B fader — colored cyan via
accent-color: var(--b)
Moving a channel fader sets channelGain.gain.value = faderValue / 100 for that deck. The channel fader sits before the crossfader in the signal chain, so it provides an independent per-deck volume trim on top of the crossfader mix.
VU Meters
A VU meter (<div class="vu">) sits on each side of the channel faders — vu-a to the left of the faders, vu-b to the right. Each meter is a column of 14 individual bar segments (<i> elements), 12 px wide and 7 px tall with 2 px gaps.
Segment colors by position (bottom to top):
| Segments | Color | CSS class |
|---|
| 1 – 9 (bottom) | Green (--good / #2fe6a0) | on1 |
| 10 – 11 | Amber (#ffcf3a) | on2 |
| 12 – 14 (top) | Red (#ff4d4d) | on3 |
Every animation frame reads the AnalyserNode byte-time-domain data for that deck, calculates the RMS level, scales it by 3, and lights segments from the bottom up proportionally. A segment that is not lit gets no class and shows the inactive dark color (#20283a).
Crossfader
The horizontal crossfader slider (<input type="range" class="cross">) spans the full panel width, range 0 – 100, default 50.
The crossfader uses an equal-power (constant-power) curve implemented directly in the applyMix() function:
const x = crossfader.value / 100; // normalised 0..1
deckA.crossGain.gain.value = Math.cos(x * 0.5 * Math.PI);
deckB.crossGain.gain.value = Math.cos((1 - x) * 0.5 * Math.PI);
This means both decks are at −3 dB when the crossfader is centered, ensuring perceived loudness stays constant as you sweep. Labels above the slider show A on the left and B on the right with CROSSFADER centered.
| Crossfader Value | Deck A Gain | Deck B Gain |
|---|
| 0 (hard left) | 1.00 (0 dB) | 0.00 (−∞ dB) |
| 25 | 0.924 (−0.7 dB) | 0.383 (−8.3 dB) |
| 50 (center) | 0.707 (−3 dB) | 0.707 (−3 dB) |
| 75 | 0.383 (−8.3 dB) | 0.924 (−0.7 dB) |
| 100 (hard right) | 0.00 (−∞ dB) | 1.00 (0 dB) |
Both channel faders and the crossfader call the same applyMix() function on every input event, so all three controls interact correctly in real time.
Master Volume
The master volume is a horizontal range slider (<input class="mvol">, range 0 – 100, default 85) in the right side of the header strip. It sets masterGain.gain.value = sliderValue / 100.
Downstream of masterGain sits a DynamicsCompressorNode acting as a hard limiter:
| Limiter Parameter | Value |
|---|
| Threshold | −3 dBFS |
| Knee | 0 dB (hard) |
| Ratio | 20:1 |
| Attack | 3 ms |
| Release | 250 ms |
The limiter protects against clipping when both decks, reverb tails, and FX pads are all playing simultaneously at high levels.
The REC button (<button id="recBtn" class="rec-btn">) is in the header strip.
| State | Appearance |
|---|
| Idle | Dark background (#2a1a22), pink text, label ● REC |
| Recording | Magenta background (var(--a)), white text, label ■ STOP, blinking animation at 1 s period |
How recording works:
- First click: a
ScriptProcessorNode (4 096-sample buffer, stereo) is connected downstream of the master limiter. PCM chunks are collected in two Float32Array arrays (recL, recR).
- Second click: collection stops. NEON DJ attempts to load
lamejs from a CDN to encode the PCM as a 128 kbps stereo MP3. If the CDN is unavailable, it falls back to a built-in PCM → 16-bit stereo WAV encoder.
- The resulting file is auto-downloaded with the filename
mi-mezcla-<timestamp>.mp3 (or .wav).
Recording captures the post-limiter stereo master output, which includes both decks, all EQ processing, echo, reverb, and any active FX pads at the moment they play.
The AUTO MIX button (<button id="autoBtn" class="rec-btn auto-btn">) in the header initiates automated cross-mixing between the two decks.
| State | Appearance |
|---|
| Off | Muted green border, dark background, label 🤖 AUTO MIX |
| On | Green background (--good), blinking animation at 1.2 s period |
When AUTO MIX is active, an autoCycle() function runs every 13 seconds. Each cycle:
- Determines which deck is currently foregrounded (crossfader < 50 → Deck A is foreground)
- Starts the background deck playing if it has a track loaded, and calls
sync() on it to match BPM and phase
- Smoothly sweeps the crossfader to the opposite side over 6 seconds using
requestAnimationFrame
Disabling AUTO MIX stops the timer but does not reset the crossfader.
Signal Flow Diagram
The full signal path from source to speakers:
DECK A DECK B
AudioBufferSource AudioBufferSource
→ EQ chain (low/mid/high) → EQ chain (low/mid/high)
→ filter (LP/HP morph) → filter (LP/HP morph)
→ channelGain ← ch-a fader → channelGain ← ch-b fader
├─ → delaySend → delay loop ├─ → delaySend → delay loop
├─ → reverbSend → convolver ├─ → reverbSend → convolver
└─ → analyser (VU-A) └─ → analyser (VU-B)
→ crossGain ←─────────────────── crossfader (equal-power) ──────────┘
↓
masterGain ← master volume slider
↓
masterLimiter (DynamicsCompressor, −3 dB / 20:1)
↙ ↓ ↘
masterFlangerWet masterEchoWet masterAnalyser
(flanger FX send) (echo FX send) (spectrum canvas)
↘ ↘
→ masterLimiter → AudioContext.destination
↓
ScriptProcessor
(REC capture)