shawn f3cdf5e13b
CI / test (push) Has been cancelled
fix: multiple issues preventing NAM from surviving rate/period changes
Root causes of 'changing bit rate / sample rate kills NAM':

1. Zombie jackd from stale second Python process — when stop_jack()
   kills jackd, the other process's auto-restart respawns jackd with
   OLD config between stop and start. start_jack() sees a running
   jackd and returns True immediately without verifying it's actually
   accepting connections.

2. Zombie Python process from incomplete service restart — two
   main.py instances running, each with its own AudioSystem and
   JackAudioClient. Profile change kills one JACK but the other
   respawns it. jack_client.start() then fails with server_error
   because the stale SHM conflicts.

3. start_jack() returned True for a dead jackd — process exists but
   JackServer::Open failed with -1 (bad period/rate for device).
   No SHM socket was created, but the process check passed.

Fixes:
- _ensure_singleton(): kill any other main.py process at boot
- start_jack(): verify jack_default_0_0 SHM socket exists before
  returning True; kill zombie process if socket is missing
- Profile handler: clean SHM right before jack_client.start()
- JackAudioClient.start(): retry once with SHM cleanup on
  server_error (0x21)
2026-06-18 17:21:04 -04:00

Pi Multi-FX Pedal 🎸

A real-time guitar multi-FX pedal running on Raspberry Pi 4B with 32 DSP effects, NAM A2 neural amp modeling, IR cab simulation, 4-Cable Method routing, and a web UI on pedal.local.

Quick Install (Focusrite 2i2 Test)

Get the pedal running on a fresh RPi with a Focusrite 2i2 in under 10 minutes.

1. OS Setup

Start with Raspberry Pi OS Lite (64-bit) or DietPi.

Configure hostname, enable SSH, and connect to WiFi:

sudo hostnamectl set-hostname pedal
# Or on DietPi: use dietpi-config

2. System Packages

sudo apt update && sudo apt upgrade -y
sudo apt install -y \
  git python3 python3-pip python3-venv python3-dev \
  jackd2 libjack-jackd2-dev \
  libsndfile1-dev \
  cmake build-essential \
  avahi-daemon          # for pedal.local mDNS

3. Clone the Repo

git clone https://gitea.ourpad.casa/shawn/pi-multifx-pedal.git ~/projects/pi-multifx-pedal
cd ~/projects/pi-multifx-pedal

4. Python Environment

python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt

Note: neural-amp-modeler needs PyTorch. On RPi 4B aarch64:

pip install torch --index-url https://download.pytorch.org/whl/nightly/cpu

5. Focusrite-Specific Config

Kill PulseAudio (it grabs USB audio):

pulseaudio --kill

Verify Focusrite is detected:

aplay -l
# Look for: card 1: USB Audio [Scarlett 2i2 USB], device 0
arecord -l
# Look for same

Copy the mono test config:

mkdir -p ~/.pedal
cp etc/config-focusrite-mono.yaml ~/.pedal/config.yaml

6. Run the Pedal

cd ~/projects/pi-multifx-pedal
source .venv/bin/activate
python3 main.py

7. Open the Web UI

From any device on the same network:

WiFi Hotspot (No Network? No Problem)

If there's no WiFi network to join — stage, rehearsal space, park bench — the Pi can create its own:

# Run once to set up
sudo bash scripts/setup-wifi-ap.sh

# Or with custom SSID/password:
sudo bash scripts/setup-wifi-ap.sh --ssid "Pi-Pedal" --psk "yourpassword"

# Phone connects to "Pi-Pedal" → open http://pedal.local

# To turn it off and go back to client mode:
sudo bash scripts/setup-wifi-ap.sh --disable

Pro tip: Add a USB WiFi dongle for dual-network — Pi creates hotspot on built-in WiFi, dongle handles internet access for git pulls and updates.

8. Wire It Up

Mono mode (standard pedal):

Guitar jack → Focusrite Input 1 (front)
Focusrite Output 1 (rear) → Amp

4CM mode (four cable method):

Guitar → Focusrite Input 1
Amp FX Send → Focusrite Input 2
Focusrite Output 1 → Amp Input (Send)
Focusrite Output 2 → Amp FX Return (Output)

Then switch config:

cp etc/config-focusrite-4cm.yaml ~/.pedal/config.yaml

Toggle 4CM on/off from the Settings page in the web UI.

Port & Privileges

The web UI runs on port 80 (standard HTTP), so URLs are clean — just http://pedal.local with no port number.

Binding to port 80 requires elevated privileges. Either:

  1. Run as root (simplest):

    sudo python3 main.py
    
  2. Grant the cap_net_bind_service capability (safer — no root shell):

    sudo setcap 'cap_net_bind_service=+ep' $(readlink -f $(which python3))
    python3 main.py   # no sudo needed
    
  3. Override the port via code change (development only): Change DEFAULT_PORT in src/web/server.py and port=80 in main.py.

