# Desktop ↔ Web Comparison: e2e-05_dj_dave_full

- **Timestamp:** 2026-06-18T14:11:38.494Z
- **Capture window:** 20000 ms

## Code
```ruby
use_bpm 130
live_loop :met1 do
 sleep 1
end
cmaster1 = 130
cmaster2 = 130
define :pattern do |pattern|
 return pattern.ring.tick == "x"
end
live_loop :kick, sync: :met1 do
 a = 1.5
 sample :bd_tek, amp: a, cutoff: cmaster1 if pattern "x--x--x---x--x--"
 sleep 0.25
end
with_fx :echo, mix: 0.2 do
 with_fx :reverb, mix: 0.2, room: 0.5 do
 live_loop :clap, sync: :met1 do
 a = 0.75
 sleep 1
 sample :drum_snare_hard, rate: 2.5, cutoff: cmaster1, amp: a
 sample :drum_snare_hard, rate: 2.2, start: 0.02, cutoff: cmaster1, pan: 0.2, amp: a
 sample :drum_snare_hard, rate: 2, start: 0.04, cutoff: cmaster1, pan: -0.2, amp: a
 sleep 1
 end
 end
end
with_fx :reverb, mix: 0.2 do
 with_fx :panslicer, mix: 0.2 do
 live_loop :hhc1, sync: :met1 do
 a = 0.75
 p = [-0.3, 0.3].choose
 sample :drum_cymbal_closed, amp: a, rate: 2.5, finish: 0.5, pan: p, cutoff: cmaster2 if pattern "x-x-x-x-x-x-x-x-xxx-x-x-x-x-x-x-"
 sleep 0.125
 end
 end
end
live_loop :hhc2, sync: :met1 do
 a = 1.25
 sleep 0.5
 sample :drum_cymbal_closed, cutoff: cmaster2, rate: 1.2, start: 0.01, finish: 0.5, amp: a
 sleep 0.5
end
with_fx :reverb, mix: 0.7 do
 live_loop :crash, sync: :met1 do
 a = 0.1
 c = cmaster2-10
 r = 1.5
 f = 0.25
 crash = :drum_splash_soft
 sleep 14.5
 sample crash, amp: a, cutoff: c, rate: r, finish: f
 sample crash, amp: a, cutoff: c, rate: r-0.2, finish: f
 sleep 1
 sample crash, amp: a, cutoff: c, rate: r, finish: f
 sample crash, amp: a, cutoff: c, rate: r-0.2, finish: f
 sleep 0.5
 end
end
with_fx :reverb, mix: 0.7 do
 live_loop :arp, sync: :met1 do
 with_fx :echo, phase: 1, mix: (line 0.1, 1, steps: 128).mirror.tick do
 a = 0.6
 r = 0.25
 c = 130
 p = (line -0.7, 0.7, steps: 64).mirror.tick
 at = 0.01
 use_synth :beep
 tick
 notes = (scale :g4, :major_pentatonic).shuffle
 play notes.look, amp: a, release: r, cutoff: c, pan: p, attack: at
 sleep 0.75
 end
 end
end
with_fx :panslicer, mix: 0.4 do
 with_fx :reverb, mix: 0.75 do
 live_loop :synthbass, sync: :met1 do
 s = 4
 r = 2
 c = 60
 a = 0.75
 at = 0
 use_synth :tech_saws
 play :g3, sustain: 6, cutoff: c, amp: a, attack: at
 sleep 6
 play :d3, sustain: 2, cutoff: c, amp: a, attack: at
 sleep 2
 play :e3, sustain: 8, cutoff: c, amp: a, attack: at
 sleep 8
 end
 end
end
```

## Stats (Level 3 — observation, not inference)

| Metric | Desktop SP | SonicPi.js (web) | Δ (desk − web) |
|---------------|------------------------|-------------------------|----------------|
| Duration (s) | 21.371 | 19.712 | 1.659 |
| Peak | 0.7685 | 0.4729 | 0.2956 |
| RMS | 0.1214 | 0.0779 | 0.0435 |
| Clipping (%) | 0.00 | 0.00 | 0.00 |
| Sample rate (Hz) | 48000 | 48000 | 0 |
| Channels | 2 | 2 | — |

## Verdict
### ✅ EVENT-MATCH — per-synthdef `/s_new` onset-sequence + note parity STRUCTURE-MATCHES desktop : the engine emitted the right notes at the right times. The audio Tier-1 said _"PITCH DIVERGENCE at note 0 (desktop 43 vs web 40)"_, but that measures stage-7+ scsynth DSP (WASM-vs-native rendering / pitch-tracker noise), not the engine. Authoritative cross-engine check passes. · ⚠ Tier-0 SOFT: level/count aggregates unreliable (Tier 1 pitch unaffected)

### Tier 0 — Validity gates
- ✓ 0.1 Sample rate consistent (48000 Hz)
- ⚠ 0.2 Capture-window misaligned (Δ 1.66s > 0.5s) — note-count / level aggregates unreliable **(SOFT — Tier 3 + 1.3 unreliable; Tier 1 pitch still valid)**
- ◦ 0.3 equal preconditions / 0.4 lossless capture / 0.5 routing sanity — not auto-checked; ensure SP.app reset + raw-float32 + FX-bus wired 

