#!/bin/bash # nam-build.sh — Build Neural Amp Modeler LV2 plugin for RPi4B (ARM Cortex-A72) # This builds the headless LV2 version that Carla can host. # Uses RTNeural for real-time neural inference (no libtorch needed). # # Usage: # chmod +x nam-build.sh # ./nam-build.sh # Build only # ./nam-build.sh --install # Build + install LV2 to /usr/lib/lv2 # ./nam-build.sh --clean # Clean rebuild # # Note: NAM models are CPU-intensive. For RPi4B, use "feather" or "nano" # sized models from https://www.tone3000.com/. Standard models may xrun. set -euo pipefail NAM_REPO="https://github.com/mikeoliphant/neural-amp-modeler-lv2.git" NAM_DIR="/tmp/nam-lv2-build" JOBS=$(nproc 2>/dev/null || echo 4) # Cortex-A72 optimized flags # Use -march=armv8-a (no crypto needed for NAM) + -O3 # Enable NEON explicitly for vectorized math A72_FLAGS="-march=armv8-a -mtune=cortex-a72 -O3 -ffast-math -ftree-vectorize" NEON_FLAGS="-mfpu=neon" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' log() { echo -e "${GREEN}[nam-build]${NC} $*"; } warn() { echo -e "${YELLOW}[nam-build] WARN:${NC} $*"; } err() { echo -e "${RED}[nam-build] ERROR:${NC} $*" >&2; exit 1; } INSTALL=false CLEAN=false BUILD_TYPE="Release" while [[ $# -gt 0 ]]; do case "$1" in --install) INSTALL=true; shift ;; --clean) CLEAN=true; shift ;; --debug) BUILD_TYPE="Debug"; shift ;; *) echo "Unknown flag: $1"; exit 1 ;; esac done # ── Check platform ───────────────────────────────────── ARCH=$(uname -m) if [[ "$ARCH" != "aarch64" ]] && [[ "$ARCH" != "armv7l" ]]; then warn "Not running on ARM (detected $ARCH). Cross-compilation not supported." warn "Run this script directly on the Raspberry Pi 4B." fi # ── Install build dependencies ───────────────────────── log "Installing NAM build dependencies..." sudo apt update -qq sudo apt install -y \ build-essential \ cmake \ pkg-config \ g++ \ git \ libeigen3-dev \ lv2-dev \ liblilv-dev \ libserd-dev \ libsord-dev \ libsratom-dev # Check for Eigen3 (critical) if ! pkg-config --modversion eigen3 2>/dev/null && ! dpkg -l | grep -q libeigen3-dev; then err "Eigen3 not found. Install with: sudo apt install libeigen3-dev" fi log "Eigen3 found: $(pkg-config --modversion eigen3 2>/dev/null || echo 'version unknown')" # ── Clone NAM-LV2 ────────────────────────────────────── if [ "$CLEAN" = true ] || [ ! -d "$NAM_DIR" ]; then log "Cloning NAM-LV2 repository (with submodules)..." rm -rf "$NAM_DIR" git clone --recursive -j4 "$NAM_REPO" "$NAM_DIR" fi cd "$NAM_DIR" # ── Check submodule status ───────────────────────────── if [ ! -f "NeuralAudio/CMakeLists.txt" ]; then log "Initializing submodules..." git submodule update --init --recursive fi # ── Create build directory ───────────────────────────── mkdir -p build cd build # ── Configure CMake with ARM Cortex-A72 optimizations ── log "Configuring CMake (${BUILD_TYPE}, Cortex-A72 optimized)..." # NeuralAudio performance options for ARM: # USE_NATIVE_ARCH=ON → auto-detects CPU features # NEON_OPTIMIZATIONS=ON → enable NEON SIMD in RTNeural # RTNEURAL_NEON=ON → use NEON backend in RTNeural # # For maximum RPi4B performance: # LTO=ON → link-time optimization # SMARTCACHING=ON → cache layer activations to avoid recomputation cmake .. \ -DCMAKE_BUILD_TYPE="$BUILD_TYPE" \ -DCMAKE_CXX_FLAGS="$A72_FLAGS" \ -DCMAKE_C_FLAGS="$A72_FLAGS" \ -DUSE_NATIVE_ARCH=ON \ -DLTO=ON \ 2>&1 | tee /tmp/nam-configure.log # ── Build ────────────────────────────────────────────── log "Building NAM LV2 (${JOBS} parallel jobs)..." make -j"$JOBS" 2>&1 | tee /tmp/nam-build.log # ── Check build results ──────────────────────────────── if [ -d "neural_amp_modeler.lv2" ]; then log "✓ NAM LV2 bundle built successfully." LV2_SIZE=$(du -sh neural_amp_modeler.lv2 | cut -f1) log " Plugin size: $LV2_SIZE" if [ -f "neural_amp_modeler.lv2/neural_amp_modeler.so" ]; then file neural_amp_modeler.lv2/neural_amp_modeler.so fi else err "NAM LV2 bundle not found. Check /tmp/nam-build.log" fi # ── Install (optional) ───────────────────────────────── if [ "$INSTALL" = true ]; then log "Installing NAM LV2 to system..." LV2_DIR="/usr/lib/lv2" # Respect LIB_INSTALL_DIR if set if [ -n "${LIB_INSTALL_DIR:-}" ]; then LV2_DIR="$LIB_INSTALL_DIR" fi sudo mkdir -p "$LV2_DIR" sudo cp -r neural_amp_modeler.lv2 "$LV2_DIR/" log "✓ Installed to $LV2_DIR/neural_amp_modeler.lv2" # Verify with lv2ls if command -v lv2ls >/dev/null 2>&1; then echo "" log "LV2 plugins containing 'neural':" lv2ls 2>/dev/null | grep -i neural || warn "NAM not showing in lv2ls yet. Run: lv2ls" fi fi # ── Model download guidance ──────────────────────────── # Check if lv2_validate is available (from lilv-utils) log "" log "╔══════════════════════════════════════════════╗" log "║ NAM LV2 Build Summary ║" log "╚══════════════════════════════════════════════╝" log "" log " Bundle: neural_amp_modeler.lv2" log " Platform: $ARCH (Cortex-A72 optimized)" log " Build type: $BUILD_TYPE" log " Installed: $([ "$INSTALL" = true ] && echo "yes" || echo "no (use --install)")" log "" log " Model recommendations for RPi4B:" log " • Use 'nano' or 'feather' sized models" log " • Standard models are too CPU-heavy" log " • Browse: https://www.tone3000.com/search?sizes=feather" log "" log " Using NAM in Carla:" log " 1. Start Carla: carla ./config/carla-default.carxp" log " 2. Add Plugin → LV2 → Neural Amp Modeler" log " 3. Set model path via atom:Path parameter" log " 4. Place an IR loader AFTER NAM for cab sim" log "" log " Download example models:" log " mkdir -p ~/nam-models" log " # Download feather models from Tone3000 and place here" log ""