mirror of
https://codeberg.org/armin/wavetable.git
synced 2026-09-01 14:00:47 +02:00
Compare commits
17 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0399fa39dc | ||
|
|
3001ed8271 | ||
|
|
5797f8b8b7 | ||
|
|
ba6e7b59ca | ||
|
|
e34c58fc8f | ||
|
|
62f2788c8a | ||
|
|
8292f10db2 | ||
|
|
afa366e9e1 | ||
|
|
a681b2e332 | ||
|
|
539fd80370 | ||
|
|
05992e760f | ||
|
|
98d290770b | ||
|
|
155c933711 | ||
|
|
e4f7246f45 | ||
|
|
8c45136be6 | ||
|
|
f822ff7659 | ||
|
|
be05233662 |
27 changed files with 780 additions and 64 deletions
1
.github/workflows/release.yaml
vendored
1
.github/workflows/release.yaml
vendored
|
|
@ -79,3 +79,4 @@ jobs:
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
APIKEY: ${{ secrets.APIKEY }}
|
APIKEY: ${{ secrets.APIKEY }}
|
||||||
|
SYMBOL_API_KEY: ${{ secrets.SYMBOL_API_KEY }}
|
||||||
|
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -39,3 +39,7 @@ Installer/win/bin
|
||||||
Installer/_flat_presets
|
Installer/_flat_presets
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.claude
|
.claude
|
||||||
|
|
||||||
|
# modules
|
||||||
|
modules
|
||||||
|
|
||||||
|
|
|
||||||
174
AGENTS.md
Normal file
174
AGENTS.md
Normal file
|
|
@ -0,0 +1,174 @@
|
||||||
|
# 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).
|
||||||
|
|
@ -213,6 +213,7 @@ if (APPLE)
|
||||||
XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO
|
XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO
|
||||||
#XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] YES
|
#XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] YES
|
||||||
XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES"
|
XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES"
|
||||||
|
XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] "dwarf-with-dsym"
|
||||||
)
|
)
|
||||||
if (NOT t STREQUAL "All")
|
if (NOT t STREQUAL "All")
|
||||||
target_compile_options(${tgt} PRIVATE
|
target_compile_options(${tgt} PRIVATE
|
||||||
|
|
@ -237,6 +238,22 @@ if (WIN32)
|
||||||
set_target_properties(${tgt} PROPERTIES LINK_FLAGS "/ignore:4099")
|
set_target_properties(${tgt} PROPERTIES LINK_FLAGS "/ignore:4099")
|
||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
# Generate debug symbols (PDBs) for Release builds so crashes can be symbolicated.
|
||||||
|
# /Zi emits full debug info; /DEBUG produces the .pdb; /OPT:REF and /OPT:ICF
|
||||||
|
# restore the size optimisations that /DEBUG otherwise disables.
|
||||||
|
foreach(t ${FORMATS} "CLAP" "")
|
||||||
|
set(tgt ${CMAKE_PROJECT_NAME})
|
||||||
|
if (NOT t STREQUAL "")
|
||||||
|
set(tgt ${tgt}_${t})
|
||||||
|
endif()
|
||||||
|
if (TARGET ${tgt})
|
||||||
|
target_compile_options(${tgt} PRIVATE "$<$<CONFIG:Release>:/Zi>")
|
||||||
|
target_link_options(${tgt} PRIVATE "$<$<CONFIG:Release>:/DEBUG>")
|
||||||
|
target_link_options(${tgt} PRIVATE "$<$<CONFIG:Release>:/OPT:REF>")
|
||||||
|
target_link_options(${tgt} PRIVATE "$<$<CONFIG:Release>:/OPT:ICF>")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,16 @@
|
||||||
|
1.0.34:
|
||||||
|
- Crash reporting improvements
|
||||||
|
|
||||||
|
1.0.33:
|
||||||
|
- Added crash reporting
|
||||||
|
|
||||||
|
1.0.32:
|
||||||
|
- Fixed fix wavetable menus
|
||||||
|
- Fixed deadlock
|
||||||
|
|
||||||
|
1.0.31:
|
||||||
|
- Fixed ADSR attack when time is 0
|
||||||
|
|
||||||
1.0.30:
|
1.0.30:
|
||||||
- VST2 install path
|
- VST2 install path
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,35 @@ fi
|
||||||
|
|
||||||
VERSION=$(cat "$PROJECT_ROOT/VERSION")
|
VERSION=$(cat "$PROJECT_ROOT/VERSION")
|
||||||
|
|
||||||
|
#
|
||||||
|
# Crash reporting: bundle the latest CrashReporter app + this plugin's
|
||||||
|
# registration JSON. Debug symbols are zipped into bin/ and uploaded later by
|
||||||
|
# the release job (release.sh), never from this build.
|
||||||
|
# The CrashReporter download is a public distribution channel (no key needed).
|
||||||
|
#
|
||||||
|
CRASH_BASE="https://crashreports.rabiensoftware.com"
|
||||||
|
|
||||||
|
# Native (non-MSYS) curl on Windows can't read Git-Bash paths like /d/a/...,
|
||||||
|
# so translate to a Windows path there. No-op on macOS/Linux.
|
||||||
|
curl_path () {
|
||||||
|
if command -v cygpath >/dev/null 2>&1; then cygpath -m "$1"; else printf '%s' "$1"; fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download the latest CrashReporter build for a platform. Non-fatal: if none is
|
||||||
|
# published yet we still ship the registration JSON so crashes register.
|
||||||
|
fetch_reporter () { # $1 platform, $2 output file
|
||||||
|
if curl -fsSL "$CRASH_BASE/reporter/latest/?platform=$1" -o "$(curl_path "$2")"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "WARNING: could not fetch CrashReporter for $1 (none published yet?)"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
#
|
#
|
||||||
# Reset staging
|
# Reset staging
|
||||||
#
|
#
|
||||||
rm -Rf "$PROJECT_ROOT/Installer/$PLATFORM/bin"
|
rm -Rf "$PROJECT_ROOT/installer/$PLATFORM/bin"
|
||||||
mkdir -p "$PROJECT_ROOT/Installer/$PLATFORM/bin"
|
mkdir -p "$PROJECT_ROOT/installer/$PLATFORM/bin"
|
||||||
rm -Rf "$PROJECT_ROOT/bin"
|
rm -Rf "$PROJECT_ROOT/bin"
|
||||||
mkdir -p "$PROJECT_ROOT/bin"
|
mkdir -p "$PROJECT_ROOT/bin"
|
||||||
|
|
||||||
|
|
@ -34,7 +58,7 @@ mkdir -p "$PROJECT_ROOT/bin"
|
||||||
# gin's loadDirectory() doesn't recurse, and the legacy BinaryData flow stored
|
# gin's loadDirectory() doesn't recurse, and the legacy BinaryData flow stored
|
||||||
# presets flat in the user directory — keeping flat matches what users see.
|
# presets flat in the user directory — keeping flat matches what users see.
|
||||||
#
|
#
|
||||||
FLAT_PRESETS="$PROJECT_ROOT/Installer/_flat_presets"
|
FLAT_PRESETS="$PROJECT_ROOT/installer/_flat_presets"
|
||||||
rm -Rf "$FLAT_PRESETS"
|
rm -Rf "$FLAT_PRESETS"
|
||||||
mkdir -p "$FLAT_PRESETS"
|
mkdir -p "$FLAT_PRESETS"
|
||||||
find "$PROJECT_ROOT/plugin/Resources/Presets" -name "*.xml" -type f -exec cp {} "$FLAT_PRESETS/" \;
|
find "$PROJECT_ROOT/plugin/Resources/Presets" -name "*.xml" -type f -exec cp {} "$FLAT_PRESETS/" \;
|
||||||
|
|
@ -77,8 +101,8 @@ if [ "$PLATFORM" = "macOS" ]; then
|
||||||
cmake --preset xcode
|
cmake --preset xcode
|
||||||
cmake --build --preset xcode --config Release
|
cmake --build --preset xcode --config Release
|
||||||
|
|
||||||
STAGE="$PROJECT_ROOT/Installer/macOS/bin/stage"
|
STAGE="$PROJECT_ROOT/installer/macOS/bin/stage"
|
||||||
PKG_DIR="$PROJECT_ROOT/Installer/macOS/bin/pkgs"
|
PKG_DIR="$PROJECT_ROOT/installer/macOS/bin/pkgs"
|
||||||
rm -Rf "$STAGE" "$PKG_DIR"
|
rm -Rf "$STAGE" "$PKG_DIR"
|
||||||
mkdir -p "$STAGE/vst" "$STAGE/vst3" "$STAGE/au" "$STAGE/clap"
|
mkdir -p "$STAGE/vst" "$STAGE/vst3" "$STAGE/au" "$STAGE/clap"
|
||||||
mkdir -p "$STAGE/resources/Library/Audio/Presets/$VENDOR/$PLUGIN"
|
mkdir -p "$STAGE/resources/Library/Audio/Presets/$VENDOR/$PLUGIN"
|
||||||
|
|
@ -95,6 +119,15 @@ if [ "$PLATFORM" = "macOS" ]; then
|
||||||
cp -R "$PROJECT_ROOT/plugin/Resources/WavetablesFLAC" "$STAGE/resources/Library/Audio/Presets/$VENDOR/$PLUGIN/Wavetables"
|
cp -R "$PROJECT_ROOT/plugin/Resources/WavetablesFLAC" "$STAGE/resources/Library/Audio/Presets/$VENDOR/$PLUGIN/Wavetables"
|
||||||
find "$STAGE/resources" -name ".DS_Store" -delete
|
find "$STAGE/resources" -name ".DS_Store" -delete
|
||||||
|
|
||||||
|
# Strip symbols from the shipped binaries so end-user crash logs are NOT
|
||||||
|
# symbolicated locally by macOS — the server symbolicates them from the dSYMs
|
||||||
|
# (built below from the unstripped products in $ART_DIR). strip preserves the
|
||||||
|
# Mach-O UUID, so the dSYM still matches. Before codesign.
|
||||||
|
strip -x "$STAGE/vst/$PLUGIN.vst/Contents/MacOS/$PLUGIN"
|
||||||
|
strip -x "$STAGE/vst3/$PLUGIN.vst3/Contents/MacOS/$PLUGIN"
|
||||||
|
strip -x "$STAGE/au/$PLUGIN.component/Contents/MacOS/$PLUGIN"
|
||||||
|
strip -x "$STAGE/clap/$PLUGIN.clap/Contents/MacOS/$PLUGIN"
|
||||||
|
|
||||||
if [ -n "${APPLICATION:-}" ]; then
|
if [ -n "${APPLICATION:-}" ]; then
|
||||||
codesign -s "$DEV_APP_ID" --options=runtime --timestamp --force -v "$STAGE/vst/$PLUGIN.vst"
|
codesign -s "$DEV_APP_ID" --options=runtime --timestamp --force -v "$STAGE/vst/$PLUGIN.vst"
|
||||||
codesign -s "$DEV_APP_ID" --options=runtime --timestamp --force -v "$STAGE/vst3/$PLUGIN.vst3"
|
codesign -s "$DEV_APP_ID" --options=runtime --timestamp --force -v "$STAGE/vst3/$PLUGIN.vst3"
|
||||||
|
|
@ -133,16 +166,48 @@ if [ "$PLATFORM" = "macOS" ]; then
|
||||||
--install-location "/" \
|
--install-location "/" \
|
||||||
--identifier "${BUNDLE_BASE}.resources.pkg" \
|
--identifier "${BUNDLE_BASE}.resources.pkg" \
|
||||||
--version "$VERSION" \
|
--version "$VERSION" \
|
||||||
--scripts "$PROJECT_ROOT/Installer/macOS/scripts" \
|
--scripts "$PROJECT_ROOT/installer/macOS/scripts" \
|
||||||
"$PKG_DIR/resources.pkg"
|
"$PKG_DIR/resources.pkg"
|
||||||
|
|
||||||
|
# CrashReporter component: latest signed CrashReporter.app + this plugin's
|
||||||
|
# registration JSON. Staged under .incoming and promoted by the postinstall
|
||||||
|
# only if strictly newer (shared component, never downgraded).
|
||||||
|
REP_STAGE="$PROJECT_ROOT/installer/macOS/bin/reporter"
|
||||||
|
REP_ROOT="$REP_STAGE/Library/Application Support/Rabien Software/Crash Reporter"
|
||||||
|
rm -Rf "$REP_STAGE"
|
||||||
|
mkdir -p "$REP_ROOT/Plugins" "$REP_ROOT/.incoming"
|
||||||
|
if fetch_reporter mac "$REP_STAGE/CrashReporter_Mac.zip"; then
|
||||||
|
( cd "$REP_STAGE" && unzip -qo CrashReporter_Mac.zip && rm CrashReporter_Mac.zip )
|
||||||
|
mv "$REP_STAGE/CrashReporter.app" "$REP_ROOT/.incoming/"
|
||||||
|
fi
|
||||||
|
cp "$PROJECT_ROOT/installer/crashreporter.json" "$REP_ROOT/Plugins/wavetable.json"
|
||||||
|
find "$REP_STAGE" -name ".DS_Store" -delete
|
||||||
|
|
||||||
|
if [ -n "${APPLICATION:-}" ] && [ -d "$REP_ROOT/.incoming/CrashReporter.app" ]; then
|
||||||
|
codesign -s "$DEV_APP_ID" --options=runtime --timestamp --force -v "$REP_ROOT/.incoming/CrashReporter.app"
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod +x "$PROJECT_ROOT/installer/macOS/reporter-scripts/postinstall"
|
||||||
|
|
||||||
|
# Disable bundle relocation so the installer installs to our staged path
|
||||||
|
# instead of redirecting to a CrashReporter.app found elsewhere via Spotlight.
|
||||||
|
COMP_PLIST="$PROJECT_ROOT/installer/macOS/bin/reporter-component.plist"
|
||||||
|
pkgbuild --analyze --root "$REP_STAGE" "$COMP_PLIST"
|
||||||
|
/usr/libexec/PlistBuddy -c "Set :0:BundleIsRelocatable false" "$COMP_PLIST" 2>/dev/null || true
|
||||||
|
|
||||||
|
pkgbuild --root "$REP_STAGE" --install-location "/" \
|
||||||
|
--identifier "${BUNDLE_BASE}.crashreporter.pkg" --version "$VERSION" \
|
||||||
|
--component-plist "$COMP_PLIST" \
|
||||||
|
--scripts "$PROJECT_ROOT/installer/macOS/reporter-scripts" \
|
||||||
|
"$PKG_DIR/reporter.pkg"
|
||||||
|
|
||||||
# productbuild — combine into one signed installer
|
# productbuild — combine into one signed installer
|
||||||
cp "$PROJECT_ROOT/Installer/EULA.rtf" "$PKG_DIR/EULA.rtf"
|
cp "$PROJECT_ROOT/installer/EULA.rtf" "$PKG_DIR/EULA.rtf"
|
||||||
cp "$PROJECT_ROOT/Installer/macOS/welcome.txt" "$PKG_DIR/welcome.txt"
|
cp "$PROJECT_ROOT/installer/macOS/welcome.txt" "$PKG_DIR/welcome.txt"
|
||||||
|
|
||||||
PKG_OUT="$PROJECT_ROOT/Installer/macOS/bin/${PLUGIN}.pkg"
|
PKG_OUT="$PROJECT_ROOT/installer/macOS/bin/${PLUGIN}.pkg"
|
||||||
|
|
||||||
productbuild --distribution "$PROJECT_ROOT/Installer/macOS/distribution.xml" \
|
productbuild --distribution "$PROJECT_ROOT/installer/macOS/distribution.xml" \
|
||||||
--package-path "$PKG_DIR" \
|
--package-path "$PKG_DIR" \
|
||||||
--resources "$PKG_DIR" \
|
--resources "$PKG_DIR" \
|
||||||
--version "$VERSION" \
|
--version "$VERSION" \
|
||||||
|
|
@ -172,7 +237,18 @@ if [ "$PLATFORM" = "macOS" ]; then
|
||||||
|
|
||||||
cp "$PKG_OUT" "$PROJECT_ROOT/bin/"
|
cp "$PKG_OUT" "$PROJECT_ROOT/bin/"
|
||||||
|
|
||||||
# Symbols zip
|
# Symbols zip. Some Xcode/CMake combos don't emit .dSYMs next to the product,
|
||||||
|
# so generate any that are missing straight from the built binaries.
|
||||||
|
for pair in "VST:$PLUGIN.vst" "VST3:$PLUGIN.vst3" "AU:$PLUGIN.component" "CLAP:$PLUGIN.clap"; do
|
||||||
|
d="${pair%%:*}"; b="${pair#*:}"
|
||||||
|
dsym="$ART_DIR/$d/$b.dSYM"
|
||||||
|
bin="$ART_DIR/$d/$b/Contents/MacOS/$PLUGIN"
|
||||||
|
if [ ! -d "$dsym" ] && [ -f "$bin" ]; then
|
||||||
|
echo "Generating dSYM for $d/$b"
|
||||||
|
dsymutil "$bin" -o "$dsym" || true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
cd "$ART_DIR"
|
cd "$ART_DIR"
|
||||||
zip -r "$PROJECT_ROOT/bin/Symbols_Mac.zip" \
|
zip -r "$PROJECT_ROOT/bin/Symbols_Mac.zip" \
|
||||||
AU/$PLUGIN.component.dSYM \
|
AU/$PLUGIN.component.dSYM \
|
||||||
|
|
@ -202,7 +278,7 @@ else
|
||||||
cmake --build --preset vs --config Release
|
cmake --build --preset vs --config Release
|
||||||
|
|
||||||
ART_DIR="$PROJECT_ROOT/Builds/vs/${PLUGIN}_artefacts/Release"
|
ART_DIR="$PROJECT_ROOT/Builds/vs/${PLUGIN}_artefacts/Release"
|
||||||
STAGE="$PROJECT_ROOT/Installer/win/bin"
|
STAGE="$PROJECT_ROOT/installer/win/bin"
|
||||||
|
|
||||||
rm -Rf "$STAGE"
|
rm -Rf "$STAGE"
|
||||||
mkdir -p "$STAGE/VST" "$STAGE/VST3" "$STAGE/CLAP"
|
mkdir -p "$STAGE/VST" "$STAGE/VST3" "$STAGE/CLAP"
|
||||||
|
|
@ -210,10 +286,18 @@ else
|
||||||
cp -R "$ART_DIR/VST3/$PLUGIN.vst3" "$STAGE/VST3/"
|
cp -R "$ART_DIR/VST3/$PLUGIN.vst3" "$STAGE/VST3/"
|
||||||
cp -R "$ART_DIR/CLAP/$PLUGIN.clap" "$STAGE/CLAP/"
|
cp -R "$ART_DIR/CLAP/$PLUGIN.clap" "$STAGE/CLAP/"
|
||||||
|
|
||||||
|
# CrashReporter: latest signed build + this plugin's registration JSON.
|
||||||
|
REP_DIR="$STAGE/CrashReporter"
|
||||||
|
rm -Rf "$REP_DIR"; mkdir -p "$REP_DIR"
|
||||||
|
if fetch_reporter win "$REP_DIR/CrashReporter_Win.zip"; then
|
||||||
|
( cd "$REP_DIR" && 7z x -y CrashReporter_Win.zip >/dev/null && rm CrashReporter_Win.zip )
|
||||||
|
fi
|
||||||
|
cp "$PROJECT_ROOT/installer/crashreporter.json" "$REP_DIR/wavetable.json"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Sign binaries via Microsoft Trusted Signing.
|
# Sign binaries via Microsoft Trusted Signing.
|
||||||
# Required env: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET.
|
# Required env: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET.
|
||||||
# Cert is referenced via Installer/win/metadata.json.
|
# Cert is referenced via installer/win/metadata.json.
|
||||||
#
|
#
|
||||||
uuid_re='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
uuid_re='^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'
|
||||||
WIN_SIGN=0
|
WIN_SIGN=0
|
||||||
|
|
@ -241,7 +325,7 @@ else
|
||||||
nuget install Microsoft.Trusted.Signing.Client -Version 1.0.86 \
|
nuget install Microsoft.Trusted.Signing.Client -Version 1.0.86 \
|
||||||
-OutputDirectory "$TOOLS_DIR" -ExcludeVersion -NonInteractive
|
-OutputDirectory "$TOOLS_DIR" -ExcludeVersion -NonInteractive
|
||||||
DLIB="$TOOLS_DIR/Microsoft.Trusted.Signing.Client/bin/x64/Azure.CodeSigning.Dlib.dll"
|
DLIB="$TOOLS_DIR/Microsoft.Trusted.Signing.Client/bin/x64/Azure.CodeSigning.Dlib.dll"
|
||||||
METADATA="$PROJECT_ROOT/Installer/win/metadata.json"
|
METADATA="$PROJECT_ROOT/installer/win/metadata.json"
|
||||||
|
|
||||||
sign_file () {
|
sign_file () {
|
||||||
"$SIGNTOOL" sign -v -fd SHA256 \
|
"$SIGNTOOL" sign -v -fd SHA256 \
|
||||||
|
|
@ -257,14 +341,14 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build installer .exe
|
# Build installer .exe
|
||||||
cd "$PROJECT_ROOT/Installer/win"
|
cd "$PROJECT_ROOT/installer/win"
|
||||||
ISCC="/c/Program Files (x86)/Inno Setup 6/ISCC.exe"
|
ISCC="/c/Program Files (x86)/Inno Setup 6/ISCC.exe"
|
||||||
if [ ! -f "$ISCC" ]; then
|
if [ ! -f "$ISCC" ]; then
|
||||||
ISCC="/c/Program Files/Inno Setup 6/ISCC.exe"
|
ISCC="/c/Program Files/Inno Setup 6/ISCC.exe"
|
||||||
fi
|
fi
|
||||||
"$ISCC" "$PROJECT_ROOT/Installer/win/${PLUGIN}.iss"
|
"$ISCC" "$PROJECT_ROOT/installer/win/${PLUGIN}.iss"
|
||||||
|
|
||||||
EXE_OUT="$PROJECT_ROOT/Installer/win/bin/${PLUGIN}.exe"
|
EXE_OUT="$PROJECT_ROOT/installer/win/bin/${PLUGIN}.exe"
|
||||||
|
|
||||||
# Sign installer
|
# Sign installer
|
||||||
if [ "$WIN_SIGN" = "1" ]; then
|
if [ "$WIN_SIGN" = "1" ]; then
|
||||||
|
|
@ -272,4 +356,12 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp "$EXE_OUT" "$PROJECT_ROOT/bin/"
|
cp "$EXE_OUT" "$PROJECT_ROOT/bin/"
|
||||||
|
|
||||||
|
# Symbols zip — PDBs for crash symbolication.
|
||||||
|
SYM_DIR="$STAGE/symbols"
|
||||||
|
rm -Rf "$SYM_DIR"; mkdir -p "$SYM_DIR/VST" "$SYM_DIR/VST3" "$SYM_DIR/CLAP"
|
||||||
|
cp "$ART_DIR/VST/$PLUGIN.pdb" "$SYM_DIR/VST/" 2>/dev/null || true
|
||||||
|
cp "$ART_DIR/VST3/$PLUGIN.pdb" "$SYM_DIR/VST3/" 2>/dev/null || true
|
||||||
|
cp "$ART_DIR/CLAP/$PLUGIN.pdb" "$SYM_DIR/CLAP/" 2>/dev/null || true
|
||||||
|
( cd "$SYM_DIR" && 7z a "$PROJECT_ROOT/bin/Symbols_Win.zip" VST VST3 CLAP )
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
6
Installer/crashreporter.json
Normal file
6
Installer/crashreporter.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"name": "Wavetable",
|
||||||
|
"pluginID": "com.socalabs.wavetable",
|
||||||
|
"crashUrl": "https://crashreports.rabiensoftware.com/post/",
|
||||||
|
"apiKey": "da8b3bc4e5fcb9b5ba8b5960d0ef805b62d4097b956082c87fcf82cab40cc2c8"
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
<line choice="com.socalabs.wavetable.au"/>
|
<line choice="com.socalabs.wavetable.au"/>
|
||||||
<line choice="com.socalabs.wavetable.clap"/>
|
<line choice="com.socalabs.wavetable.clap"/>
|
||||||
<line choice="com.socalabs.wavetable.resources"/>
|
<line choice="com.socalabs.wavetable.resources"/>
|
||||||
|
<line choice="com.socalabs.wavetable.crashreporter"/>
|
||||||
</choices-outline>
|
</choices-outline>
|
||||||
|
|
||||||
<choice id="com.socalabs.wavetable.vst"
|
<choice id="com.socalabs.wavetable.vst"
|
||||||
|
|
@ -52,9 +53,19 @@
|
||||||
<pkg-ref id="com.socalabs.wavetable.resources.pkg"/>
|
<pkg-ref id="com.socalabs.wavetable.resources.pkg"/>
|
||||||
</choice>
|
</choice>
|
||||||
|
|
||||||
|
<choice id="com.socalabs.wavetable.crashreporter"
|
||||||
|
title="Crash Reporter"
|
||||||
|
description="Install the shared crash reporter that sends crash reports to SocaLabs. Recommended; only updated if newer."
|
||||||
|
visible="true"
|
||||||
|
enabled="true"
|
||||||
|
selected="true">
|
||||||
|
<pkg-ref id="com.socalabs.wavetable.crashreporter.pkg"/>
|
||||||
|
</choice>
|
||||||
|
|
||||||
<pkg-ref id="com.socalabs.wavetable.vst.pkg" version="0">vst.pkg</pkg-ref>
|
<pkg-ref id="com.socalabs.wavetable.vst.pkg" version="0">vst.pkg</pkg-ref>
|
||||||
<pkg-ref id="com.socalabs.wavetable.vst3.pkg" version="0">vst3.pkg</pkg-ref>
|
<pkg-ref id="com.socalabs.wavetable.vst3.pkg" version="0">vst3.pkg</pkg-ref>
|
||||||
<pkg-ref id="com.socalabs.wavetable.au.pkg" version="0">au.pkg</pkg-ref>
|
<pkg-ref id="com.socalabs.wavetable.au.pkg" version="0">au.pkg</pkg-ref>
|
||||||
<pkg-ref id="com.socalabs.wavetable.clap.pkg" version="0">clap.pkg</pkg-ref>
|
<pkg-ref id="com.socalabs.wavetable.clap.pkg" version="0">clap.pkg</pkg-ref>
|
||||||
<pkg-ref id="com.socalabs.wavetable.resources.pkg" version="0">resources.pkg</pkg-ref>
|
<pkg-ref id="com.socalabs.wavetable.resources.pkg" version="0">resources.pkg</pkg-ref>
|
||||||
|
<pkg-ref id="com.socalabs.wavetable.crashreporter.pkg" version="0">reporter.pkg</pkg-ref>
|
||||||
</installer-gui-script>
|
</installer-gui-script>
|
||||||
|
|
|
||||||
38
Installer/macOS/reporter-scripts/postinstall
Executable file
38
Installer/macOS/reporter-scripts/postinstall
Executable file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# CrashReporter is a SHARED component across all SocaLabs/Rabien plugins, so we
|
||||||
|
# never downgrade it and never remove it. The pkg payload stages the incoming
|
||||||
|
# app under .incoming; here we promote it to the live location only if it is
|
||||||
|
# strictly newer than what's already installed (or nothing is installed yet).
|
||||||
|
#
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BASE="/Library/Application Support/Rabien Software/Crash Reporter"
|
||||||
|
NEW="$BASE/.incoming/CrashReporter.app"
|
||||||
|
LIVE="$BASE/CrashReporter.app"
|
||||||
|
PB="/usr/libexec/PlistBuddy"
|
||||||
|
|
||||||
|
version_of () { # $1 = .app path -> prints CFBundleShortVersionString or 0
|
||||||
|
if [ -d "$1" ]; then
|
||||||
|
"$PB" -c "Print :CFBundleShortVersionString" "$1/Contents/Info.plist" 2>/dev/null || echo 0
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -d "$NEW" ]; then
|
||||||
|
newver="$(version_of "$NEW")"
|
||||||
|
livever="$(version_of "$LIVE")"
|
||||||
|
|
||||||
|
# Promote if nothing installed, or the incoming build is strictly newer.
|
||||||
|
highest="$(printf '%s\n%s\n' "$livever" "$newver" | sort -V | tail -1)"
|
||||||
|
if [ ! -d "$LIVE" ] || { [ "$highest" = "$newver" ] && [ "$newver" != "$livever" ]; }; then
|
||||||
|
rm -rf "$LIVE"
|
||||||
|
mv "$NEW" "$LIVE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Always clear the staging area.
|
||||||
|
rm -rf "$BASE/.incoming"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
@ -56,9 +56,10 @@ Name: "vst"; Description: "VST plug-in"; Types: full cu
|
||||||
Name: "vst3"; Description: "VST3 plug-in"; Types: full custom; Flags: checkablealone
|
Name: "vst3"; Description: "VST3 plug-in"; Types: full custom; Flags: checkablealone
|
||||||
Name: "clap"; Description: "CLAP plug-in"; Types: full custom; Flags: checkablealone
|
Name: "clap"; Description: "CLAP plug-in"; Types: full custom; Flags: checkablealone
|
||||||
Name: "resources"; Description: "Factory wavetables and presets"; Types: full custom; Flags: fixed
|
Name: "resources"; Description: "Factory wavetables and presets"; Types: full custom; Flags: fixed
|
||||||
|
Name: "crashreporter"; Description: "Crash reporter (shared component, only updated if newer)"; Types: full custom; Flags: checkablealone
|
||||||
|
|
||||||
[InstallDelete]
|
[InstallDelete]
|
||||||
Type: files; Name: "{commoncf64}\VST2\Wavetable.dll"; Components: vst
|
Type: files; Name: "{commoncf64}\VST2\Wavetable.dll"; Components: vst
|
||||||
Type: filesandordirs; Name: "{commoncf64}\VST3\Wavetable.vst3"; Components: vst3
|
Type: filesandordirs; Name: "{commoncf64}\VST3\Wavetable.vst3"; Components: vst3
|
||||||
Type: files; Name: "{commoncf64}\CLAP\Wavetable.clap"; Components: clap
|
Type: files; Name: "{commoncf64}\CLAP\Wavetable.clap"; Components: clap
|
||||||
Type: filesandordirs; Name: "{commonappdata}\SocaLabs\Wavetable\Presets"; Components: resources
|
Type: filesandordirs; Name: "{commonappdata}\SocaLabs\Wavetable\Presets"; Components: resources
|
||||||
|
|
@ -66,11 +67,18 @@ Type: filesandordirs; Name: "{commonappdata}\SocaLabs\Wavetable\Wavetables";
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
; Plug-in formats
|
; Plug-in formats
|
||||||
Source: "bin\VST\Wavetable.dll"; DestDir: "{commoncf64}\VST2"; Flags: ignoreversion overwritereadonly; Components: vst
|
Source: "bin\VST\Wavetable.dll"; DestDir: "{commoncf64}\VST2"; Flags: ignoreversion overwritereadonly; Components: vst
|
||||||
Source: "bin\VST3\Wavetable.vst3\*"; DestDir: "{commoncf64}\VST3\Wavetable.vst3\"; Flags: ignoreversion overwritereadonly recursesubdirs; Components: vst3
|
Source: "bin\VST3\Wavetable.vst3\*"; DestDir: "{commoncf64}\VST3\Wavetable.vst3\"; Flags: ignoreversion overwritereadonly recursesubdirs; Components: vst3
|
||||||
Source: "bin\CLAP\Wavetable.clap"; DestDir: "{commoncf64}\CLAP"; Flags: ignoreversion overwritereadonly; Components: clap
|
Source: "bin\CLAP\Wavetable.clap"; DestDir: "{commoncf64}\CLAP"; Flags: ignoreversion overwritereadonly; Components: clap
|
||||||
|
|
||||||
; Factory content (Wavetables, Presets) → C:\ProgramData\SocaLabs\Wavetable\
|
; Factory content (Wavetables, Presets) → C:\ProgramData\SocaLabs\Wavetable\
|
||||||
; Presets are flattened by Installer/build.sh into Installer/_flat_presets/.
|
; Presets are flattened by installer/build.sh into installer/_flat_presets/.
|
||||||
Source: "..\_flat_presets\*.xml"; DestDir: "{commonappdata}\SocaLabs\Wavetable\Presets\"; Flags: ignoreversion; Components: resources
|
Source: "..\_flat_presets\*.xml"; DestDir: "{commonappdata}\SocaLabs\Wavetable\Presets\"; Flags: ignoreversion; Components: resources
|
||||||
Source: "..\..\plugin\Resources\WavetablesFLAC\*.wt2048"; DestDir: "{commonappdata}\SocaLabs\Wavetable\Wavetables\"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: resources
|
Source: "..\..\plugin\Resources\WavetablesFLAC\*.wt2048"; DestDir: "{commonappdata}\SocaLabs\Wavetable\Wavetables\"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: resources
|
||||||
|
|
||||||
|
; CrashReporter app → C:\Program Files\Rabien Software\Crash Reporter, plus this
|
||||||
|
; plugin's registration JSON → C:\ProgramData\Rabien Software\Crash Reporter\Plugins.
|
||||||
|
; Shared across plugins: the app is only updated if newer and never removed on
|
||||||
|
; uninstall; the registration JSON is always installed and never removed.
|
||||||
|
Source: "bin\CrashReporter\CrashReporter.exe"; DestDir: "{commonpf}\Rabien Software\Crash Reporter"; Flags: skipifsourcedoesntexist uninsneveruninstall; Components: crashreporter
|
||||||
|
Source: "bin\CrashReporter\wavetable.json"; DestDir: "{commonappdata}\Rabien Software\Crash Reporter\Plugins"; Flags: ignoreversion uninsneveruninstall
|
||||||
|
|
|
||||||
1
LICENSE
1
LICENSE
|
|
@ -27,3 +27,4 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
|
||||||
305
README.md
305
README.md
|
|
@ -1,12 +1,8 @@
|
||||||
# Wavetable
|
# Wavetable - personal fork with some modifications
|
||||||
|
|
||||||

|
A 2 oscillator wavetable synthesizer with flexible modulation options. See https://github.com/FigBug/Wavetable for the upstream code project and https://socalabs.com/synths/Wavetable/ for the product page.
|
||||||
|
|
||||||
A 2 oscillator wavetable synthesizer with flexible modulation options.
|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[Download](https://github.com/FigBug/Wavetable/releases) | [Product Page](https://socalabs.com/synths/Wavetable/)
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
@ -48,26 +44,301 @@ A 2 oscillator wavetable synthesizer with flexible modulation options.
|
||||||
- VST3
|
- VST3
|
||||||
- VST2 (requires VST2 SDK)
|
- VST2 (requires VST2 SDK)
|
||||||
- AU (macOS)
|
- AU (macOS)
|
||||||
|
- CLAP
|
||||||
- LV2
|
- LV2
|
||||||
- Standalone
|
- Standalone
|
||||||
|
|
||||||
## Building
|
## System Requirements
|
||||||
|
|
||||||
Requirements:
|
- macOS 10.13 or later
|
||||||
- CMake 3.16+
|
- Windows 10 or later
|
||||||
- C++20 compatible compiler
|
- Linux (Ubuntu 20.04 or compatible)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Building on macOS (ARM64 / Apple Silicon)
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Xcode (with Command Line Tools)
|
||||||
|
- CMake 3.24+ (`brew install cmake`)
|
||||||
|
- Git
|
||||||
|
|
||||||
|
### Clone & Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone --recursive https://github.com/FigBug/Wavetable.git
|
git clone --recursive https://github.com/FigBug/Wavetable.git
|
||||||
cd Wavetable
|
cd Wavetable
|
||||||
cmake -B build
|
|
||||||
cmake --build build --config Release
|
# Configure (generates Xcode project, universal arm64 + x86_64)
|
||||||
|
cmake --preset xcode
|
||||||
|
|
||||||
|
# Build Release
|
||||||
|
cmake --build --preset xcode --config Release
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Build products are in `Builds/xcode/Wavetable_artefacts/Release/`:
|
||||||
|
|
||||||
|
| Format | Path |
|
||||||
|
|--------|------|
|
||||||
|
| Standalone | `Standalone/Wavetable.app` |
|
||||||
|
| VST | `VST/Wavetable.vst` |
|
||||||
|
| VST3 | `VST3/Wavetable.vst3` |
|
||||||
|
| AU | `AU/Wavetable.component` |
|
||||||
|
| CLAP | `CLAP/Wavetable.clap` |
|
||||||
|
|
||||||
|
### Install via Installer (.pkg)
|
||||||
|
|
||||||
|
Build the signed/notarized installer (or unsigned for local use):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./installer/build.sh
|
||||||
|
# Output: installer/macOS/bin/Wavetable.pkg
|
||||||
|
```
|
||||||
|
|
||||||
|
Open `Wavetable.pkg` and follow the installer. It installs:
|
||||||
|
|
||||||
|
| Component | Install Location |
|
||||||
|
|-----------|-----------------|
|
||||||
|
| 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/` |
|
||||||
|
|
||||||
|
### Install Manually (no installer)
|
||||||
|
|
||||||
|
Copy the built bundles to the system plugin directories:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# AU (Logic Pro, GarageBand)
|
||||||
|
cp -R Builds/xcode/Wavetable_artefacts/Release/AU/Wavetable.component \
|
||||||
|
~/Library/Audio/Plug-Ins/Components/
|
||||||
|
|
||||||
|
# VST3 (Ableton Live, Reaper, Bitwig, etc.)
|
||||||
|
cp -R Builds/xcode/Wavetable_artefacts/Release/VST3/Wavetable.vst3 \
|
||||||
|
~/Library/Audio/Plug-Ins/VST3/
|
||||||
|
|
||||||
|
# CLAP (Ableton Live 12+, Bitwig, Reaper)
|
||||||
|
cp -R Builds/xcode/Wavetable_artefacts/Release/CLAP/Wavetable.clap \
|
||||||
|
~/Library/Audio/Plug-Ins/CLAP/
|
||||||
|
|
||||||
|
# VST (legacy)
|
||||||
|
cp -R Builds/xcode/Wavetable_artefacts/Release/VST/Wavetable.vst \
|
||||||
|
~/Library/Audio/Plug-Ins/VST/
|
||||||
|
```
|
||||||
|
|
||||||
|
Install factory wavetables and presets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p ~/Library/Audio/Presets/SocaLabs/Wavetable
|
||||||
|
cp -R plugin/Resources/WavetablesFLAC \
|
||||||
|
~/Library/Audio/Presets/SocaLabs/Wavetable/Wavetables
|
||||||
|
|
||||||
|
# Presets must be flattened (subdirectories are not scanned by the plugin)
|
||||||
|
find plugin/Resources/Presets -name "*.xml" -exec \
|
||||||
|
cp {} ~/Library/Audio/Presets/SocaLabs/Wavetable/ \;
|
||||||
|
```
|
||||||
|
|
||||||
|
After copying, rescan plugins in your DAW. For AU, you may need to log out and back in, or run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
killall -9 AudioComponentRegistrar
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Parameter Reference
|
||||||
|
|
||||||
|
### Oscillators
|
||||||
|
|
||||||
|
Two identical wavetable oscillators provide the main sound source.
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable the oscillator |
|
||||||
|
| Wavetable | - | Select from built-in wavetables or load custom WAV files |
|
||||||
|
| Tune | -36 to +36 semitones | Coarse pitch adjustment |
|
||||||
|
| Fine | -100 to +100 cents | Fine pitch adjustment |
|
||||||
|
| Level | -100 to 0 dB | Oscillator volume |
|
||||||
|
| Pos | 0-100% | Wavetable position - morphs through the wavetable frames |
|
||||||
|
| Pan | -100% to +100% | Stereo panning |
|
||||||
|
| Formant | -1.0 to +1.0 | Formant shifting for tonal variation |
|
||||||
|
| Bend | -1.0 to +1.0 | Pitch bend modulation amount |
|
||||||
|
| Voices | 1-8 | Number of unison voices |
|
||||||
|
| Detune | 0-0.5 | Pitch spread between unison voices (enabled when Voices > 1) |
|
||||||
|
| Spread | -100% to +100% | Stereo spread of unison voices (enabled when Voices > 1) |
|
||||||
|
| Retrig | On/Off | Retrigger oscillator phase on each new note |
|
||||||
|
|
||||||
|
**Tip:** Drag on the wavetable display to adjust the position in real-time.
|
||||||
|
|
||||||
|
### Sub-Oscillator
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable the sub-oscillator |
|
||||||
|
| Wave | Sine, Triangle, Saw Up, Pulse 50%, Pulse 25%, Pulse 12% | Waveform selection |
|
||||||
|
| Tune | -36 to +36 semitones | Pitch adjustment |
|
||||||
|
| Level | -100 to 0 dB | Volume |
|
||||||
|
| Pan | -100% to +100% | Stereo panning |
|
||||||
|
| Retrig | On/Off | Retrigger phase on new notes |
|
||||||
|
|
||||||
|
### Noise Generator
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable noise |
|
||||||
|
| Type | White, Pink | Noise color |
|
||||||
|
| Level | -100 to 0 dB | Volume |
|
||||||
|
| Pan | -100% to +100% | Stereo panning |
|
||||||
|
|
||||||
|
### Filter
|
||||||
|
|
||||||
|
Multi-mode filter with envelope control and key/velocity tracking.
|
||||||
|
|
||||||
|
**Filter Types:** LP 12, LP 24, HP 12, HP 24, BP 12, BP 24, NT 12, NT 24
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable the filter |
|
||||||
|
| Type | See above | Filter type selection |
|
||||||
|
| Frequency | 20 Hz - 20 kHz | Cutoff frequency |
|
||||||
|
| Resonance | 0-100% | Filter resonance/Q |
|
||||||
|
| Key | 0-100% | Keyboard tracking amount |
|
||||||
|
| Velocity | 0-100% | Velocity to filter frequency modulation |
|
||||||
|
| Amount | -1.0 to +1.0 | Filter envelope modulation depth |
|
||||||
|
|
||||||
|
**Filter Envelope:**
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Attack | 0-60 seconds | Attack time |
|
||||||
|
| Decay | 0-60 seconds | Decay time |
|
||||||
|
| Sustain | 0-100% | Sustain level |
|
||||||
|
| Release | 0-60 seconds | Release time |
|
||||||
|
| Retrig | On/Off | Retrigger envelope on new notes |
|
||||||
|
|
||||||
|
**Filter Routing:** Use the routing buttons (WT1, WT2, Sub, Noise) to select which sound sources are processed by the filter.
|
||||||
|
|
||||||
|
### Amplitude Envelope
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Attack | 0-60 seconds | Attack time |
|
||||||
|
| Decay | 0-60 seconds | Decay time |
|
||||||
|
| Sustain | 0-100% | Sustain level |
|
||||||
|
| Release | 0-60 seconds | Release time |
|
||||||
|
| Velocity | 0-100% | Velocity sensitivity |
|
||||||
|
| Retrig | On/Off | Retrigger on new notes (mono mode with glide only) |
|
||||||
|
|
||||||
|
### LFOs
|
||||||
|
|
||||||
|
Three independent LFOs with multiple waveforms.
|
||||||
|
|
||||||
|
**Waveforms:** None, Sine, Triangle, Saw Up, Saw Down, Square, Square+, Sample & Hold, Noise, Step Up (3/4/8 steps), Step Down (3/4/8 steps), Pyramid (3/5/9 steps)
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable the LFO |
|
||||||
|
| Wave | See above | Waveform selection |
|
||||||
|
| Sync | On/Off | Sync to host tempo |
|
||||||
|
| Rate | 0-50 Hz | LFO speed (when Sync is off) |
|
||||||
|
| Beat | Note values | LFO speed (when Sync is on) |
|
||||||
|
| Depth | -1.0 to +1.0 | Modulation amount |
|
||||||
|
| Phase | -1.0 to +1.0 | Starting phase offset |
|
||||||
|
| Offset | -1.0 to +1.0 | DC offset/center bias |
|
||||||
|
| Fade | -60 to +60 seconds | Fade in (positive) or fade out (negative) time |
|
||||||
|
| Delay | 0-60 seconds | Delay before LFO starts |
|
||||||
|
| Retrig | On/Off | Retrigger phase on new notes |
|
||||||
|
|
||||||
|
### Modulation Envelopes
|
||||||
|
|
||||||
|
Three independent ADSR envelopes for modulation.
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable the envelope |
|
||||||
|
| Attack | 0-60 seconds | Attack time |
|
||||||
|
| Decay | 0-60 seconds | Decay time |
|
||||||
|
| Sustain | 0-100% | Sustain level |
|
||||||
|
| Release | 0-60 seconds | Release time |
|
||||||
|
| Retrig | On/Off | Retrigger on new notes |
|
||||||
|
|
||||||
|
### Step LFO
|
||||||
|
|
||||||
|
A 32-step sequencer for rhythmic modulation.
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Enable | On/Off | Enable or disable |
|
||||||
|
| Beat | Note values | Step clock speed (tempo-synced) |
|
||||||
|
| Length | 2-32 steps | Number of active steps |
|
||||||
|
| Retrig | On/Off | Retrigger sequence on new notes |
|
||||||
|
| Steps 1-32 | -1.0 to +1.0 | Individual step values |
|
||||||
|
|
||||||
|
### Modulation Matrix
|
||||||
|
|
||||||
|
The mod matrix routes any modulation source to any parameter with flexible depth, curve shaping, and polarity controls.
|
||||||
|
|
||||||
|
**Source types:** Single ring = mono (global), double ring = poly (per-voice).
|
||||||
|
|
||||||
|
**MIDI sources:** Pitch Bend (mono), Note Number (poly), Velocity (poly), CC 1-120 (mono)
|
||||||
|
|
||||||
|
**MPE sources (when enabled):** Pressure (poly), Timbre (poly), Pitch Bend (poly)
|
||||||
|
|
||||||
|
**Internal sources:** LFO 1-3 poly/mono, Step LFO poly/mono, Filter Envelope, Mod Envelopes 1-3
|
||||||
|
|
||||||
|
**Assigning modulation:**
|
||||||
|
1. **Drag and Drop** - Drag a source icon from the mod source list onto any knob
|
||||||
|
2. **Learn Mode** - Click a source icon, then click a knob to assign
|
||||||
|
|
||||||
|
**Matrix panel controls:** Enable toggle, depth slider, bipolar button, curve button, delete button.
|
||||||
|
|
||||||
|
**Polarity:** Unipolar (0 to 1) or Bipolar (-1 to +1).
|
||||||
|
|
||||||
|
**Curves:** Linear, Quadratic (In/Out/In-Out), Sine (In/Out/In-Out), Exponential (In/Out/In-Out), plus inverted versions of all.
|
||||||
|
|
||||||
|
### Effects
|
||||||
|
|
||||||
|
Effects can be reordered by dragging.
|
||||||
|
|
||||||
|
**Gate:** Beat, Length (2-16 steps), Attack, Release, L/R step pattern
|
||||||
|
|
||||||
|
**Chorus:** Delay (0.1-30 ms), Rate (0.1-10 Hz), Depth (0.1-20 ms), Width, Mix
|
||||||
|
|
||||||
|
**Distortion:** Simple (Amount), Bitcrusher (Rate/Rez/Hard/Mix), Fire Amp (Gain/Tone/Output/Mix), Grind Amp (Gain/Tone/Output/Mix)
|
||||||
|
|
||||||
|
**Delay:** Sync, Time/Beat, Feedback, Crossfeed, Mix
|
||||||
|
|
||||||
|
**Reverb:** Size, Decay, Lowpass, Damping, Predelay, Mix
|
||||||
|
|
||||||
|
### Global Settings
|
||||||
|
|
||||||
|
| Parameter | Range | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| Level | -100 to 0 dB | Master output volume |
|
||||||
|
| Voices | 2-40 | Maximum polyphony |
|
||||||
|
| Mono | On/Off | Monophonic mode |
|
||||||
|
| Glide | Off, Glissando, Portamento | Pitch glide mode |
|
||||||
|
| Glide Time | 0.001-20 seconds | Glide duration |
|
||||||
|
| Legato | On/Off | Legato mode (mono only) |
|
||||||
|
| Pitch Bend | 0-48 semitones | MIDI pitch bend range |
|
||||||
|
| MPE | On/Off | Enable MPE support |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tips & Tricks
|
||||||
|
|
||||||
|
1. **Rich Pads:** Use both oscillators with different wavetables, slight detune, and long filter envelope
|
||||||
|
2. **Punchy Basses:** Enable the sub-oscillator, use LP24 filter with short decay envelope
|
||||||
|
3. **Movement:** Modulate wavetable position with an LFO for evolving textures
|
||||||
|
4. **Rhythmic Effects:** Use the Step LFO or Gate effect for pulsing sounds
|
||||||
|
5. **Expression:** Enable MPE and map pressure/timbre to filter cutoff and wavetable position
|
||||||
|
6. **Layering:** Route oscillators differently through the filter for complex timbres
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The synth is BSD licensed. However, it depends on JUCE. To use in a commercial application, you must have a JUCE license. Wavetables have their own license.
|
See the LICENSE file for license information.
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
Need additional features or help integrating? Contact me for consulting services: https://rabiensoftware.com/
|
|
||||||
|
|
|
||||||
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
1.0.30
|
1.0.34
|
||||||
|
|
|
||||||
16
ci/config_cmake.sh
Executable file
16
ci/config_cmake.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
ROOT=$(cd "$(dirname "$0")/.."; pwd)
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
export PATH=$PATH:"/c/Program Files/CMake/bin"
|
||||||
|
|
||||||
|
if [ "$(uname)" == "Darwin" ]; then
|
||||||
|
TOOLCHAIN="xcode"
|
||||||
|
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
|
||||||
|
TOOLCHAIN="ninja-gcc"
|
||||||
|
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
|
||||||
|
TOOLCHAIN="vs"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake --preset $TOOLCHAIN -D BUILD_EXTRAS=OFF -D JUCE_COPY_PLUGIN_AFTER_BUILD=ON
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 2d7c013ebf4a076c35811e62293e8f819d053a91
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit e44a9e53ea8d22e2fbe2f366921d494534bb2b52
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7781d8dafb59e6e4b7837ff8acb113fcae7291ea
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit bc7339fe07ca1ef7d4708cb6a124932de4af3719
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit d0e42b81bb7b747b0b7b51a993366a1f46ea3a55
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit bcbef199f4dd78b883aebd6477cc104dad850e1b
|
|
||||||
|
|
@ -143,16 +143,16 @@ public:
|
||||||
}
|
}
|
||||||
else if (e.originalComponent == &h && e.mouseWasClicked() && e.x >= prevButton.getRight() && e.x <= nextButton.getX())
|
else if (e.originalComponent == &h && e.mouseWasClicked() && e.x >= prevButton.getRight() && e.x <= nextButton.getX())
|
||||||
{
|
{
|
||||||
auto tables = proc.getWavetableNames();
|
auto files = proc.getWavetableFiles();
|
||||||
|
|
||||||
std::map<juce::String, juce::PopupMenu> menus;
|
std::map<juce::String, juce::PopupMenu> menus;
|
||||||
|
|
||||||
for (auto t : tables)
|
for (auto& f : files)
|
||||||
{
|
{
|
||||||
auto prefix = t.upToFirstOccurrenceOf (" ", false, false);
|
auto t = f.getFileNameWithoutExtension();
|
||||||
auto suffix = t.fromFirstOccurrenceOf (" ", false, false);
|
auto category = f.getParentDirectory().getFileName();
|
||||||
|
|
||||||
menus[prefix].addItem (t, [this, t]
|
menus[category].addItem (t, [this, t]
|
||||||
{
|
{
|
||||||
if (idx == 0)
|
if (idx == 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -102,5 +102,5 @@ void WavetableAudioProcessorEditor::addMenuItems (juce::PopupMenu& m)
|
||||||
|
|
||||||
m.addSeparator();
|
m.addSeparator();
|
||||||
|
|
||||||
m.addItem ("Manual", [] { juce::URL ("https://github.com/FigBug/Wavetable/blob/master/Manual.md").launchInDefaultBrowser(); });
|
m.addItem ("Manual", [] { juce::URL ("https://github.com/FigBug/Wavetable/blob/master/README.md").launchInDefaultBrowser(); });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,29 @@
|
||||||
#include "PluginEditor.h"
|
#include "PluginEditor.h"
|
||||||
#include "WavetableVoice.h"
|
#include "WavetableVoice.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
// If the shared CrashReporter is installed, launch it once per process (on the
|
||||||
|
// first plugin instance) so it can scan and upload any crash from last session.
|
||||||
|
static void launchCrashReporterOnce()
|
||||||
|
{
|
||||||
|
static std::once_flag flag;
|
||||||
|
std::call_once (flag, []
|
||||||
|
{
|
||||||
|
#if JUCE_MAC
|
||||||
|
juce::File app ("/Library/Application Support/Rabien Software/Crash Reporter/CrashReporter.app");
|
||||||
|
#elif JUCE_WINDOWS
|
||||||
|
auto app = juce::File::getSpecialLocation (juce::File::globalApplicationsDirectory)
|
||||||
|
.getChildFile ("Rabien Software").getChildFile ("Crash Reporter").getChildFile ("CrashReporter.exe");
|
||||||
|
#else
|
||||||
|
juce::File app;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (app.exists())
|
||||||
|
juce::Process::openDocument (app.getFullPathName(), {});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static juce::String subTextFunction (const gin::Parameter&, float v)
|
static juce::String subTextFunction (const gin::Parameter&, float v)
|
||||||
{
|
{
|
||||||
switch (int (v))
|
switch (int (v))
|
||||||
|
|
@ -563,6 +586,8 @@ WavetableAudioProcessor::WavetableAudioProcessor()
|
||||||
fireAmp (FXBaseCallback ([this] { return gin::Processor::getSampleRate(); })),
|
fireAmp (FXBaseCallback ([this] { return gin::Processor::getSampleRate(); })),
|
||||||
grindAmp (FXBaseCallback ([this] { return gin::Processor::getSampleRate(); }))
|
grindAmp (FXBaseCallback ([this] { return gin::Processor::getSampleRate(); }))
|
||||||
{
|
{
|
||||||
|
launchCrashReporterOnce();
|
||||||
|
|
||||||
// One-time migration of any user presets from the pre-installer location.
|
// One-time migration of any user presets from the pre-installer location.
|
||||||
// Factory presets now live in systemResourceRoot()/Presets and are surfaced
|
// Factory presets now live in systemResourceRoot()/Presets and are surfaced
|
||||||
// via getFactoryProgramDirectories(). User saves go to userResourceRoot()/Presets.
|
// via getFactoryProgramDirectories(). User saves go to userResourceRoot()/Presets.
|
||||||
|
|
@ -643,12 +668,15 @@ void WavetableAudioProcessor::reloadWavetables()
|
||||||
{
|
{
|
||||||
auto loadMemory = [&] (const juce::String& name) -> juce::MemoryBlock
|
auto loadMemory = [&] (const juce::String& name) -> juce::MemoryBlock
|
||||||
{
|
{
|
||||||
auto file = systemResourceRoot().getChildFile ("Wavetables").getChildFile (name + ".wt2048");
|
auto wtDir = systemResourceRoot().getChildFile ("Wavetables");
|
||||||
if (file.existsAsFile())
|
if (wtDir.isDirectory())
|
||||||
{
|
{
|
||||||
juce::MemoryBlock mb;
|
for (auto& file : wtDir.findChildFiles (juce::File::findFiles, true, name + ".wt2048"))
|
||||||
if (file.loadFileAsData (mb))
|
{
|
||||||
return mb;
|
juce::MemoryBlock mb;
|
||||||
|
if (file.loadFileAsData (mb))
|
||||||
|
return mb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
@ -788,15 +816,38 @@ juce::Array<juce::File> WavetableAudioProcessor::getFactoryProgramDirectories()
|
||||||
juce::StringArray WavetableAudioProcessor::getWavetableNames() const
|
juce::StringArray WavetableAudioProcessor::getWavetableNames() const
|
||||||
{
|
{
|
||||||
juce::StringArray tables;
|
juce::StringArray tables;
|
||||||
auto wtDir = systemResourceRoot().getChildFile ("Wavetables");
|
for (auto& f : getWavetableFiles())
|
||||||
if (wtDir.isDirectory())
|
tables.add (f.getFileNameWithoutExtension());
|
||||||
for (auto f : wtDir.findChildFiles (juce::File::findFiles, false, "*.wt2048"))
|
|
||||||
tables.add (f.getFileNameWithoutExtension());
|
|
||||||
|
|
||||||
tables.sortNatural();
|
tables.sortNatural();
|
||||||
return tables;
|
return tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
juce::Array<juce::File> WavetableAudioProcessor::getWavetableFiles() const
|
||||||
|
{
|
||||||
|
juce::Array<juce::File> files;
|
||||||
|
auto wtDir = systemResourceRoot().getChildFile ("Wavetables");
|
||||||
|
if (wtDir.isDirectory())
|
||||||
|
files = wtDir.findChildFiles (juce::File::findFiles, true, "*.wt2048");
|
||||||
|
|
||||||
|
struct Sorter
|
||||||
|
{
|
||||||
|
static int compareElements (const juce::File& a, const juce::File& b)
|
||||||
|
{
|
||||||
|
auto categoryCmp = a.getParentDirectory().getFileName()
|
||||||
|
.compareNatural (b.getParentDirectory().getFileName());
|
||||||
|
if (categoryCmp != 0)
|
||||||
|
return categoryCmp;
|
||||||
|
return a.getFileNameWithoutExtension()
|
||||||
|
.compareNatural (b.getFileNameWithoutExtension());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Sorter sorter;
|
||||||
|
files.sort (sorter);
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void WavetableAudioProcessor::setupModMatrix()
|
void WavetableAudioProcessor::setupModMatrix()
|
||||||
{
|
{
|
||||||
|
|
@ -916,15 +967,16 @@ bool WavetableAudioProcessor::isBusesLayoutSupported (const BusesLayout& layout)
|
||||||
void WavetableAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midi)
|
void WavetableAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midi)
|
||||||
{
|
{
|
||||||
juce::ScopedNoDenormals noDenormals;
|
juce::ScopedNoDenormals noDenormals;
|
||||||
|
|
||||||
|
if (buffer.getNumChannels() != 2)
|
||||||
|
return;
|
||||||
|
|
||||||
if (! dspLock.tryEnter())
|
if (! dspLock.tryEnter())
|
||||||
{
|
{
|
||||||
blockMissed = true;
|
blockMissed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer.getNumChannels() != 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (midiLearn)
|
if (midiLearn)
|
||||||
midiLearn->processBlock (midi, buffer.getNumSamples());
|
midiLearn->processBlock (midi, buffer.getNumSamples());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ public:
|
||||||
void incWavetable (int osc, int delta);
|
void incWavetable (int osc, int delta);
|
||||||
bool loadUserWavetable (int osc, const juce::File& f, int sz);
|
bool loadUserWavetable (int osc, const juce::File& f, int sz);
|
||||||
juce::StringArray getWavetableNames() const;
|
juce::StringArray getWavetableNames() const;
|
||||||
|
juce::Array<juce::File> getWavetableFiles() const;
|
||||||
|
|
||||||
void applyEffects (juce::AudioSampleBuffer& buffer);
|
void applyEffects (juce::AudioSampleBuffer& buffer);
|
||||||
void applyEffect (juce::AudioSampleBuffer& buffer, int fxId);
|
void applyEffect (juce::AudioSampleBuffer& buffer, int fxId);
|
||||||
|
|
|
||||||
17
release.sh
17
release.sh
|
|
@ -26,6 +26,23 @@ fi
|
||||||
|
|
||||||
echo "$NOTES" > /tmp/release_notes.txt
|
echo "$NOTES" > /tmp/release_notes.txt
|
||||||
|
|
||||||
|
# --- Debug symbols -> crash server -------------------------------------------
|
||||||
|
# Uploaded here (not the build job) so a failed upload fails the release. The
|
||||||
|
# server stores symbols write-once per (plugin, platform, version): a re-tagged
|
||||||
|
# or rebuilt version whose symbols already exist returns 409 and fails the
|
||||||
|
# release loudly — delete the stale symbols in the crash site, then re-run.
|
||||||
|
CRASH_BASE="https://crashreports.rabiensoftware.com"
|
||||||
|
upload_symbols () { # $1 platform, $2 zip
|
||||||
|
if [ ! -f "$2" ]; then echo "Error: expected symbols $2 not found"; exit 1; fi
|
||||||
|
echo "Uploading $1 symbols for $VER"
|
||||||
|
curl -sS --fail-with-body -H "X-API-Key: $SYMBOL_API_KEY" \
|
||||||
|
-F "platform=$1" -F "version=$VER" -F "files[]=@$2" \
|
||||||
|
"$CRASH_BASE/symbols/"
|
||||||
|
echo
|
||||||
|
}
|
||||||
|
upload_symbols mac "./Binaries macOS/Symbols_Mac.zip"
|
||||||
|
upload_symbols win "./Binaries Windows/Symbols_Win.zip"
|
||||||
|
|
||||||
ASSETS=(
|
ASSETS=(
|
||||||
"./Binaries Linux"/*.deb
|
"./Binaries Linux"/*.deb
|
||||||
"./Binaries Windows"/*.exe
|
"./Binaries Windows"/*.exe
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 1 MiB After Width: | Height: | Size: 1 MiB |
Loading…
Add table
Add a link
Reference in a new issue