#!/usr/bin/env python3 """Generate 48 factory presets (12 banks x 4 presets) for Pi Multi-FX Pedal. Replaces ALL existing factory presets in presets/factory/. """ import json import os import shutil FACTORY_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "presets", "factory") # ── Banks ────────────────────────────────────────────────────────────── BANKS = [ {"number": 0, "name": "Classic Rock"}, {"number": 1, "name": "Punk"}, {"number": 2, "name": "Metal"}, {"number": 3, "name": "Hardcore"}, {"number": 4, "name": "Emo"}, {"number": 5, "name": "Midwest Emo"}, {"number": 6, "name": "Djent"}, {"number": 7, "name": "Acoustic"}, {"number": 8, "name": "Grunge"}, {"number": 9, "name": "Alternative Rock"}, {"number": 10, "name": "Garage Rock"}, {"number": 11, "name": "Pop"}, ] # ── IR path shortcuts ───────────────────────────────────────────────── IR = { "vintage": "~/.pedal/irs/vintage-1x12.wav", "british": "~/.pedal/irs/british-4x12.wav", "american": "~/.pedal/irs/american-2x12.wav", "modern": "~/.pedal/irs/modern-4x12.wav", "jazz": "~/.pedal/irs/jazz-1x15.wav", "boutique": "~/.pedal/irs/boutique-1x12.wav", "mini": "~/.pedal/irs/mini-1x8.wav", } # ── Helper builders ──────────────────────────────────────────────────── def noise_gate(threshold=0.01): return {"fx_type": "noise_gate", "enabled": True, "bypass": False, "params": {"threshold": threshold}, "nam_model_path": "", "ir_file_path": ""} def compressor(threshold=0.3, ratio=4.0, gain=0.8): return {"fx_type": "compressor", "enabled": True, "bypass": False, "params": {"threshold": threshold, "ratio": ratio, "gain": gain}, "nam_model_path": "", "ir_file_path": ""} def boost(gain_db=6.0): return {"fx_type": "boost", "enabled": True, "bypass": False, "params": {"gain_db": gain_db}, "nam_model_path": "", "ir_file_path": ""} def overdrive(drive=0.5, gain=0.7, tone=0.5): return {"fx_type": "overdrive", "enabled": True, "bypass": False, "params": {"drive": drive, "tone": tone, "gain": gain}, "nam_model_path": "", "ir_file_path": ""} def distortion(drive=0.7, gain=0.5): return {"fx_type": "distortion", "enabled": True, "bypass": False, "params": {"drive": drive, "gain": gain}, "nam_model_path": "", "ir_file_path": ""} def fuzz(gain=0.6): return {"fx_type": "fuzz", "enabled": True, "bypass": False, "params": {"gain": gain}, "nam_model_path": "", "ir_file_path": ""} def eq(bass=0.5, mid=0.5, treble=0.5): return {"fx_type": "eq", "enabled": True, "bypass": False, "params": {"bass": bass, "mid": mid, "treble": treble}, "nam_model_path": "", "ir_file_path": ""} def ir_cab(ir_path): return {"fx_type": "ir_cab", "enabled": True, "bypass": False, "params": {"wet": 1.0, "dry": 0.0}, "nam_model_path": "", "ir_file_path": ir_path} def delay(time=400.0, feedback=0.3, mix=0.25): return {"fx_type": "delay", "enabled": True, "bypass": False, "params": {"time": time, "feedback": feedback, "mix": mix}, "nam_model_path": "", "ir_file_path": ""} def reverb(decay=0.4, mix=0.25): return {"fx_type": "reverb", "enabled": True, "bypass": False, "params": {"decay": decay, "mix": mix}, "nam_model_path": "", "ir_file_path": ""} def chorus(rate=0.35, depth=0.5, mix=0.3): return {"fx_type": "chorus", "enabled": True, "bypass": False, "params": {"rate": rate, "depth": depth, "mix": mix}, "nam_model_path": "", "ir_file_path": ""} def phaser(rate=0.3, depth=0.5, feedback=0.3): return {"fx_type": "phaser", "enabled": True, "bypass": False, "params": {"rate": rate, "depth": depth, "feedback": feedback}, "nam_model_path": "", "ir_file_path": ""} def flanger(rate=0.2, depth=0.4, feedback=0.3): return {"fx_type": "flanger", "enabled": True, "bypass": False, "params": {"rate": rate, "depth": depth, "feedback": feedback}, "nam_model_path": "", "ir_file_path": ""} def tremolo(rate=3.0, depth=0.4): return {"fx_type": "tremolo", "enabled": True, "bypass": False, "params": {"rate": rate, "depth": depth}, "nam_model_path": "", "ir_file_path": ""} def volume(level=0.85): return {"fx_type": "volume", "enabled": True, "bypass": False, "params": {"level": level}, "nam_model_path": "", "ir_file_path": ""} def octaver(mix=0.4): return {"fx_type": "octaver", "enabled": True, "bypass": False, "params": {"mix": mix}, "nam_model_path": "", "ir_file_path": ""} # ── Preset definitions per bank ──────────────────────────────────────── PRESETS = { 0: [ # Classic Rock { "name": "Brown Sound Crunch", "master_volume": 0.75, "chain": [ noise_gate(0.015), overdrive(0.55, 0.75, 0.5), eq(0.55, 0.35, 0.65), delay(380, 0.25, 0.2), ir_cab(IR["british"]), volume(0.78), ], }, { "name": "Singing Lead", "master_volume": 0.85, "chain": [ noise_gate(0.02), compressor(0.35, 3.5, 1.1), overdrive(0.7, 0.65, 0.6), distortion(0.5, 0.5), eq(0.5, 0.25, 0.75), delay(450, 0.35, 0.3), reverb(0.5, 0.25), ir_cab(IR["british"]), volume(0.88), ], }, { "name": "Sparkling Clean", "master_volume": 0.78, "chain": [ noise_gate(0.008), compressor(0.25, 4.0, 0.85), eq(0.45, 0.5, 0.65), chorus(0.3, 0.45, 0.3), reverb(0.35, 0.2), ir_cab(IR["vintage"]), volume(0.82), ], }, { "name": "Hard Rock Pounder", "master_volume": 0.7, "chain": [ noise_gate(0.025), boost(8.0), distortion(0.75, 0.45), eq(0.6, 0.25, 0.7), ir_cab(IR["modern"]), volume(0.72), ], }, ], 1: [ # Punk { "name": "Fast Riff Machine", "master_volume": 0.72, "chain": [ noise_gate(0.02), boost(6.0), overdrive(0.6, 0.7, 0.45), eq(0.5, 0.3, 0.7), ir_cab(IR["british"]), volume(0.75), ], }, { "name": "Snotty Lead", "master_volume": 0.82, "chain": [ noise_gate(0.015), overdrive(0.4, 0.85, 0.4), distortion(0.65, 0.5), eq(0.4, 0.35, 0.8), delay(350, 0.2, 0.2), ir_cab(IR["british"]), volume(0.85), ], }, { "name": "Jangle Pop Clean", "master_volume": 0.76, "chain": [ noise_gate(0.008), compressor(0.3, 4.5, 0.75), eq(0.4, 0.55, 0.7), chorus(0.4, 0.35, 0.25), reverb(0.3, 0.2), ir_cab(IR["american"]), volume(0.8), ], }, { "name": "Hardcore Attack", "master_volume": 0.68, "chain": [ noise_gate(0.03), boost(9.0), distortion(0.8, 0.4), eq(0.55, 0.2, 0.75), ir_cab(IR["modern"]), volume(0.7), ], }, ], 2: [ # Metal { "name": "Chug Chug", "master_volume": 0.65, "chain": [ noise_gate(0.035), boost(10.0), distortion(0.85, 0.35), eq(0.65, 0.15, 0.7), ir_cab(IR["modern"]), volume(0.68), ], }, { "name": "Scream Lead", "master_volume": 0.82, "chain": [ noise_gate(0.03), compressor(0.4, 3.0, 1.3), boost(8.0), distortion(0.75, 0.4), eq(0.5, 0.2, 0.85), delay(420, 0.3, 0.28), reverb(0.4, 0.2), ir_cab(IR["modern"]), volume(0.86), ], }, { "name": "Crystal Clean", "master_volume": 0.75, "chain": [ noise_gate(0.008), compressor(0.2, 5.0, 0.7), eq(0.4, 0.5, 0.65), chorus(0.3, 0.5, 0.35), reverb(0.45, 0.3), ir_cab(IR["vintage"]), volume(0.78), ], }, { "name": "Doom Descent", "master_volume": 0.6, "chain": [ noise_gate(0.04), boost(12.0), fuzz(0.75), distortion(0.9, 0.3), eq(0.7, 0.1, 0.65), ir_cab(IR["modern"]), volume(0.62), ], }, ], 3: [ # Hardcore { "name": "Punch Drunk", "master_volume": 0.7, "chain": [ noise_gate(0.025), overdrive(0.5, 0.8, 0.4), distortion(0.6, 0.5), eq(0.55, 0.25, 0.7), ir_cab(IR["modern"]), volume(0.73), ], }, { "name": "Vein Lead", "master_volume": 0.8, "chain": [ noise_gate(0.02), compressor(0.35, 3.5, 1.0), boost(7.0), overdrive(0.65, 0.6, 0.5), eq(0.5, 0.2, 0.8), delay(380, 0.25, 0.25), ir_cab(IR["british"]), volume(0.83), ], }, { "name": "Breather Clean", "master_volume": 0.74, "chain": [ noise_gate(0.008), compressor(0.28, 4.0, 0.8), eq(0.45, 0.55, 0.6), reverb(0.4, 0.25), ir_cab(IR["american"]), volume(0.76), ], }, { "name": "Pit Stomp", "master_volume": 0.66, "chain": [ noise_gate(0.035), boost(9.0), distortion(0.85, 0.35), eq(0.6, 0.15, 0.75), ir_cab(IR["modern"]), volume(0.68), ], }, ], 4: [ # Emo { "name": "Twinkle Crunch", "master_volume": 0.72, "chain": [ noise_gate(0.012), compressor(0.3, 4.0, 0.8), overdrive(0.35, 0.8, 0.55), chorus(0.4, 0.3, 0.2), eq(0.4, 0.6, 0.65), ir_cab(IR["american"]), volume(0.75), ], }, { "name": "Heartstring Lead", "master_volume": 0.84, "chain": [ noise_gate(0.015), compressor(0.3, 3.5, 1.0), overdrive(0.6, 0.7, 0.5), eq(0.45, 0.35, 0.75), delay(480, 0.4, 0.35), reverb(0.6, 0.3), ir_cab(IR["american"]), volume(0.86), ], }, { "name": "Diary Pages", "master_volume": 0.76, "chain": [ noise_gate(0.008), compressor(0.25, 5.0, 0.7), eq(0.35, 0.6, 0.55), reverb(0.55, 0.3), ir_cab(IR["vintage"]), volume(0.78), ], }, { "name": "Pop Core", "master_volume": 0.7, "chain": [ noise_gate(0.02), boost(7.0), distortion(0.7, 0.45), eq(0.5, 0.25, 0.7), delay(350, 0.2, 0.15), ir_cab(IR["british"]), volume(0.72), ], }, ], 5: [ # Midwest Emo { "name": "Mathy Tappy", "master_volume": 0.72, "chain": [ noise_gate(0.01), compressor(0.3, 4.5, 0.75), overdrive(0.3, 0.85, 0.5), eq(0.4, 0.55, 0.6), delay(400, 0.2, 0.15), ir_cab(IR["american"]), volume(0.74), ], }, { "name": "Emotive Swell", "master_volume": 0.82, "chain": [ noise_gate(0.012), compressor(0.28, 4.0, 0.9), overdrive(0.5, 0.75, 0.45), eq(0.4, 0.4, 0.7), delay(500, 0.35, 0.3), reverb(0.5, 0.3), ir_cab(IR["american"]), volume(0.84), ], }, { "name": "Fingerpicked Porch", "master_volume": 0.75, "chain": [ noise_gate(0.006), compressor(0.2, 5.0, 0.7), eq(0.35, 0.65, 0.55), chorus(0.25, 0.35, 0.2), reverb(0.4, 0.22), ir_cab(IR["boutique"]), volume(0.77), ], }, { "name": "Power Chord Wall", "master_volume": 0.68, "chain": [ noise_gate(0.02), overdrive(0.55, 0.7, 0.45), distortion(0.6, 0.5), eq(0.5, 0.3, 0.65), ir_cab(IR["british"]), volume(0.7), ], }, ], 6: [ # Djent { "name": "Machine Gun", "master_volume": 0.62, "chain": [ noise_gate(0.04), compressor(0.4, 6.0, 1.0), boost(12.0), distortion(0.85, 0.3), eq(0.7, 0.1, 0.8), ir_cab(IR["modern"]), volume(0.65), ], }, { "name": "Polyphonic Lead", "master_volume": 0.8, "chain": [ noise_gate(0.025), compressor(0.35, 4.0, 1.1), overdrive(0.6, 0.6, 0.55), eq(0.55, 0.2, 0.8), delay(440, 0.3, 0.28), reverb(0.45, 0.2), ir_cab(IR["modern"]), volume(0.82), ], }, { "name": "Clean Arpeggio", "master_volume": 0.76, "chain": [ noise_gate(0.008), compressor(0.25, 5.0, 0.7), eq(0.4, 0.5, 0.6), chorus(0.3, 0.4, 0.3), delay(480, 0.25, 0.2), reverb(0.4, 0.25), ir_cab(IR["american"]), volume(0.78), ], }, { "name": "Syncopated Riff", "master_volume": 0.6, "chain": [ noise_gate(0.045), boost(10.0), fuzz(0.7), distortion(0.8, 0.3), eq(0.65, 0.1, 0.75), ir_cab(IR["modern"]), volume(0.62), ], }, ], 7: [ # Acoustic { "name": "Body Strum", "master_volume": 0.78, "chain": [ noise_gate(0.005), compressor(0.25, 4.5, 0.65), eq(0.5, 0.6, 0.55), reverb(0.35, 0.2), ir_cab(IR["boutique"]), volume(0.8), ], }, { "name": "Fingerpicking Lead", "master_volume": 0.82, "chain": [ noise_gate(0.005), compressor(0.2, 5.0, 0.7), eq(0.4, 0.65, 0.5), delay(380, 0.2, 0.18), reverb(0.45, 0.25), ir_cab(IR["boutique"]), volume(0.84), ], }, { "name": "Ambient Soundscape", "master_volume": 0.8, "chain": [ noise_gate(0.005), compressor(0.3, 4.0, 0.8), eq(0.4, 0.5, 0.55), chorus(0.2, 0.5, 0.4), reverb(0.7, 0.4), ir_cab(IR["jazz"]), volume(0.82), ], }, { "name": "Percussive Slap", "master_volume": 0.74, "chain": [ noise_gate(0.006), compressor(0.35, 6.0, 0.6), boost(4.0), eq(0.55, 0.4, 0.65), ir_cab(IR["american"]), volume(0.76), ], }, ], 8: [ # Grunge { "name": "Fuzz Festival", "master_volume": 0.7, "chain": [ noise_gate(0.015), overdrive(0.5, 0.75, 0.4), fuzz(0.6), eq(0.55, 0.2, 0.7), ir_cab(IR["british"]), volume(0.72), ], }, { "name": "Biting Solo", "master_volume": 0.82, "chain": [ noise_gate(0.02), boost(7.0), distortion(0.65, 0.5), eq(0.35, 0.15, 0.85), delay(400, 0.3, 0.28), ir_cab(IR["british"]), volume(0.85), ], }, { "name": "Grunge Clean", "master_volume": 0.75, "chain": [ noise_gate(0.008), compressor(0.3, 4.0, 0.8), overdrive(0.2, 0.9, 0.5), phaser(0.25, 0.4, 0.3), eq(0.45, 0.5, 0.6), ir_cab(IR["vintage"]), volume(0.77), ], }, { "name": "Wall of Noise", "master_volume": 0.65, "chain": [ noise_gate(0.025), boost(10.0), fuzz(0.8), distortion(0.7, 0.35), eq(0.6, 0.1, 0.75), ir_cab(IR["modern"]), volume(0.67), ], }, ], 9: [ # Alternative Rock { "name": "Indie Crunch", "master_volume": 0.74, "chain": [ noise_gate(0.012), overdrive(0.45, 0.78, 0.55), eq(0.5, 0.4, 0.65), ir_cab(IR["american"]), volume(0.76), ], }, { "name": "Quirky Lead", "master_volume": 0.84, "chain": [ noise_gate(0.015), compressor(0.3, 3.5, 1.0), overdrive(0.55, 0.65, 0.5), flanger(0.15, 0.35, 0.25), eq(0.45, 0.3, 0.75), delay(420, 0.3, 0.28), ir_cab(IR["american"]), volume(0.86), ], }, { "name": "Jangle Box", "master_volume": 0.76, "chain": [ noise_gate(0.008), compressor(0.25, 4.5, 0.75), eq(0.4, 0.55, 0.65), tremolo(4.0, 0.35), reverb(0.3, 0.2), ir_cab(IR["american"]), volume(0.78), ], }, { "name": "Alt Heavy", "master_volume": 0.68, "chain": [ noise_gate(0.025), boost(8.0), distortion(0.75, 0.4), octaver(0.3), eq(0.55, 0.2, 0.75), ir_cab(IR["modern"]), volume(0.7), ], }, ], 10: [ # Garage Rock { "name": "Lo-Fi Crunch", "master_volume": 0.72, "chain": [ noise_gate(0.015), overdrive(0.6, 0.7, 0.35), eq(0.5, 0.3, 0.55), ir_cab(IR["mini"]), volume(0.74), ], }, { "name": "Fuzzed Out", "master_volume": 0.8, "chain": [ noise_gate(0.01), boost(6.0), fuzz(0.7), eq(0.45, 0.25, 0.65), delay(300, 0.3, 0.25), ir_cab(IR["british"]), volume(0.82), ], }, { "name": "Raw Clean", "master_volume": 0.78, "chain": [ noise_gate(0.006), eq(0.45, 0.55, 0.5), tremolo(2.5, 0.3), reverb(0.3, 0.18), ir_cab(IR["vintage"]), volume(0.8), ], }, { "name": "Sludge Fuzz", "master_volume": 0.62, "chain": [ noise_gate(0.03), boost(12.0), fuzz(0.85), distortion(0.7, 0.3), eq(0.65, 0.1, 0.6), ir_cab(IR["modern"]), volume(0.64), ], }, ], 11: [ # Pop { "name": "Clean Pop", "master_volume": 0.78, "chain": [ noise_gate(0.006), compressor(0.28, 4.5, 0.7), overdrive(0.2, 0.9, 0.6), eq(0.45, 0.5, 0.6), ir_cab(IR["american"]), volume(0.8), ], }, { "name": "Catchy Hook", "master_volume": 0.84, "chain": [ noise_gate(0.01), compressor(0.3, 4.0, 0.9), overdrive(0.4, 0.8, 0.5), chorus(0.35, 0.4, 0.3), delay(380, 0.25, 0.22), ir_cab(IR["american"]), volume(0.86), ], }, { "name": "Shimmer Clean", "master_volume": 0.8, "chain": [ noise_gate(0.006), compressor(0.2, 5.0, 0.65), eq(0.35, 0.55, 0.65), chorus(0.3, 0.5, 0.35), reverb(0.5, 0.3), ir_cab(IR["vintage"]), volume(0.82), ], }, { "name": "Pop Punk", "master_volume": 0.72, "chain": [ noise_gate(0.018), overdrive(0.5, 0.75, 0.45), distortion(0.55, 0.55), eq(0.5, 0.3, 0.7), delay(320, 0.15, 0.12), ir_cab(IR["british"]), volume(0.74), ], }, ], } # ── Generate all files ───────────────────────────────────────────────── def generate(): # Wipe existing factory dir if os.path.exists(FACTORY_DIR): # Remove all bank dirs but keep irs/ for entry in os.listdir(FACTORY_DIR): path = os.path.join(FACTORY_DIR, entry) if entry != "irs" and os.path.isdir(path): shutil.rmtree(path) elif entry != "irs" and os.path.isfile(path): os.remove(path) for bank in BANKS: num = bank["number"] bank_dir = os.path.join(FACTORY_DIR, f"bank_{num}") os.makedirs(bank_dir, exist_ok=True) # bank.json bank_json = { "number": num, "name": bank["name"], "preset_count": 4, } with open(os.path.join(bank_dir, "bank.json"), "w") as f: json.dump(bank_json, f, indent=2) f.write("\n") # 4 presets for prog in range(4): preset_data = PRESETS[num][prog] preset_json = { "name": preset_data["name"], "bank": num, "program": prog, "master_volume": preset_data["master_volume"], "tuner_enabled": False, "chain": preset_data["chain"], "midi_mappings": {}, } path = os.path.join(bank_dir, f"preset_{prog}.json") with open(path, "w") as f: json.dump(preset_json, f, indent=2) f.write("\n") print(f"✅ Generated {len(BANKS) * 4} presets across {len(BANKS)} banks") for bank in BANKS: print(f" Bank {bank['number']}: {bank['name']} — 4 presets") if __name__ == "__main__": generate()