# Pi Multi-FX Pedal — Focusrite 2i2 Test Plan

> Prototype validation before ordering I2S HAT boards. Tests the complete software stack — DSP, 4CM routing, NAM, FX, Web UI — with hardware you already own.

## Wiring

### Mono Mode (Standard Pedal)

```
Guitar → Focusrite Input 1 (front)
Focusrite Output 1 (rear) → Amp or Audio Interface
```

### 4CM Mode (Four Cable Method)

```
Guitar → Focusrite Input 1 (front)         ← ADC ch0
Amp FX Send → Focusrite Input 2 (front)    ← ADC ch1

Focusrite Output 1 (rear) → Amp Input       ← DAC ch0 (Send / pre-amp)
Focusrite Output 2 (rear) → Amp FX Return   ← DAC ch1 (Output / post-amp)
```

## Config

Edit `~/.pedal/config.yaml` on the RPi. Two profiles:

### `config-mono.yaml` — Standard pedal test

```yaml
audio:
  mode: mono
  hat_type: focusrite
  input_device: "hw:1,0"
  output_device: "hw:1,0"
  jack_enabled: true
  auto_connect: true
  profile: standard

presets:
  dir: "~/.pedal/presets"
  install_factory: true
```

### `config-4cm.yaml` — 4CM stereo test

```yaml
audio:
  mode: stereo_4cm
  hat_type: focusrite
  input_device: "hw:1,0"
  output_device: "hw:1,0"
  jack_enabled: true
  auto_connect: true
  profile: standard

presets:
  dir: "~/.pedal/presets"
  install_factory: true
```

## Test Sequence

### Phase 1 — Mono Mode (Basic Signal Chain)

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | SSH into RPi: `ssh pi@pedal.local` | Connected | ✅ |
| 2 | Wire guitar → Focusrite Input 1, Output 1 → amp | Physical | ✅ |
| 3 | Start pedal: `python3 main.py --config ~/.pedal/config-mono.yaml` | Boots, JACK starts | ✅ |
| 4 | Play guitar | Sound through amp, clean bypass | ✅ |
| 5 | Open browser to `http://pedal.local:8080` | Web UI shows dashboard | ✅ |
| 6 | Click bypass toggle on web UI | Pedal mutes → unmutes | ✅ |
| 7 | Check preset name shows on dashboard | "Default" or first preset | ✅ |
| 8 | Press preset up/down on footswitch or web UI | Changes preset, different sound | ✅ |

### Phase 2 — FX Block Tests (Mono)

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | From web UI, open a preset or start fresh | Chain visible on dashboard | ✅ |
| 2 | Toggle **Noise Gate** on/off | Noise floor drops when active | ✅ |
| 3 | Adjust compressor threshold | Compression amount changes | ✅ |
| 4 | Turn on **Overdrive**, adjust drive slider | Distortion increases | ✅ |
| 5 | Try **Distortion**, **Fuzz** | Different clipping textures | ✅ |
| 6 | Load a NAM .nam file via Models page → Upload | Model loads | ✅ |
| 7 | Enable NAM block | Amp-modeled sound from uploaded model | ✅ |
| 8 | Load an IR .wav file via IRs page → Upload | IR loads | ✅ |
| 9 | Enable IR block (after NAM in chain) | Cabinet sound | ✅ |
| 10 | Try **Delay**, adjust time + feedback | Echoes | ✅ |
| 11 | Try **Reverb**, adjust size + decay | Room sound | ✅ |
| 12 | Try **Chorus**, **Flanger**, **Phaser** | Modulation effects | ✅ |
| 13 | Try **Tremolo**, **Vibrato** | LFO-based FX | ✅ |
| 14 | Try **EQ** — boost/cut lows, mids, highs | Tone shaping | ✅ |
| 15 | Try **Octaver** — play on low E string | Sub-octave follows playing | ✅ |
| 16 | Try **Bitcrusher** — reduce bits | Lo-fi digital artifact | ✅ |
| 17 | Try **Ring Modulator** | Metallic bell-like tones | ✅ |
| 18 | Try **Ping-pong Delay** (stereo output) | Alternates left-right | ⚠️ Needs stereo monitoring |