### Tier 1 — Musical correctness (THE verdict — energy/MFCC may never override)
- **1.1 Note progression:** ✗ PITCH DIVERGENCE at note 0 (desktop 43 vs web 40)
 - method: desktop `onset` (conf 1) · web `onset` (conf 1)
 - desktop: `43,43,40,40,40,40,59,67,69,40,40,41,43,43,40`
 - web&nbsp;&nbsp;&nbsp;: `40,68,40,43,43,40,43,40,76,76,40,69,40,40,68,41,40,40,40,79,69,71,40,40`
- **1.2 Tempo (inter-onset):** ✗ desktop 0.930s · web 0.400s/note
- **1.3 Onset count:** desktop 15 · web 33 (Δ explained by Tier-0 window misalignment)
- ◦ 1.4 note duration / 1.5 polyphony / 1.6 determinism — not auto-tracked here (unit tests cover determinism; see /)

### Tier 1.0 — Event parity (`/s_new` onset-sequence vs desktop — authoritative tiebreaker)
- **Structure (synthdef multiset):** STRUCTURE-MATCH — desktop 438 voice `/s_new`, web 428
- **Onset sequence (ε=15ms, prefix-compared, + per-tick NOTE multiset):** ✓ MATCH
 - ✓ `mono_player` — 283 onsets within ε (max Δ 1ms), notes match
 - ✓ `beep` — 59 onsets within ε (max Δ 1ms), notes match
 - ✓ `basic_stereo_player` — 55 onsets within ε (max Δ 1ms), notes match
 - ✓ `basic_mono_player` — 22 onsets within ε (max Δ 1ms), notes match
- ✅ **EVENT-MATCH:** structure + onset sequences both match — the engine's deterministic output (stages 1-6, terminating at the OSC emission) is correct. The audio Tier-1 divergence is stage-7+ scsynth rendering or tracker noise, not an engine bug (; #453/#379/#378 class).

### Tier 3 — Level / gain (reported; NOT a musical-correctness blocker — known ~0.5× web gain-staging)
> ⚠ Tier-0 SOFT failed — these ratios span misaligned windows; treat as indicative only.
- 3.1 RMS ratio web/desktop = 0.64× (within 0.5–2× band)
- 3.2 Peak ratio web/desktop = 0.62×
- 3.3 Clipping: desktop 0% · web 0% ✓ (< 1%)

### Tier 2 — Spectral / timbral (supporting only) · Tier 4 — FX/routing · Tier 5 — lifecycle
- Tier 2: see **Spectrogram comparison** section below (MFCC carries its mandatory caveat there).
- Tier 4 (FX accumulation/suppression 200ms scan, per-FX-scope energy): **not analysed** by this tool — use the FX-sweep / boundary-scan tools when FX is in scope.
- Tier 5 (Run/Stop/hot-swap, cold-start, long-run drift): **not analysed** — single capture; use `tools/test-run-stop-cycle.ts` for lifecycle.

## Source WAVs
- **Desktop:** /Users/mrityunjaybhardwaj/Documents/projects/sonicPiWeb/.captures/desktop-recordings/desktop_2026-06-18T14-10-44-177Z_e2e-05_dj_dave_full.wav
- **Web:** /Users/mrityunjaybhardwaj/Documents/projects/sonicPiWeb/.captures/2026-06-18T14-10-45-446Z_inline_audio.wav

## Spectrogram comparison
![spectrogram comparison](/Users/mrityunjaybhardwaj/Documents/projects/sonicPiWeb/.captures/compare_2026-06-18T14-11-11-258Z_e2e-05_dj_dave_full_spectrogram.png)

| Metric | Value | Reading |
|---|---|---|
| L2 distance (mel-dB) | 16.76 | < 10 = very close · 10–25 = similar shape · > 25 = divergent |
| MFCC distance (timbre) | 159.56 | < 30 = similar · 30–80 = noticeably different · > 80 = unrelated |
| ↳ MFCC caveat | — | **Tier-2 supporting only.** Confounded by the known ~0.5× web gain ratio + desktop reverb-tail length; **never overrides Tier 1** . A high MFCC with a Tier-1 PITCH-MATCH means timbre/gain, not wrong notes. |
| Frames compared | 1849 | overlapping window after length-aligning |
| Peak freq desktop | 66.6 Hz | dominant frequency |
| Peak freq web | 63.4 Hz | dominant frequency |
⚠ MFCC distance 159.56 is high — **check Tier 1 first**: if pitch-track matched, this is timbre/gain (the known 0.5× + reverb tail), NOT wrong notes. Only treat as "different synth/sample chain" when Tier 1 also diverges.

## Tool stdout (debug)
### Desktop
```
▶ Desktop capture (20000ms): e2e-05_dj_dave_full
✓ Report: /Users/mrityunjaybhardwaj/Documents/projects/sonicPiWeb/.captures/desktop_2026-06-18T14-10-44-177Z_e2e-05_dj_dave_full.md
✓ WAV: /Users/mrityunjaybhardwaj/Documents/projects/sonicPiWeb/.captures/desktop-recordings/desktop_2026-06-18T14-10-44-177Z_e2e-05_dj_dave_full.wav
 21.37s · peak 0.7685 · RMS 0.1214 · clip 0%
```
### Web
```
Launching Chromium (headed, audio capture)...
 Running: inline (20000ms)...

Capture saved: /Users/mrityunjaybhardwaj/Documents/projects/sonicPiWeb/.captures/inline.md
No errors detected.
```