5c51b3db28
Bank 7 — Bass: Ampeg PF20T, Aguilar Tone Hammer 500, GK 800RB (Gallien-Krueger), Aguilar DB751 Bank 7 — Orange: Orange Rocker 30 Dirty + Natural Bank 7 — Others: Fender Bassman dimed, Hiwatt DR103 Bright + Cornish, Supro Black Magick M3 All SlimmableContainer v0.7.0, ~287-295 KB, verified JSON. Also fixed Bank 2 Tone3000 storage keys to include .nam extension (Tone3000 changed URL format). Inventory updated: 54 → 64 total models.
509 lines
20 KiB
Python
509 lines
20 KiB
Python
#!/usr/bin/env python3
|
|
"""Download NAM WaveNet models from community collection + cabinet IRs.
|
|
|
|
Downloads real NAM amp captures from the pelennor2170/NAM_models GitHub
|
|
repository and free cabinet IR packs from Archive.org.
|
|
|
|
Usage:
|
|
python3 scripts/download_nam_and_irs.py # Download everything
|
|
python3 scripts/download_nam_and_irs.py --list # List models only
|
|
python3 scripts/download_nam_and_irs.py --models # Models only
|
|
python3 scripts/download_nam_and_irs.py --irs # IRs only
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
import urllib.parse
|
|
import urllib.request
|
|
from pathlib import Path
|
|
|
|
# ── Paths ────────────────────────────────────────────────────────────────
|
|
NAM_DIR = Path.home() / ".pedal" / "models"
|
|
IR_DIR = Path.home() / ".pedal" / "irs"
|
|
BASE_URL = "https://raw.githubusercontent.com/pelennor2170/NAM_models/main"
|
|
|
|
# ── Model definitions ────────────────────────────────────────────────────
|
|
# (local_name, remote_name, description, architecture, size_kb)
|
|
# URL for Tone3000 (ToneHunt) Supabase storage downloads
|
|
TONE3000_STORAGE = "https://api.tone3000.com/storage/v1/object/public/models"
|
|
|
|
MODELS = [
|
|
# ── Bank 0: Clean & Edge ──────────────────────────────────────────
|
|
("Fender_TwinVerb_Clean.nam",
|
|
"Tim R Fender TwinVerb Norm Bright.nam",
|
|
"Fender Twin Reverb Normal Bright — clean jazz/fingerstyle",
|
|
"WaveNet", 400),
|
|
("Fender_TwinVerb_Vibrato.nam",
|
|
"Tim R Fender TwinVerb Vibrato Bright.nam",
|
|
"Fender Twin Reverb Vibrato Bright — sparkling clean",
|
|
"WaveNet", 400),
|
|
("Vox_AC15_TopBoost.nam",
|
|
"Phillipe P VOXAC15-TopBoost.nam",
|
|
"Vox AC15 Top Boost — chimey edge-of-breakup",
|
|
"WaveNet", 400),
|
|
("Magnatone_Super59_Pushed.nam",
|
|
"Tim R Magnatone Super 59 Mkii Pushed.nam",
|
|
"Magnatone Super 59 pushed — bluesy breakup",
|
|
"WaveNet", 400),
|
|
("JCM2000_Clean.nam",
|
|
"Tim R JCM2000 Clean.nam",
|
|
"Marshall JCM2000 clean — crisp rhythm",
|
|
"WaveNet", 400),
|
|
|
|
# ── Bank 1: Drive & Lead ──────────────────────────────────────────
|
|
("Orange_Rockerverb.nam",
|
|
"Tom C Axe FX 2 Orange Rockerverb.nam",
|
|
"Orange Rockerverb — classic rock crunch",
|
|
"WaveNet", 400),
|
|
("JCM2000_Crunch.nam",
|
|
"Tim R JCM2000 Crunch.nam",
|
|
"Marshall JCM2000 crunch — hard rock rhythm",
|
|
"WaveNet", 400),
|
|
("JCM900_Lead.nam",
|
|
"Tim R JCM90050WDualVerbCHAG6.nam",
|
|
"Marshall JCM900 Dual Verb ch.A gain6 — lead",
|
|
"WaveNet", 400),
|
|
("5150_BlockLetter_Boosted.nam",
|
|
"Helga B 5150 BlockLetter - Boosted.nam",
|
|
"EVH 5150 Block Letter boosted — high-gain lead",
|
|
"WaveNet", 400),
|
|
("6505_Red_NoBoost.nam",
|
|
"Helga B 6505+ Red ch - NoBoost.nam",
|
|
"Peavey 6505+ Red ch no boost — metal rhythm",
|
|
"WaveNet", 400),
|
|
("Engl_Savage.nam",
|
|
"Tom C Axe FX 2 Engl Savage.nam",
|
|
"ENGL Savage 120 — modern high-gain lead",
|
|
"WaveNet", 400),
|
|
("Splawn_ProMod_3rd.nam",
|
|
"Tim R Splawn Pro Mod 3rd Gear - G12.nam",
|
|
"Splawn Pro Mod 3rd gear — tight high-gain",
|
|
"WaveNet", 400),
|
|
("5152_Lead_TS9.nam",
|
|
"Tim R 5152 Lead + TS9.nam",
|
|
"5152 Lead with Tube Screamer — boosted solo",
|
|
"WaveNet", 400),
|
|
|
|
# ── Pedal captures ───────────────────────────────────────────────
|
|
("Klon_Centaur_High.nam",
|
|
"Keith B Klone_plus_BB_highGain.nam",
|
|
"Klon Centaur-style OD high gain — boost/overdrive",
|
|
"WaveNet", 400),
|
|
("TubeScreamer_Maxed.nam",
|
|
"Tudor N Ibanez Tube Screamer Mini Tone@10_Level@10_Overdrive@0 ESR_0.0006_lite.nam",
|
|
"Ibanez TS808 Mini maxed — clean boost",
|
|
"WaveNet", 200),
|
|
("Mesa_MarkIV_Lead.nam",
|
|
"Roman A LT_MESA_MARKIV_1.nam",
|
|
"Mesa Boogie Mark IV lead — singing sustain",
|
|
"WaveNet", 400),
|
|
("Bogner_Ecstasy.nam",
|
|
"Tudor N Ceriatone Molecular 50.nam",
|
|
"Bogner Ecstasy-style — versatile OD range",
|
|
"WaveNet", 400),
|
|
|
|
# ── Feather models (93 KB, ultra-low CPU) ────────────────────────
|
|
("BOSS_SD1_Feather.nam",
|
|
"Phillipe P BOSS-SD1-Feather-ESR0,001.nam",
|
|
"BOSS SD-1 overdrive feather — 93 KB",
|
|
"WaveNet", 93),
|
|
("MXR_M77_Feather.nam",
|
|
"Phillipe P MXR-M77-Feather-ESR0,001.nam",
|
|
"MXR M77 Custom Badass OD feather — 93 KB",
|
|
"WaveNet", 93),
|
|
("TS808_Feather.nam",
|
|
"Phillipe P Maxon-OD808-Feather-ESR0,001.nam",
|
|
"Maxon OD808 Tube Screamer feather — 93 KB",
|
|
"WaveNet", 93),
|
|
("Precision_Drive_Feather.nam",
|
|
"Phillipe P Precision-Drive-Feather-ESR0,001.nam",
|
|
"Precision Drive overdrive feather — 93 KB",
|
|
"WaveNet", 93),
|
|
("Friedman_PowerAmp_Feather.nam",
|
|
"Sascha S FriedmanDSM_PowerAmpEL84_MV10_feather.nam",
|
|
"Friedman DSM power amp feather — 93 KB",
|
|
"WaveNet", 93),
|
|
|
|
# ── Bank 2: Blues (Tone3000 captures — clean, edge-of-breakup, pushed) ─
|
|
# Downloaded from ToneHunt / Tone3000 Supabase storage. These are real
|
|
# amp captures of classic blues tones: Fender Princeton, Tweed Deluxe,
|
|
# Twin Reverb, Dumble ODS, Two-Rock, Marshall Bluesbreaker.
|
|
# Format: (local_name, tone3000_storage_key, description, architecture, size_kb)
|
|
("Fender_Princeton_Clone_Clean.nam",
|
|
"4f81e2b088149c04.nam",
|
|
"Fender Hand-wired Princeton Clone Clean — blues clean (WaveNet A1, 289 KB)",
|
|
"WaveNet", 289),
|
|
("Fender_Princeton_Clone_EOB.nam",
|
|
"68a5f3484e1759ed_a2.nam",
|
|
"Fender Hand-wired Princeton Clone Edge-of-Breakup — blues edge (Slimmable A2, 288 KB)",
|
|
"SlimmableContainer", 288),
|
|
("Fender_Tweed_Dlx_Edge.nam",
|
|
"ga5rj9sxlnk.nam",
|
|
"Fender Tweed Deluxe The Edge (Celestion Blue) — pushed clean (Slimmable A2, 288 KB)",
|
|
"SlimmableContainer", 288),
|
|
("Fender_Twin_Reverb_Clean_A2.nam",
|
|
"tg81uadutjo_a2.nam",
|
|
"Fender Twin Reverb Clean — sparkling blues clean (Slimmable A2, 290 KB)",
|
|
"SlimmableContainer", 290),
|
|
("TwoRock_JTM_Signature.nam",
|
|
"qj3hkgbcwb9.nam",
|
|
"Two-Rock John Mayer Signature Prototype — clean/edge bloom (WaveNet A1, 276 KB)",
|
|
"WaveNet", 276),
|
|
("Dumble_ODS_102_Rock_A1.nam",
|
|
"5bac98f136812852.nam",
|
|
"Dumble ODS #102 Clone Rock setting — pushed blues overdrive (WaveNet A1, 87 KB feather)",
|
|
"WaveNet", 87),
|
|
("Dumble_ODS_102_Rock_A2.nam",
|
|
"5bac98f136812852_a2.nam",
|
|
"Dumble ODS #102 Clone Rock setting — pushed blues OD (Slimmable A2, 289 KB)",
|
|
"SlimmableContainer", 289),
|
|
("Marshall_Bluesbreaker_1962_A2.nam",
|
|
"bbc41ecccdc730fb_a2.nam",
|
|
"Marshall Bluesbreaker 1962 — classic blues rock (Slimmable A2, 289 KB)",
|
|
"SlimmableContainer", 289),
|
|
("Marshall_Bluesbreaker_Pedal.nam",
|
|
"31aeae1256b36839.nam",
|
|
"Marshall Bluesbreaker Pedal (Original) Setting 1 — pedal OD (WaveNet A1, 290 KB)",
|
|
"WaveNet", 290),
|
|
|
|
|
|
# ── Bank 7: Bass, Orange & Others (Tone3000 A2 — SlimmableContainer) ────
|
|
# Downloaded from Tone3000 Supabase storage. Covers missing categories:
|
|
# Bass (Ampeg, Aguilar, GK), Orange Rocker 30, Fender Bassman,
|
|
# Hiwatt DR103, Supro Black Magick.
|
|
("Ampeg_PF20T_A2.nam",
|
|
"db2c43e99cfc346d_a2.nam",
|
|
"Ampeg PF20T — clean bass tube amp (Slimmable A2, 288 KB)",
|
|
"SlimmableContainer", 288),
|
|
("Aguilar_Tone_Hammer_500_A2.nam",
|
|
"38rdhwzk3hp_a2.nam",
|
|
"Aguilar Tone Hammer 500 — modern bass preamp (Slimmable A2, 293 KB)",
|
|
"SlimmableContainer", 293),
|
|
("GK_800RB_Line_A2.nam",
|
|
"ce68ccd373a10054_a2.nam",
|
|
"Gallien-Krueger 800RB — classic bass solid-state (Slimmable A2, 295 KB)",
|
|
"SlimmableContainer", 295),
|
|
("Aguilar_DB751_Cab_A2.nam",
|
|
"lage0x4ybk_a2.nam",
|
|
"Aguilar DB751 — bass amp DI (Slimmable A2, 292 KB)",
|
|
"SlimmableContainer", 292),
|
|
("Orange_Rocker30_Dirty_A2.nam",
|
|
"8491c70c3771de1e_a2.nam",
|
|
"Orange Rocker 30 Dirty — classic rock crunch (Slimmable A2, 295 KB)",
|
|
"SlimmableContainer", 295),
|
|
("Orange_Rocker30_Natural_A2.nam",
|
|
"a60ed1a1aa0c2c0f_a2.nam",
|
|
"Orange Rocker 30 Natural — clean edge (Slimmable A2, 289 KB)",
|
|
"SlimmableContainer", 289),
|
|
("Fender_Bassman_Dimed_A2.nam",
|
|
"0a9223a9f1c879d5_a2.nam",
|
|
"Fender Bassman dimed — blues/rock breakup (Slimmable A2, 289 KB)",
|
|
"SlimmableContainer", 289),
|
|
("Hiwatt_DR103_Bright_A2.nam",
|
|
"0c46e5a7db1cce48_a2.nam",
|
|
"Hiwatt DR-103 Bright Normal — prog/classic rock (Slimmable A2, 287 KB)",
|
|
"SlimmableContainer", 287),
|
|
("Hiwatt_DR103_Cornish_A2.nam",
|
|
"ynk0h2e2tph.nam",
|
|
"Hiwatt DR103 + Cornish PGS — boosted prog rock (Slimmable A2, 288 KB)",
|
|
"SlimmableContainer", 288),
|
|
("Supro_Black_Magick_M3_A2.nam",
|
|
"c90a6d8ee0c0a689_a2.nam",
|
|
"Supro Black Magick M3 — garage/blues (Slimmable A2, 288 KB)",
|
|
"SlimmableContainer", 288),
|
|
]
|
|
|
|
# ── IR Pack definitions ──────────────────────────────────────────────────
|
|
IR_PACKS = [
|
|
("God's Cab",
|
|
"https://archive.org/download/godscab-ir-pack/GodsCab_IR_Pack.zip",
|
|
"godscab.zip",
|
|
"100+ cabinet IRs (412, 1960, V30, Greenback, etc.) — CC0 / Public Domain"),
|
|
("Seacow Cabs",
|
|
"https://archive.org/download/seacow-cabs-free-ir-2023/Seacow_Cabs_Free_IRs_2023.zip",
|
|
"seacow.zip",
|
|
"Boutique cab IR pack, 15+ cabs — Free for personal use"),
|
|
]
|
|
|
|
|
|
def info(msg): print(f"\033[0;36m[INFO]\033[0m {msg}")
|
|
def ok(msg): print(f"\033[0;32m[OK]\033[0m {msg}")
|
|
def warn(msg): print(f"\033[1;33m[WARN]\033[0m {msg}")
|
|
def err(msg): print(f"\033[0;31m[ERR]\033[0m {msg}", file=sys.stderr)
|
|
|
|
|
|
def download_file(url: str, dest: Path, max_size_mb: int = 50) -> bool:
|
|
"""Download a file from url to dest. Returns True on success."""
|
|
try:
|
|
req = urllib.request.Request(url, headers={"User-Agent": "pedal-downloader/1.0"})
|
|
with urllib.request.urlopen(req, timeout=30) as src:
|
|
data = src.read()
|
|
size_mb = len(data) / (1024 * 1024)
|
|
if size_mb > max_size_mb:
|
|
err(f"File too large ({size_mb:.1f} MB, max {max_size_mb} MB)")
|
|
return False
|
|
if len(data) < 1000:
|
|
err(f"File too small ({len(data)} bytes)")
|
|
return False
|
|
dest.write_bytes(data)
|
|
return True
|
|
except Exception as e:
|
|
err(f"Download failed: {e}")
|
|
return False
|
|
|
|
|
|
def download_model(local_name: str, remote_name: str, desc: str, arch: str, size: int) -> bool:
|
|
"""Download a single NAM model file from GitHub."""
|
|
outfile = NAM_DIR / local_name
|
|
|
|
if outfile.exists() and outfile.stat().st_size > 1000:
|
|
ok(f"SKIP {local_name} (already exists, {outfile.stat().st_size // 1024} KB)")
|
|
return True
|
|
|
|
# URL-encode the remote filename
|
|
encoded = urllib.parse.quote(remote_name)
|
|
url = f"{BASE_URL}/{encoded}"
|
|
|
|
info(f"DL {local_name} ({desc})")
|
|
if download_file(url, outfile):
|
|
# Verify it's valid JSON (.nam format)
|
|
try:
|
|
data = json.loads(outfile.read_text())
|
|
actual_arch = data.get("architecture", "?")
|
|
actual_ver = data.get("version", "?")
|
|
ok(f"Downloaded {local_name} ({outfile.stat().st_size // 1024} KB, {actual_arch} v{actual_ver})")
|
|
return True
|
|
except json.JSONDecodeError as e:
|
|
err(f"Invalid .nam file (not valid JSON): {e}")
|
|
outfile.unlink(missing_ok=True)
|
|
return False
|
|
else:
|
|
err(f"Failed to download {local_name}")
|
|
return False
|
|
|
|
|
|
def _discover_tone3000_key() -> str:
|
|
"""Discover the Supabase anon key from Tone3000 website JS bundles."""
|
|
try:
|
|
req = urllib.request.Request(
|
|
"https://tone3000.com",
|
|
headers={"User-Agent": "Mozilla/5.0 (compatible; pedal-downloader/1.0)"},
|
|
)
|
|
with urllib.request.urlopen(req, timeout=15) as resp:
|
|
html = resp.read().decode("utf-8", errors="replace")
|
|
import re
|
|
chunk_urls = set()
|
|
for m in re.finditer(r'src="([^"]*\.js[^"]*)"', html):
|
|
url = m.group(1)
|
|
if url.startswith("/"):
|
|
url = "https://tone3000.com" + url
|
|
chunk_urls.add(url)
|
|
for chunk_url in sorted(chunk_urls)[:15]:
|
|
try:
|
|
req2 = urllib.request.Request(chunk_url, headers={"User-Agent": "Mozilla/5.0"})
|
|
with urllib.request.urlopen(req2, timeout=10) as resp2:
|
|
js = resp2.read().decode("utf-8", errors="replace")
|
|
m = re.search(
|
|
r'createBrowserClient\s*\)\s*\(\s*["\']https?://api\.tone3000\.com["\']\s*,\s*["\']([^"\']+)["\']',
|
|
js,
|
|
)
|
|
if m:
|
|
key = m.group(1)
|
|
if key.startswith("eyJ") and key.count(".") >= 2:
|
|
return key
|
|
for m2 in re.finditer(
|
|
r'["\'](eyJ[a-zA-Z0-9_\-]{20,}\.[a-zA-Z0-9_\-]{20,}\.[a-zA-Z0-9_\-]{10,})["\']', js
|
|
):
|
|
key = m2.group(1)
|
|
if key.count(".") >= 2:
|
|
return key
|
|
except Exception:
|
|
continue
|
|
except Exception:
|
|
pass
|
|
return ""
|
|
|
|
|
|
def download_tone3000_model(local_name: str, storage_key: str, desc: str, arch: str, size: int) -> bool:
|
|
"""Download a single NAM model file from Tone3000 Supabase storage."""
|
|
outfile = NAM_DIR / local_name
|
|
|
|
if outfile.exists() and outfile.stat().st_size > 1000:
|
|
ok(f"SKIP {local_name} (already exists, {outfile.stat().st_size // 1024} KB)")
|
|
return True
|
|
|
|
url = f"{TONE3000_STORAGE}/{storage_key}"
|
|
|
|
info(f"DL {local_name} ({desc})")
|
|
req = urllib.request.Request(url, headers={"User-Agent": "pedal-downloader/1.0"})
|
|
try:
|
|
with urllib.request.urlopen(req, timeout=30) as src:
|
|
data = src.read()
|
|
except Exception as e:
|
|
err(f"Download failed: {e}")
|
|
# Try with anon key (some storage buckets require authentication)
|
|
try:
|
|
anon_key = _discover_tone3000_key()
|
|
if anon_key:
|
|
req = urllib.request.Request(url, headers={
|
|
"User-Agent": "pedal-downloader/1.0",
|
|
"Authorization": f"Bearer {anon_key}",
|
|
})
|
|
with urllib.request.urlopen(req, timeout=30) as src:
|
|
data = src.read()
|
|
else:
|
|
return False
|
|
except Exception as e2:
|
|
err(f"Download failed even with auth: {e2}")
|
|
return False
|
|
|
|
size_mb = len(data) / (1024 * 1024)
|
|
if size_mb > 50:
|
|
err(f"File too large ({size_mb:.1f} MB, max 50 MB)")
|
|
return False
|
|
if len(data) < 1000:
|
|
err(f"File too small ({len(data)} bytes)")
|
|
return False
|
|
outfile.write_bytes(data)
|
|
|
|
# Verify
|
|
try:
|
|
model_data = json.loads(data)
|
|
actual_arch = model_data.get("architecture", "?")
|
|
actual_ver = model_data.get("version", "?")
|
|
ok(f"Downloaded {local_name} ({outfile.stat().st_size // 1024} KB, {actual_arch} v{actual_ver})")
|
|
return True
|
|
except json.JSONDecodeError as e:
|
|
err(f"Invalid .nam file (not valid JSON): {e}")
|
|
outfile.unlink(missing_ok=True)
|
|
return False
|
|
|
|
|
|
def download_models():
|
|
"""Download all NAM models (GitHub + Tone3000)."""
|
|
print(f"\n\033[0;36mDownloading {len(MODELS)} NAM models to {NAM_DIR}\033[0m")
|
|
print(f"\033[0;36m{'━' * 60}\033[0m")
|
|
NAM_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
success = 0
|
|
fail = 0
|
|
|
|
for local_name, remote_name, desc, arch, size in MODELS:
|
|
# Detect Tone3000 storage key (short, no dots, no spaces)
|
|
if " " not in remote_name and "." not in remote_name and len(remote_name) < 64:
|
|
if download_tone3000_model(local_name, remote_name, desc, arch, size):
|
|
success += 1
|
|
else:
|
|
fail += 1
|
|
else:
|
|
if download_model(local_name, remote_name, desc, arch, size):
|
|
success += 1
|
|
else:
|
|
fail += 1
|
|
|
|
print(f"\n Models: {success} successful, {fail} failed")
|
|
return fail
|
|
|
|
|
|
def download_irs():
|
|
"""Download IR packs from Archive.org."""
|
|
print(f"\n\033[0;36mDownloading IR packs to {IR_DIR}\033[0m")
|
|
print(f"\033[0;36m{'━' * 60}\033[0m")
|
|
IR_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
success = 0
|
|
fail = 0
|
|
|
|
for name, url, fname, desc in IR_PACKS:
|
|
# Check if already extracted
|
|
wav_count = len(list(IR_DIR.rglob("*.wav")))
|
|
if wav_count > 10:
|
|
ok(f"SKIP {name} ({wav_count} .wav files already present)")
|
|
success += 1
|
|
continue
|
|
|
|
dest = IR_DIR / fname
|
|
info(f"Downloading {name}...")
|
|
info(f" Source: {url}")
|
|
|
|
if download_file(url, dest, max_size_mb=200):
|
|
size_mb = dest.stat().st_size / (1024 * 1024)
|
|
ok(f"Downloaded {fname} ({size_mb:.1f} MB)")
|
|
|
|
# Extract ZIP
|
|
import zipfile
|
|
try:
|
|
with zipfile.ZipFile(dest, "r") as zf:
|
|
zf.extractall(IR_DIR)
|
|
dest.unlink()
|
|
wav_count = len(list(IR_DIR.rglob("*.wav")))
|
|
ok(f"Extracted to {IR_DIR}/ ({wav_count} .wav files)")
|
|
success += 1
|
|
except zipfile.BadZipFile:
|
|
warn(f"Bad ZIP — saved at {dest}")
|
|
fail += 1
|
|
else:
|
|
err(f"Failed to download {name}")
|
|
fail += 1
|
|
|
|
print(f"\n IR packs: {success} downloaded, {fail} failed")
|
|
wav_count = len(list(IR_DIR.rglob("*.wav")))
|
|
info(f"Total .wav IR files: {wav_count}")
|
|
return fail
|
|
|
|
|
|
def list_models():
|
|
"""Print model listing."""
|
|
print(f"\n\033[0;36mNAM Models by Genre:\033[0m")
|
|
print(f"\033[0;36m{'━' * 60}\033[0m")
|
|
for local_name, remote_name, desc, arch, size in MODELS:
|
|
print(f" {local_name:35s} {desc}")
|
|
print(f" {'':35s} ({arch}, ~{size} KB)")
|
|
print()
|
|
|
|
print(f"\nTotal: {len(MODELS)} models")
|
|
|
|
# Count existing files
|
|
nam_count = len(list(NAM_DIR.glob("*.nam")))
|
|
ir_count = len(list(IR_DIR.rglob("*.wav")))
|
|
print(f"\n Models in {NAM_DIR}: {nam_count}")
|
|
print(f" IRs in {IR_DIR}: {ir_count}")
|
|
|
|
|
|
def main():
|
|
# Also check ~/.pedal/nam/ legacy location
|
|
NAM_DIR.mkdir(parents=True, exist_ok=True)
|
|
IR_DIR.mkdir(parents=True, exist_ok=True)
|
|
|
|
arg = sys.argv[1] if len(sys.argv) > 1 else "--all"
|
|
|
|
if arg == "--list":
|
|
list_models()
|
|
elif arg == "--models":
|
|
exit(download_models())
|
|
elif arg == "--irs":
|
|
exit(download_irs())
|
|
elif arg == "--all":
|
|
fail = download_models()
|
|
download_irs()
|
|
|
|
# Summary
|
|
nam_count = len(list(NAM_DIR.glob("*.nam")))
|
|
ir_count = len(list(IR_DIR.rglob("*.wav")))
|
|
print(f"\n\033[0;32m{'╔' + '═' * 56 + '╗'}\033[0m")
|
|
print(f"\033[0;32m║ Download complete!{' ' * 36}║\033[0m")
|
|
print(f"\033[0;32m{'╚' + '═' * 56 + '╝'}\033[0m")
|
|
print()
|
|
print(f" Models: {nam_count} .nam files in {NAM_DIR}")
|
|
print(f" IRs: {ir_count} .wav files in {IR_DIR}")
|
|
exit(fail)
|
|
else:
|
|
print(f"Usage: {sys.argv[0]} [--list|--models|--irs|--all]")
|
|
exit(1)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|