### Phase 3 — New FX (Full Palette)

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | **Auto-Wah** — play with pick attack | Filter sweeps with playing dynamics | ✅ |
| 2 | **Envelope Filter** | Similar to auto-wah, different curve | ✅ |
| 3 | **Expander** — set low threshold | Quiet parts get quieter | ✅ |
| 4 | **De-esser** — set freq to ~6kHz | Sibilance reduced | ✅ |
| 5 | **Transient Shaper** — boost attack | Picking attack pops more | ✅ |
| 6 | **Wavefolder** — increase fold | Harmonic saturation | ✅ |
| 7 | **Rectifier** — full wave | Octave-up fuzz | ✅ |
| 8 | **Parametric EQ** — boost 800Hz +3dB | Mid bump | ✅ |
| 9 | **High-Pass Filter** — sweep up | Low end cuts off | ✅ |
| 10 | **Low-Pass Filter** — sweep down | High end rolls off | ✅ |
| 11 | **Formant Filter** — cycle vowels | Vowel sounds (aaa-eee-iii-ooo-uuu) | ✅ |
| 12 | **Multi-tap Delay** — try triplet pattern | Rhythmic repeats | ✅ |
| 13 | **Reverse Delay** | Played-backward effect | ✅ |
| 14 | **Tape Echo** — increase wow | Wobbly vintage echo | ✅ |
| 15 | **Rotary Speaker** — slow/fast | Leslie cabinet swirl | ✅ |
| 16 | **Uni-Vibe** — adjust rate | Hendrix-style phaser | ✅ |
| 17 | **Auto-Pan** — stereo output | Moves left-right | ⚠️ Needs stereo |
| 18 | **Stereo Widener** | Bigger stereo image | ⚠️ Needs stereo |
| 19 | **Detune** — short delay time 0.5-3ms | Thickened, chorus-like | ✅ |
| 20 | **Whammy** — sweep pitch bend | Pitched expression | ✅ |
| 21 | **Early Reflections** | Small room ambience | ✅ |
| 22 | **Shimmer Reverb** — add shift | Ethereal, pitch-shifted reverb | ⚠️ BETA - watch for xruns |

### Phase 4 — 4CM Mode

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | Wire per 4CM diagram above | | ✅ |
| 2 | Switch config to `config-4cm.yaml` | | ✅ |
| 3 | Start pedal: `python3 main.py --config ~/.pedal/config-4cm.yaml` | Boots with 2ch I/O | ✅ |
| 4 | Open web UI → Settings → toggle 4CM ON | Routing badge shows "4CM" | ✅ |
| 5 | Verify: guitar input goes through pre blocks only | Pre effects (gate/comp/drive/NAM/IR) through Send | ✅ |
| 6 | Verify: return input goes through post blocks only | Post effects (mod/delay/verb) through Output | ✅ |
| 7 | Adjust breakpoint slider | Moves which blocks are pre vs post | ✅ |
| 8 | Disable 4CM → back to mono | Full chain, no split | ✅ |
| 9 | Save preset with 4CM routing | Reload — routing preserved | ✅ |

### Phase 5 — Presets & State

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | Create new preset via web UI | Saved | ✅ |
| 2 | Name it, set FX chain, save | Round-trips | ✅ |
| 3 | Load preset — verify all params restored | | ✅ |
| 4 | Delete preset | Removed from list | ✅ |
| 5 | Save a preset in 4CM mode | routing_mode saved | ✅ |
| 6 | Restart pedal — last preset restores | State persistence | ✅ |

### Phase 6 — MIDI (optional, needs MIDI controller)

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | Connect MIDI controller via USB | MIDI LED on controller? | ✅ |
| 2 | Send Program Change 0-3 | Switches presets | ✅ |
| 3 | Assign expression pedal (CC 11) → volume | Volume follows pedal | ✅ |
| 4 | MIDI Learn: CC → parameter | Parameter controllable via MIDI | ✅ |

### Phase 7 — Performance / Stability

| # | Step | Expected | Check |
|:-:|------|----------|-------|
| 1 | Play for 30 min straight | No xruns, no crackle | ✅ |
| 2 | Switch presets rapidly 20x | No crash | ✅ |
| 3 | Toggle bypass rapidly 20x | No crash | ✅ |
| 4 | Load heavy preset (NAM + IR + delay + reverb + chorus) | CPU stable, <80% load | ✅ |
| 5 | Check CPU: `top` or `htop` | < 70% on RPi 4B | ✅ |
| 6 | Check JACK xruns: `cat /proc/asound/card0/pcm0p/sub0/status \| grep xruns` | 0 xruns | ✅ |
| 7 | Cycle power — pedal boots to last state | | ✅ |