For development, option 2 is recommended.

WiFi / Bluetooth Permissions

The WiFi hotspot and Bluetooth management features call sudo internally for system operations (hostapd, dnsmasq, iwlist, systemctl). If your user does not have passwordless sudo, these features will fail silently.

Add a sudoers entry to grant passwordless access for the pedal user (pi or your username):

sudo visudo -f /etc/sudoers.d/pi-pedal

Add one of the following, replacing pi with your actual username:

Minimal (only the WiFi setup script):

pi ALL=(ALL) NOPASSWD: /home/pi/projects/pi-multifx-pedal/scripts/setup-wifi-ap.sh *
pi ALL=(ALL) NOPASSWD: /usr/sbin/iwlist *
pi ALL=(ALL) NOPASSWD: /usr/sbin/iwconfig *
pi ALL=(ALL) NOPASSWD: /usr/bin/wpa_cli *
pi ALL=(ALL) NOPASSWD: /usr/bin/systemctl * hostapd
pi ALL=(ALL) NOPASSWD: /usr/bin/systemctl * dnsmasq
pi ALL=(ALL) NOPASSWD: /usr/bin/systemctl * pi-bt-midi

Permissive (full passwordless sudo — convenient on a dedicated device):

pi ALL=(ALL) NOPASSWD: ALL

The web UI surfaces permission errors with an "insufficient_permissions" key when sudo calls fail due to missing sudoers configuration.

Hardware

Component Spec
SBC Raspberry Pi 4B (2GB+ RAM)
Audio I/O I2S DAC + ADC (PCM1808 + PCM5102 custom HAT, or USB via Focusrite 2i2)
Footswitches 3-6 momentary soft-touch (e.g. MXR-style)
LEDs RGB WS2812B or APA102 per footswitch + status LEDs
Display 128x64 OLED SSD1306 (I2C) or 5" DSI touch
MIDI 5-pin DIN in/out via UART + optoisolator
Power 5V/3A USB-C (with buck for 3.3V rail)
Enclosure 1590BB or 3D-printed custom

32 Effects

Category Effects
Dynamics Noise Gate, Compressor, Expander, De-esser, Transient Shaper, Sidechain Compressor
Drive Boost, Overdrive, Distortion, Fuzz, Bitcrusher, Wavefolder, Rectifier
Amp + Cab NAM Amp Model (any .nam file), IR Cab Sim (any .wav)
Modulation Chorus, Flanger, Phaser, Tremolo, Vibrato, Ring Mod, Auto-Wah, Envelope Filter, Rotary Speaker, Uni-Vibe, Auto-Pan, Stereo Widener
Time Delay, Ping-pong Delay, Multi-tap Delay, Reverse Delay, Tape Echo, Reverb, Shimmer Reverb, Early Reflections, Looper
Pitch Octaver, Detune, Harmonizer, Whammy, Pitch Shifter
Filter EQ, Parametric EQ, High-Pass, Low-Pass, Band-Pass, Notch, Formant, Wah
Utility Volume, Tuner

Project Structure

├── src/
│   ├── dsp/              Audio processing pipeline
│   │   ├── pipeline.py   FX chain orchestration (mono + 4CM split)
│   │   ├── ir_loader.py  IR convolution engine
│   │   ├── nam_host.py   NAM model loading & inference
│   ├── midi/             MIDI subsystem
│   │   ├── handler.py    MIDI event parse & dispatch
│   ├── presets/          Preset system
│   │   ├── manager.py    Save/load/bank/preset CRUD + 4CM routing
│   │   └── types.py      Preset & chain data model + FXType enum
│   ├── ui/               Hardware UI layer
│   │   ├── footswitch.py Debounced GPIO input
│   │   ├── leds.py       RGB LED controller
│   │   └── display.py    OLED display manager
│   ├── web/              Web UI (FastAPI + WebSocket)
│   │   ├── server.py     REST + WebSocket endpoints
│   │   ├── templates/    Jinja2 HTML pages
│   │   └── static/       CSS + JS
│   └── system/           System integration
│       ├── audio.py      ALSA/JACK/I2S configuration
│       └── config.py     YAML config loader
├── etc/                  Config file templates
├── scripts/              Build & utility scripts
├── tests/                Tests
├── docs/                 Documentation + test plans
└── hardware/             KiCad/PCB schematics

Development

# Tests
source .venv/bin/activate
python -m pytest tests/ -v

# All 574 tests should pass

Early development — initial scaffold.

S
Description
RPi 4B guitar multi-FX pedal — NAM A2 amp modeling, IR cab sim, multi-FX chain, MIDI foot controller
Readme 9.3 MiB
Languages
Python 68.9%
JavaScript 9.3%
Shell 9.1%
HTML 5.7%
TypeScript 4.8%
Other 2.2%