# AGENTS.md — Wavetable Synth Project Context ## Project Overview Wavetable is a polyphonic wavetable synthesizer audio plugin (VST3, AU, CLAP, LV2, Standalone) built with **JUCE** and the **Gin** framework. It's developed by SocaLabs (Roland Rabien). - **Version**: 1.0.34 (tracked in `VERSION` file) - **Language**: C++20 - **Build system**: CMake (minimum 3.24) - **Bundle ID**: `com.socalabs.wavetable` ## Repository Structure ``` Wavetable/ ├── CMakeLists.txt # Main build config ├── CMakePresets.json # Presets: xcode (macOS), vs (Windows), ninja-gcc (Linux) ├── VERSION # Current version string ├── Changelist.txt # Version history (used by release.sh) ├── release.sh # GitHub release script ├── tag.sh # Tags current VERSION and pushes ├── plugin/ │ ├── Source/ │ │ ├── PluginProcessor.h/cpp # Main processor (WavetableAudioProcessor) │ │ ├── PluginEditor.h/cpp # Editor (WavetableAudioProcessorEditor) │ │ ├── Editor.h/cpp # Main UI layout component │ │ ├── Panels.h # All section UI boxes (OscillatorBox, FilterBox, etc.) │ │ ├── WavetableVoice.h/cpp # Synth voice │ │ ├── Cfg.h # Compile-time constants │ │ └── FX/ # Custom FX (DeRez2, FireAmp, GrindAmp) │ └── Resources/ │ ├── layout.json # UI layout │ ├── Presets/ # Factory presets (XML, per-category subdirs) │ ├── Wavetables/ # Factory wavetables │ └── WavetablesFLAC/ # FLAC-compressed wavetables ├── modules/ # Git submodules │ ├── gin/ # Gin framework (core dependency) │ ├── juce/ # JUCE framework │ ├── clap-juce-extensions/ # CLAP format support │ ├── MTS-ESP/ # Microtuning support │ ├── plugin_sdk/ # VST2 SDK (optional) │ └── melatonin_inspector/ # Debug UI inspector ├── installer/ │ ├── build.sh # Full installer build script (macOS/Linux/Windows) │ ├── macOS/ # macOS pkg installer resources │ └── win/ # Windows Inno Setup installer └── .github/workflows/ ├── build.yaml # CI build on push └── release.yaml # Release build on tag push ``` ## Key Architecture ### Plugin Core - **`WavetableAudioProcessor`** (`plugin/Source/PluginProcessor.h`) — inherits `gin::Processor` + `gin::Synthesiser` - **`WavetableAudioProcessorEditor`** (`plugin/Source/PluginEditor.h`) — inherits `gin::ProcessorEditor` - **`Editor`** (`plugin/Source/Editor.h`) — the main content component with all section boxes ### UI Panels (Panels.h) All section UIs are `gin::ParamBox` subclasses: - `OscillatorBox` — wavetable osc with navigation buttons in header - `SubBox`, `NoiseBox` — simple boxes - `FilterBox` — complex with ADSR, routing buttons - `ADSRBox` — envelope display + knobs - `LFOBox`, `ENVBox` — tabbed (addHeader with HeaderButton) - `StepBox` — step sequencer - `ModBox`, `MatrixBox` — modulation source/matrix tabs - `GlobalBox` — global controls - FX boxes: `GateBox`, `ChorusBox`, `DistortBox`, `DelayBox`, `ReverbBox` ### Gin Framework (submodule) - **`gin::ParamBox`** (`modules/gin/.../gin_parambox.h`) — base for all section boxes - **`gin::ParamHeader`** — header bar with gradient background + label text - **`gin::CopperLookAndFeel`** (`modules/gin/.../gin_copperlookandfeel.cpp`) — default LookAndFeel - **Colors**: title1/title2 (header gradient), matte1/matte2 (body gradient), accent (copper) - **`gradientRect()`** helper — vertical linear gradient fill ### Custom LookAndFeel The project uses `gin::CopperLookAndFeel` by default (set in `gin_processor.cpp`). Colors can be overridden per-component via `findColour()`. **Important**: `ParamHeader::paint()` is **private** and has hardcoded font size and gradient colors. To customize header appearance, you must edit `gin_parambox.h` directly in the submodule. This is a local modification that will be overwritten on `git submodule update`. ## Build Instructions ### Quick Build (macOS) ```bash git clone --recursive https://github.com/FigBug/Wavetable.git cd Wavetable cmake --preset xcode cmake --build --preset xcode --config Release # Output: Builds/xcode/Wavetable_artefacts/Release/ ``` ### CMake Presets - **macOS**: `xcode` — generates Xcode project, builds universal (arm64 + x86_64) - **Windows**: `vs` — generates Visual Studio solution - **Linux**: `ninja-gcc` — generates Ninja build files with GCC ### Build Outputs (macOS) ``` Builds/xcode/Wavetable_artefacts/Release/ ├── Standalone/Wavetable.app ├── VST/Wavetable.vst ├── VST3/Wavetable.vst3 ├── AU/Wavetable.component └── CLAP/Wavetable.clap ``` ### Installer (macOS) ```bash ./installer/build.sh # Output: installer/macOS/bin/Wavetable.pkg # Requires Xcode CLI tools; signing/notarization optional (needs secrets) ``` The installer pkg installs: - VST → `/Library/Audio/Plug-Ins/VST/` - VST3 → `/Library/Audio/Plug-Ins/VST3/` - AU → `/Library/Audio/Plug-Ins/Components/` - CLAP → `/Library/Audio/Plug-Ins/CLAP/` - Factory wavetables + presets → `/Library/Audio/Presets/SocaLabs/Wavetable/` ### Manual Plugin Install (macOS, no installer) Copy built bundles manually: ```bash cp -R Builds/xcode/Wavetable_artefacts/Release/AU/Wavetable.component ~/Library/Audio/Plug-Ins/Components/ cp -R Builds/xcode/Wavetable_artefacts/Release/VST3/Wavetable.vst3 ~/Library/Audio/Plug-Ins/VST3/ cp -R Builds/xcode/Wavetable_artefacts/Release/CLAP/Wavetable.clap ~/Library/Audio/Plug-Ins/CLAP/ ``` Factory resources: ```bash mkdir -p ~/Library/Audio/Presets/SocaLabs/Wavetable cp -R plugin/Resources/WavetablesFLAC ~/Library/Audio/Presets/SocaLabs/Wavetable/Wavetables # Presets (flatten subdirs): find plugin/Resources/Presets -name "*.xml" -exec cp {} ~/Library/Audio/Presets/SocaLabs/Wavetable/ \; ``` ## Release Process 1. Update `VERSION` file 2. Add changelog entry in `Changelist.txt` under the version 3. Commit and push 4. Run `./tag.sh` — tags `v{VERSION}` and pushes the tag 5. GitHub Actions (`release.yaml`) builds installers for all platforms 6. `release.sh` creates a GitHub release and uploads to socalabs.com ## Submodule Notes The Gin submodule is pinned at commit `414fecf`. Local modifications to Gin files (e.g., `gin_parambox.h`, `gin_copperlookandfeel.cpp`) are intentional and should not be committed to the submodule. Be aware that `git submodule update` will overwrite these changes. ## Coding Conventions - Standard JUCE/Gin code style (camelCase methods, PascalCase classes) - `gin::Parameter::Ptr` for all synth parameters - `gin::ParamBox` subclassed for each UI section - Parameters defined as nested structs in `WavetableAudioProcessor` (e.g., `OSCParams`, `FilterParams`) - No comments unless explicitly requested - Build with `-ffast-math -fno-finite-math-only` on macOS/Release ## Common Tasks ### Changing header label appearance Edit `modules/gin/modules/gin_plugin/components/gin_parambox.h` → `ParamHeader::paint()`. The font and gradient are hardcoded there. ### Changing header gradient colors Edit `modules/gin/modules/gin_plugin/lookandfeel/gin_copperlookandfeel.cpp` → `title1ColourId` / `title2ColourId` in constructor. ### Adding new parameters 1. Add to the relevant Params struct in `PluginProcessor.h` 2. Initialize in `PluginProcessor.cpp` (`setup()` method) 3. Add UI control in the appropriate Box class in `Panels.h` ### Changing UI layout Edit `plugin/Resources/layout.json` — positions are grid-based (56px columns, 70px rows, 23px header height).