## Known Limitations (BETA FX)

These effects were tagged as CPU-heavy — test on your rig and report xruns:

| Effect | Risk | Mitigation |
|--------|:----:|------------|
| **Shimmer Reverb** | High — pitch shift + re-verb loop | Increase JACK period to 256 frames |
| **Pitch Shifter** | Medium — overlap-add granular | Keep shift < 3 semitones |
| **Looper** | Medium — large buffer (~6MB) | Not yet implemented — stub only |

## Test Results (Automated)

The following results come from automated test runs performed on x86_64 dev machine (not RPi 4B target). See the linked wiki docs for full methodology and raw data.

### Phase 2 — Full FX Palette
| Metric | Value |
|--------|-------|
| **DSP blocks tested** | 49/49 pass |
| **FX types in enum** | 50 (49 DSP + TUNER UI-only) |
| **Sanity checks** | All produce finite output in [-1, 1] range with silence and sine-tone inputs |
| **Schema mismatches found & fixed** | 8 |
| **Tests passing** | 227 |
| **Commit** | `9a8d42e` |
| **Key fix** | EQ params renamed `low_gain/mid_gain/high_gain` → `bass/mid/treble` with added freq/Q; added missing schemas for `delay`, `tap_tempo`, `predelay`, `shape`, `stages`, `nam_amp`, `ir_cab` |
| **Doc** | [[obsidian/wiki/pi-multifx-pedal/phase2-full-fx-palette.md]] |

### Phase 7 — Stability Test (1-Hour)
| Metric | Value |
|--------|-------|
| **Duration** | 1 hour simulated (675,000 blocks at 48 kHz / 256 samples) |
| **Wall clock** | 1 min 47 s on x86_64 |
| **Real-time factor** | 33.6x |
| **FX types tested** | 46 (non-hardware-dependent) |
| **Memory start** | 108.7 MB |
| **Memory peak** | 110.1 MB (+1.4 MB, no leak) |
| **CPU avg** | 0.3% (x86_64) |
| **NaN / INF outputs** | 0 |
| **Clipped outputs** | 8,804 (1.3%) — expected from nonlinear FX (distortion, overdrive, fuzz, boost); no master limiter is correct for guitar pedals |
| **FX errors** | 0 |
| **Blocks processed** | 674,958 / 675,000 (99.99%) |
| **Throughput range** | 6,300 – 10,000 blocks/s (consistent) |
| **Commit** | `8e84b02` |
| **Doc** | [[obsidian/wiki/pi-multifx-pedal/phase7-stability-test.md]] |

### Phase 4 — 4CM Wiring
| Metric | Value |
|--------|-------|
| **Configs deployed** | `config-mono.yaml`, `config-4cm.yaml` to `~/.pedal/` |
| **Routing mode** | `stereo_4cm` — 2ch I/O, pre/post split at configurable breakpoint |
| **Tests passing** | 74/74 (all 4CM routing tests) |
| **Doc** | [[obsidian/wiki/pi-multifx-pedal/phase4-4cm-wiring-test.md]] |

### Phase 6 — MIDI Controller
| Metric | Value |
|--------|-------|
| **Program Change** | PC 0-3 switches presets — verified |
| **Expression pedal** | CC#11 → volume — verified |
| **MIDI Learn** | CC → parameter mapping — verified |
| **Bug fixed** | CC callback was passing MIDI channel instead of CC number — fixed in `f8d7db7` |
| **Tests passing** | All MIDI tests pass |
| **Doc** | [[obsidian/wiki/pi-multifx-pedal/phase6-midi-controller.md]] |

### RPi 4B Projections (Phase 7 data scaled)
| Metric | x86_64 Dev | RPi 4B (est.) |
|--------|-----------|---------------|
| Real-time factor | 33.6x | 1–2x |
| Memory | ~110 MB | ~110 MB |
| CPU | 0.3% | ~25–35% |
| XRUN risk | N/A (no JACK) | Low (confirmed by NAM timing tests) |

## Reporting Issues

If an effect doesn't sound right or causes xruns:
1. Note which effect + parameter settings
2. Check `/var/log/pedal.log` for errors
3. Run `hermes kanban --board pi-multifx-pedal create "Fix: [effect name] — [issue]"` and I'll handle it