Skip to content

Commit 6fdbb28

Browse files
[EVR-001] - Foundation (#1)
Foundation of the EVR Mixer and stand alone mixer
1 parent f0e87c7 commit 6fdbb28

362 files changed

Lines changed: 15816 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENTS.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# AGENTS.md
2+
3+
## Project Overview
4+
5+
"Everything Is Remixed" (EVR) is a web-based interactive music album and stem mixer. Users can remix tracks by manipulating individual audio stems (drums, vocals, synths, etc.) directly in the browser using the Web Audio API. Released under CC0 1.0 (public domain).
6+
7+
## Architecture
8+
9+
- **Platform**: Cloudflare Workers
10+
- **Storage**: Cloudflare R2 (buckets named by element: `HYDROGEN`, `LITHIUM`, etc.)
11+
- **Frontend**: Modular ES6 JavaScript served via Workers Assets
12+
- **Audio Engine**: Web Audio API (client-side)
13+
14+
## File Structure
15+
16+
```
17+
src/
18+
├── standalone-mixer/
19+
│ └── index.html # Standalone mixer (drag-and-drop, no dependencies)
20+
└── workers/
21+
├── everything-is-remixed-worker.js # Worker entry point (~309 lines)
22+
├── stems.json # Stem metadata for all tracks
23+
├── {trackId}_peaks.json # Pre-generated waveform peaks
24+
└── app/ # Frontend/UI (served as assets)
25+
├── mixer-app.js # Client orchestrator (~565 lines)
26+
├── mix-style.css # Application styles
27+
└── modules/ # ES6 modules (13 total)
28+
├── mixer-constants.js # Config, defaults
29+
├── mixer-audio.js # AudioEngine class
30+
├── mixer-state.js # MixerState class
31+
├── mixer-transport.js # TransportController class
32+
├── mixer-ui.js # UIBuilder class
33+
├── mixer-fx.js # FXController class
34+
├── mixer-help.js # HelpController class
35+
├── mixer-loader.js # StemLoader class
36+
├── mixer-loop.js # AnimationManager class
37+
├── mixer-waveform.js # WaveformRenderer class
38+
├── mixer-templates.js # HTML generation functions
39+
├── mixer-visualizer.js # Holograph class (main thread)
40+
└── mixer-holographic-worker.js # 3D visualizer (Web Worker)
41+
```
42+
43+
## Standalone Mixer (standalone-mixer/index.html)
44+
45+
Self-contained stem mixer for user-provided audio files. No external dependencies, no share URL functionality (not applicable for local files).
46+
47+
**Features:**
48+
- Drag-and-drop audio files (M4A, MP3, MP4, WAV, FLAC, OGG)
49+
- Full FX chain with filter rolloff (-12/-24 dB/oct)
50+
- Holograph visualizer
51+
- Help system
52+
- Performance optimizations (visibility tracking, time slicing, dirty checks)
53+
54+
## Key Concepts
55+
56+
- **Tracks**: Named after alkali metals (Hydrogen, Lithium, Sodium, Potassium, Rubidium, Caesium, Francium)
57+
- **Stems**: Individual audio tracks that make up a song (9-38 per track)
58+
- **FX Chain**: EQ → Filter (-12/-24 dB/oct) → Delay → Panner → Gain → Master (+ Reverb Send)
59+
- **FX Modal**: Tabbed modal interface (EQ/FILTER tab with Slope dropdown, REVERB/DELAY tab)
60+
- **Progress Bar**: Display-only, no seeking (use skip buttons ±10s)
61+
- **Share URLs**: Mix state encoded in URL parameters for sharing
62+
- **Holograph**: 3D "City Landscape" visualizer using OffscreenCanvas + Web Worker
63+
- **Signal LED**: Per-channel LED that lights up when audio detected (>5% level)
64+
- **Sync**: Leader-based playback with rate nudging (desktop only, ~1Hz)
65+
- **Theme**: Light/dark mode via `data-theme` attribute, persisted in localStorage
66+
- **Listing**: Swiss Lab periodic table design (4-column grid, element symbols)
67+
68+
## Module Responsibilities
69+
70+
| Module | Class | Purpose |
71+
|--------|-------|---------|
72+
| `mixer-constants.js` | - | Configuration, defaults |
73+
| `mixer-audio.js` | `AudioEngine` | Web Audio API setup, effects chain, filter rolloff, master output |
74+
| `mixer-state.js` | `MixerState` | Stem volume, mute/solo, FX state, URL encoding |
75+
| `mixer-transport.js` | `TransportController` | Play, pause, seek, skip, sync, leader election |
76+
| `mixer-ui.js` | `UIBuilder` | Channel strips, faders, meters, visibility tracking |
77+
| `mixer-fx.js` | `FXController` | FX modal, tabbed UI, parameter control, rolloff |
78+
| `mixer-help.js` | `HelpController` | Help modal/bottom sheet, keyboard shortcuts |
79+
| `mixer-loader.js` | `StemLoader` | Batch loading, audio graph construction |
80+
| `mixer-loop.js` | `AnimationManager` | Throttled loop tasks, drift correction |
81+
| `mixer-waveform.js` | `WaveformRenderer` | Canvas waveform drawing & caching |
82+
| `mixer-templates.js` | - | Pure HTML string generation functions |
83+
| `mixer-visualizer.js` | `Holograph` | Main thread bridge to visualizer worker |
84+
| `mixer-holographic-worker.js` | - | 3D "City Landscape" rendering (Web Worker) |
85+
86+
## Development Guidelines
87+
88+
- **Worker**: Serves HTML shell, routes audio/asset requests, handles R2 proxying
89+
- **Client**: ES6 modules loaded via `type="module"` script tag
90+
- **Audio**: Processing done in browser (gain, EQ, filter, reverb, delay, pan)
91+
- **State**: Mix state shareable via URL parameters (`?mix=...&master=80`)
92+
- **Style**: Light/dark theme via `data-theme` attribute, track-specific accent colors (`--track-color`)
93+
94+
## Performance Considerations
95+
96+
- **Pre-allocate buffers**: Reuse `Float32Array` for meters/waveforms (avoid GC)
97+
- **Cache DOM refs**: Store meter/channel element references after building UI
98+
- **GPU animation**: Use `transform: scaleY()` not `height` for meters
99+
- **Throttle updates**: Progress bar at 10fps, meters at 30fps, holograph at 30fps
100+
- **Time slicing**: Update half the meters per frame (30fps → 15fps effective per channel)
101+
- **Dirty check**: Only update meter DOM if value changed by >1%
102+
- **Cache computations**: Pass `hasSolo` result to `isStemActive()` calls
103+
- **Visibility tracking**: Skip meter updates for off-screen channels (IntersectionObserver)
104+
- **Memory cleanup**: Release blob objects early, URLs on page unload
105+
- **Event delegation**: Single container listener instead of per-channel listeners
106+
- **Event cleanup**: Call `uiBuilder.dispose()` to remove global listeners
107+
- **Visualizer**: OffscreenCanvas + Web Worker, fake glow (2-pass), pre-allocated arrays
108+
109+
## Route Order (Critical)
110+
111+
1. Audio files: `/{trackId}/{filename}.m4a` (must be before assets)
112+
2. Peaks JSON: `/*_peaks.json` (must be before assets)
113+
3. Assets: `/assets/*` (JS, CSS, JSON, modules)
114+
4. App: `/` (home) or `/{trackId}` (mixer)
115+
116+
## Documentation
117+
118+
Detailed documentation in `docs/`:
119+
- `ARCHITECTURE.md` - Modular architecture, classes
120+
- `CLIENT_APP.md` - Audio, state, transport, UI
121+
- `SERVER_WORKER.md` - Routing, R2, caching
122+
- `GUIDES.md` - Adding tracks, FX, deployment
123+
- `MIXER_SYSTEM.md` - Effects, state encoding
124+
- `PERFORMANCE.md` - Animation loop, memory, rendering optimizations
125+
- `STEM_COLOR_PALETTES.md` - Color generation
126+
- `TRACK_COLORS.md` - Track primary colors
127+
- `PEAK_GENERATOR.md` - Waveform peaks tool
128+
129+
## Filter Rolloff
130+
131+
The filter supports two rolloff slopes selectable via the FX modal "Slope" dropdown:
132+
133+
| Rolloff | Implementation | Use Case |
134+
|---------|----------------|----------|
135+
| **-12 dB/oct** | Single BiquadFilterNode | Gentle slope, default |
136+
| **-24 dB/oct** | 2 cascaded BiquadFilterNodes | Steeper, more surgical |
137+
138+
Hot-swapping rolloff requires reconnecting the audio graph (disconnect old filter, create new, reconnect EQ → Filter → Delay).
139+
140+
## Persona
141+
142+
The project embodies the philosophy that "Everything is free" and "Music should circulate like electricity." Code should reflect high engineering standards while respecting the artistic intent of radical accessibility.

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# CLAUDE.md
2+
3+
See [AGENTS.md](AGENTS.md) for project documentation.

MANIFESTO.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# EVERYTHING IS REMIXED
2+
3+
## Stems as Invitation
4+
5+
When an artist releases stems, they're saying: this is not finished. This is starting material.
6+
7+
The "final" mix is just one arrangement. The stems contain infinite others. Releasing them is an invitation to find those arrangements.
8+
9+
## The Remix as Artifact
10+
11+
A fan remix is not a cover. It's not karaoke. It's not a lesser version of the original.
12+
13+
It's a new work made from shared material. It has its own intentions. Its own decisions. Its own validity.
14+
15+
The person who mutes the vocals and loops the bridge has created something. The person who solos the drums and studies the pattern has learned something. Both are legitimate uses.
16+
17+
## Copyright as Barrier
18+
19+
Traditional music release is one-directional. Artist to listener. Master recording to passive consumption.
20+
21+
Copyright enforces this direction. The listener cannot legally extract, modify, redistribute. The recording is final. The relationship is fixed.
22+
23+
This serves commerce. It does not serve culture.
24+
25+
## CC0 as Bridge
26+
27+
Public domain dedication removes the barrier. The listener becomes a collaborator. The relationship becomes bidirectional.
28+
29+
You can:
30+
- Download the stems
31+
- Remix them
32+
- Release your remix
33+
- Sell your remix
34+
- Never credit the original
35+
36+
All of this is permitted. All of this was intended.
37+
38+
## From Consumer to Collaborator
39+
40+
The mixer is not a playback device. It's a creative tool.
41+
42+
When you adjust a fader, you're not consuming—you're producing. When you share your mix URL, you're not sharing a link to the song—you're sharing your arrangement of the song.
43+
44+
The distinction matters. Consumers receive. Collaborators contribute.
45+
46+
## The Stems Will Outlast the Mix
47+
48+
The "official" mix is a snapshot. The stems are the source.
49+
50+
Future listeners with different tools, different tastes, different contexts will make different mixes. The stems enable this. The original mix does not.
51+
52+
Releasing stems is releasing the future versions of the song, not just the present one.
53+
54+
## Why This Approach
55+
56+
Stems expose the construction. They reveal the tricks. They make the magic legible.
57+
58+
It's dangerous for industries built on scarcity. It's unusual for cultures that equate ownership with value.
59+
60+
But the music was always made of parts. The stems just make that visible.
61+
62+
---
63+
64+
**Everything is Free** • CC0 1.0 Universal

0 commit comments

Comments
 (0)