From 8c45136be6b259a9b52c8a00a95ad6b1b4893d2f Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sat, 2 May 2026 09:54:17 -0700 Subject: [PATCH 01/15] bring back config_cmake --- ci/config_cmake.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 ci/config_cmake.sh diff --git a/ci/config_cmake.sh b/ci/config_cmake.sh new file mode 100755 index 0000000..233babd --- /dev/null +++ b/ci/config_cmake.sh @@ -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 From e4f7246f45d062b1827e97a360ce2130a98df5ed Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sat, 2 May 2026 15:47:21 -0700 Subject: [PATCH 02/15] Fix wavetable menu --- plugin/Source/Panels.h | 12 ++++----- plugin/Source/PluginProcessor.cpp | 44 ++++++++++++++++++++++++------- plugin/Source/PluginProcessor.h | 1 + 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/plugin/Source/Panels.h b/plugin/Source/Panels.h index 65bd3c0..161699e 100644 --- a/plugin/Source/Panels.h +++ b/plugin/Source/Panels.h @@ -143,16 +143,16 @@ public: } 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 menus; - for (auto t : tables) + for (auto& f : files) { - auto prefix = t.upToFirstOccurrenceOf (" ", false, false); - auto suffix = t.fromFirstOccurrenceOf (" ", false, false); + auto t = f.getFileNameWithoutExtension(); + auto category = f.getParentDirectory().getFileName(); - menus[prefix].addItem (t, [this, t] + menus[category].addItem (t, [this, t] { if (idx == 0) { @@ -171,7 +171,7 @@ public: juce::PopupMenu m; m.setLookAndFeel (&getLookAndFeel()); - + for (auto itr : menus) m.addSubMenu (itr.first, itr.second); diff --git a/plugin/Source/PluginProcessor.cpp b/plugin/Source/PluginProcessor.cpp index 27bead0..956f6f7 100644 --- a/plugin/Source/PluginProcessor.cpp +++ b/plugin/Source/PluginProcessor.cpp @@ -643,12 +643,15 @@ void WavetableAudioProcessor::reloadWavetables() { auto loadMemory = [&] (const juce::String& name) -> juce::MemoryBlock { - auto file = systemResourceRoot().getChildFile ("Wavetables").getChildFile (name + ".wt2048"); - if (file.existsAsFile()) + auto wtDir = systemResourceRoot().getChildFile ("Wavetables"); + if (wtDir.isDirectory()) { - juce::MemoryBlock mb; - if (file.loadFileAsData (mb)) - return mb; + for (auto& file : wtDir.findChildFiles (juce::File::findFiles, true, name + ".wt2048")) + { + juce::MemoryBlock mb; + if (file.loadFileAsData (mb)) + return mb; + } } return {}; }; @@ -788,15 +791,38 @@ juce::Array WavetableAudioProcessor::getFactoryProgramDirectories() juce::StringArray WavetableAudioProcessor::getWavetableNames() const { juce::StringArray tables; - auto wtDir = systemResourceRoot().getChildFile ("Wavetables"); - if (wtDir.isDirectory()) - for (auto f : wtDir.findChildFiles (juce::File::findFiles, false, "*.wt2048")) - tables.add (f.getFileNameWithoutExtension()); + for (auto& f : getWavetableFiles()) + tables.add (f.getFileNameWithoutExtension()); tables.sortNatural(); return tables; } +juce::Array WavetableAudioProcessor::getWavetableFiles() const +{ + juce::Array 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() { diff --git a/plugin/Source/PluginProcessor.h b/plugin/Source/PluginProcessor.h index b96eb51..5ef0f1b 100644 --- a/plugin/Source/PluginProcessor.h +++ b/plugin/Source/PluginProcessor.h @@ -56,6 +56,7 @@ public: void incWavetable (int osc, int delta); bool loadUserWavetable (int osc, const juce::File& f, int sz); juce::StringArray getWavetableNames() const; + juce::Array getWavetableFiles() const; void applyEffects (juce::AudioSampleBuffer& buffer); void applyEffect (juce::AudioSampleBuffer& buffer, int fxId); From 155c9337110a2c9eee5ff524ef70b755385744b0 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sat, 2 May 2026 15:54:57 -0700 Subject: [PATCH 03/15] Fix deadlock --- plugin/Source/PluginProcessor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugin/Source/PluginProcessor.cpp b/plugin/Source/PluginProcessor.cpp index 956f6f7..1d6d488 100644 --- a/plugin/Source/PluginProcessor.cpp +++ b/plugin/Source/PluginProcessor.cpp @@ -942,14 +942,15 @@ bool WavetableAudioProcessor::isBusesLayoutSupported (const BusesLayout& layout) void WavetableAudioProcessor::processBlock (juce::AudioBuffer& buffer, juce::MidiBuffer& midi) { juce::ScopedNoDenormals noDenormals; + + if (buffer.getNumChannels() != 2) + return; + if (! dspLock.tryEnter()) { blockMissed = true; return; } - - if (buffer.getNumChannels() != 2) - return; if (midiLearn) midiLearn->processBlock (midi, buffer.getNumSamples()); From 98d290770b1436bc43017defb9a775b7ea80fe47 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sat, 2 May 2026 15:58:03 -0700 Subject: [PATCH 04/15] Spacing --- Installer/win/Wavetable.iss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Installer/win/Wavetable.iss b/Installer/win/Wavetable.iss index 97d2621..6f3e732 100644 --- a/Installer/win/Wavetable.iss +++ b/Installer/win/Wavetable.iss @@ -58,7 +58,7 @@ Name: "clap"; Description: "CLAP plug-in"; Types: full cu Name: "resources"; Description: "Factory wavetables and presets"; Types: full custom; Flags: fixed [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: files; Name: "{commoncf64}\CLAP\Wavetable.clap"; Components: clap Type: filesandordirs; Name: "{commonappdata}\SocaLabs\Wavetable\Presets"; Components: resources @@ -66,7 +66,7 @@ Type: filesandordirs; Name: "{commonappdata}\SocaLabs\Wavetable\Wavetables"; [Files] ; 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\CLAP\Wavetable.clap"; DestDir: "{commoncf64}\CLAP"; Flags: ignoreversion overwritereadonly; Components: clap From 05992e760fb24240af16a033a51afcc7670177ad Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sat, 2 May 2026 15:59:02 -0700 Subject: [PATCH 05/15] v1.0.32 --- Changelist.txt | 4 ++++ VERSION | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelist.txt b/Changelist.txt index 374f337..e2e08b4 100644 --- a/Changelist.txt +++ b/Changelist.txt @@ -1,3 +1,7 @@ +1.0.32: +- Fixed fix wavetable menus +- Fixed deadlock + 1.0.31: - Fixed ADSR attack when time is 0 diff --git a/VERSION b/VERSION index a8c6b78..08a69b5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.31 \ No newline at end of file +1.0.32 \ No newline at end of file From 539fd803709d2cdba57e3a6031ef24d5301ab412 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sun, 3 May 2026 12:23:58 -0700 Subject: [PATCH 06/15] new instances remember ui size --- modules/gin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gin b/modules/gin index ec6ac53..94fee5b 160000 --- a/modules/gin +++ b/modules/gin @@ -1 +1 @@ -Subproject commit ec6ac53d4c86559ff40cfe335c96a249890a12ab +Subproject commit 94fee5b72348976107f6d7c751b1c4f632cf6bf0 From a681b2e3321e6833ccbd8c6ab6b3f7d326f68339 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Thu, 16 Jul 2026 18:18:43 -0700 Subject: [PATCH 07/15] Add crash reporting (bundle CrashReporter, strip, symbols, upload) - register plugin + ship Installer/crashreporter.json - installer bundles the shared CrashReporter (mac pkg + component-plist + reporter-scripts promote-if-newer; win .iss shared component) and the JSON - strip shipped mac binaries; emit dSYM (Xcode) and PDB (/Zi /DEBUG) in Release - launchCrashReporterOnce() from the processor on first instance - upload dSYM/PDB symbols to the crash site from release.yaml - bump to 1.0.33 --- .github/workflows/release.yaml | 1 + CMakeLists.txt | 17 +++ Changelist.txt | 3 + Installer/build.sh | 110 ++++++++++++++++++- Installer/crashreporter.json | 6 + Installer/macOS/distribution.xml | 11 ++ Installer/macOS/reporter-scripts/postinstall | 38 +++++++ Installer/win/Wavetable.iss | 8 ++ VERSION | 2 +- plugin/Source/PluginProcessor.cpp | 25 +++++ 10 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 Installer/crashreporter.json create mode 100755 Installer/macOS/reporter-scripts/postinstall diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 42df63a..c48a2a8 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -53,6 +53,7 @@ jobs: AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} + SYMBOL_API_KEY: ${{ secrets.SYMBOL_API_KEY }} - name: Upload Artifact uses: actions/upload-artifact@v4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a8d37b..7504482 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,6 +213,7 @@ if (APPLE) XCODE_ATTRIBUTE_CLANG_LINK_OBJC_RUNTIME NO #XCODE_ATTRIBUTE_DEPLOYMENT_POSTPROCESSING[variant=Release] YES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES" + XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT[variant=Release] "dwarf-with-dsym" ) if (NOT t STREQUAL "All") target_compile_options(${tgt} PRIVATE @@ -237,6 +238,22 @@ if (WIN32) set_target_properties(${tgt} PROPERTIES LINK_FLAGS "/ignore:4099") endif() 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 "$<$:/Zi>") + target_link_options(${tgt} PRIVATE "$<$:/DEBUG>") + target_link_options(${tgt} PRIVATE "$<$:/OPT:REF>") + target_link_options(${tgt} PRIVATE "$<$:/OPT:ICF>") + endif() + endforeach() endif() if(UNIX AND NOT APPLE) diff --git a/Changelist.txt b/Changelist.txt index e2e08b4..b3babb2 100644 --- a/Changelist.txt +++ b/Changelist.txt @@ -1,3 +1,6 @@ +1.0.33: +- Added crash reporting + 1.0.32: - Fixed fix wavetable menus - Fixed deadlock diff --git a/Installer/build.sh b/Installer/build.sh index 6e2da81..e559fe2 100755 --- a/Installer/build.sh +++ b/Installer/build.sh @@ -21,6 +21,42 @@ fi VERSION=$(cat "$PROJECT_ROOT/VERSION") +# +# Crash reporting: bundle the latest CrashReporter app + this plugin's +# registration JSON, and upload debug symbols so crashes can be symbolicated. +# SYMBOL_API_KEY - CI secret, authorises symbol upload for this plugin. +# 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 +} + +# Upload a symbols archive for this plugin/version. Skipped if the key is unset. +upload_symbols () { # $1 platform, $2 zip file + if [ -z "${SYMBOL_API_KEY:-}" ]; then echo "SYMBOL_API_KEY not set — skipping symbol upload"; return 0; fi + if [ ! -f "$2" ]; then echo "No symbol archive $2 — skipping"; return 0; fi + echo "Uploading $1 symbols for $VERSION" + # Non-fatal: a symbol-upload failure must never break a release build. + curl -fsS -H "X-API-Key: $SYMBOL_API_KEY" \ + -F "platform=$1" -F "version=$VERSION" -F "files[]=@$(curl_path "$2")" \ + "$CRASH_BASE/symbols/" || echo "WARNING: symbol upload failed" + echo +} + # # Reset staging # @@ -95,6 +131,15 @@ if [ "$PLATFORM" = "macOS" ]; then cp -R "$PROJECT_ROOT/plugin/Resources/WavetablesFLAC" "$STAGE/resources/Library/Audio/Presets/$VENDOR/$PLUGIN/Wavetables" 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 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" @@ -136,6 +181,38 @@ if [ "$PLATFORM" = "macOS" ]; then --scripts "$PROJECT_ROOT/Installer/macOS/scripts" \ "$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 cp "$PROJECT_ROOT/Installer/EULA.rtf" "$PKG_DIR/EULA.rtf" cp "$PROJECT_ROOT/Installer/macOS/welcome.txt" "$PKG_DIR/welcome.txt" @@ -172,7 +249,18 @@ if [ "$PLATFORM" = "macOS" ]; then 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" zip -r "$PROJECT_ROOT/bin/Symbols_Mac.zip" \ AU/$PLUGIN.component.dSYM \ @@ -180,6 +268,8 @@ if [ "$PLATFORM" = "macOS" ]; then VST3/$PLUGIN.vst3.dSYM \ CLAP/$PLUGIN.clap.dSYM 2>/dev/null || true + upload_symbols mac "$PROJECT_ROOT/bin/Symbols_Mac.zip" + ############################################################ # Linux — cpack DEB (VST + VST3 + LV2 + CLAP + Resources) ############################################################ @@ -210,6 +300,14 @@ else cp -R "$ART_DIR/VST3/$PLUGIN.vst3" "$STAGE/VST3/" 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. # Required env: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. @@ -272,4 +370,14 @@ else fi 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 ) + + upload_symbols win "$PROJECT_ROOT/bin/Symbols_Win.zip" fi diff --git a/Installer/crashreporter.json b/Installer/crashreporter.json new file mode 100644 index 0000000..cc52a9c --- /dev/null +++ b/Installer/crashreporter.json @@ -0,0 +1,6 @@ +{ + "name": "Wavetable", + "pluginID": "com.socalabs.wavetable", + "crashUrl": "https://crashreports.rabiensoftware.com/post/", + "apiKey": "da8b3bc4e5fcb9b5ba8b5960d0ef805b62d4097b956082c87fcf82cab40cc2c8" +} diff --git a/Installer/macOS/distribution.xml b/Installer/macOS/distribution.xml index 63aa3fd..6846ef7 100644 --- a/Installer/macOS/distribution.xml +++ b/Installer/macOS/distribution.xml @@ -13,6 +13,7 @@ + + + + + vst.pkg vst3.pkg au.pkg clap.pkg resources.pkg + reporter.pkg diff --git a/Installer/macOS/reporter-scripts/postinstall b/Installer/macOS/reporter-scripts/postinstall new file mode 100755 index 0000000..9ae4a00 --- /dev/null +++ b/Installer/macOS/reporter-scripts/postinstall @@ -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 diff --git a/Installer/win/Wavetable.iss b/Installer/win/Wavetable.iss index 6f3e732..133a24a 100644 --- a/Installer/win/Wavetable.iss +++ b/Installer/win/Wavetable.iss @@ -56,6 +56,7 @@ Name: "vst"; Description: "VST plug-in"; Types: full cu Name: "vst3"; Description: "VST3 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: "crashreporter"; Description: "Crash reporter (shared component, only updated if newer)"; Types: full custom; Flags: checkablealone [InstallDelete] Type: files; Name: "{commoncf64}\VST2\Wavetable.dll"; Components: vst @@ -74,3 +75,10 @@ Source: "bin\CLAP\Wavetable.clap"; DestDir: "{commoncf64}\CLAP"; ; 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: "..\..\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 diff --git a/VERSION b/VERSION index 08a69b5..c1cf2f9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.32 \ No newline at end of file +1.0.33 \ No newline at end of file diff --git a/plugin/Source/PluginProcessor.cpp b/plugin/Source/PluginProcessor.cpp index 1d6d488..00f6604 100644 --- a/plugin/Source/PluginProcessor.cpp +++ b/plugin/Source/PluginProcessor.cpp @@ -2,6 +2,29 @@ #include "PluginEditor.h" #include "WavetableVoice.h" +#include + +// 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) { switch (int (v)) @@ -563,6 +586,8 @@ WavetableAudioProcessor::WavetableAudioProcessor() fireAmp (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. // Factory presets now live in systemResourceRoot()/Presets and are surfaced // via getFactoryProgramDirectories(). User saves go to userResourceRoot()/Presets. From afa366e9e166b88516c0ad280ddd4e1fd85dc3f8 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Thu, 16 Jul 2026 18:36:32 -0700 Subject: [PATCH 08/15] Update Gin and JUCE --- modules/gin | 2 +- modules/juce | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/gin b/modules/gin index 94fee5b..32f47f6 160000 --- a/modules/gin +++ b/modules/gin @@ -1 +1 @@ -Subproject commit 94fee5b72348976107f6d7c751b1c4f632cf6bf0 +Subproject commit 32f47f63ad3fb3d53b1d7928fc8465ad8bd48b29 diff --git a/modules/juce b/modules/juce index bc7339f..2cdfca8 160000 --- a/modules/juce +++ b/modules/juce @@ -1 +1 @@ -Subproject commit bc7339fe07ca1ef7d4708cb6a124932de4af3719 +Subproject commit 2cdfca8feb300fb424002ba2c2751569e5bacb64 From 8292f10db2e8bff14952b6a40c6cc88d99153bec Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Sun, 19 Jul 2026 07:51:19 -0700 Subject: [PATCH 09/15] Upload symbols from release step; bump to 1.0.34 --- .github/workflows/release.yaml | 2 +- Changelist.txt | 3 +++ Installer/build.sh | 20 ++------------------ VERSION | 2 +- release.sh | 17 +++++++++++++++++ 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c48a2a8..b651fb4 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -53,7 +53,6 @@ jobs: AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }} AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }} AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }} - SYMBOL_API_KEY: ${{ secrets.SYMBOL_API_KEY }} - name: Upload Artifact uses: actions/upload-artifact@v4 @@ -80,3 +79,4 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} APIKEY: ${{ secrets.APIKEY }} + SYMBOL_API_KEY: ${{ secrets.SYMBOL_API_KEY }} diff --git a/Changelist.txt b/Changelist.txt index b3babb2..d3f543d 100644 --- a/Changelist.txt +++ b/Changelist.txt @@ -1,3 +1,6 @@ +1.0.34: +- Crash reporting improvements + 1.0.33: - Added crash reporting diff --git a/Installer/build.sh b/Installer/build.sh index e559fe2..3aa595b 100755 --- a/Installer/build.sh +++ b/Installer/build.sh @@ -23,8 +23,8 @@ VERSION=$(cat "$PROJECT_ROOT/VERSION") # # Crash reporting: bundle the latest CrashReporter app + this plugin's -# registration JSON, and upload debug symbols so crashes can be symbolicated. -# SYMBOL_API_KEY - CI secret, authorises symbol upload for this plugin. +# 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" @@ -45,18 +45,6 @@ fetch_reporter () { # $1 platform, $2 output file return 1 } -# Upload a symbols archive for this plugin/version. Skipped if the key is unset. -upload_symbols () { # $1 platform, $2 zip file - if [ -z "${SYMBOL_API_KEY:-}" ]; then echo "SYMBOL_API_KEY not set — skipping symbol upload"; return 0; fi - if [ ! -f "$2" ]; then echo "No symbol archive $2 — skipping"; return 0; fi - echo "Uploading $1 symbols for $VERSION" - # Non-fatal: a symbol-upload failure must never break a release build. - curl -fsS -H "X-API-Key: $SYMBOL_API_KEY" \ - -F "platform=$1" -F "version=$VERSION" -F "files[]=@$(curl_path "$2")" \ - "$CRASH_BASE/symbols/" || echo "WARNING: symbol upload failed" - echo -} - # # Reset staging # @@ -268,8 +256,6 @@ if [ "$PLATFORM" = "macOS" ]; then VST3/$PLUGIN.vst3.dSYM \ CLAP/$PLUGIN.clap.dSYM 2>/dev/null || true - upload_symbols mac "$PROJECT_ROOT/bin/Symbols_Mac.zip" - ############################################################ # Linux — cpack DEB (VST + VST3 + LV2 + CLAP + Resources) ############################################################ @@ -378,6 +364,4 @@ else 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 ) - - upload_symbols win "$PROJECT_ROOT/bin/Symbols_Win.zip" fi diff --git a/VERSION b/VERSION index c1cf2f9..ffcbe71 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.0.33 \ No newline at end of file +1.0.34 diff --git a/release.sh b/release.sh index f39f24a..d86c90c 100755 --- a/release.sh +++ b/release.sh @@ -26,6 +26,23 @@ fi 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=( "./Binaries Linux"/*.deb "./Binaries Windows"/*.exe From 62f2788c8a937b5d8e81695bdd4c7f95154034e8 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Tue, 21 Jul 2026 08:44:25 -0700 Subject: [PATCH 10/15] Update JUCE --- modules/juce | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/juce b/modules/juce index 2cdfca8..f8f8864 160000 --- a/modules/juce +++ b/modules/juce @@ -1 +1 @@ -Subproject commit 2cdfca8feb300fb424002ba2c2751569e5bacb64 +Subproject commit f8f8864172464b9adf9eba6101e1f784838d1597 From e34c58fc8fa9c873ce425e48b1be3c6095d00f14 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Tue, 21 Jul 2026 08:45:24 -0700 Subject: [PATCH 11/15] Update Gin --- modules/gin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/gin b/modules/gin index 32f47f6..414fecf 160000 --- a/modules/gin +++ b/modules/gin @@ -1 +1 @@ -Subproject commit 32f47f63ad3fb3d53b1d7928fc8465ad8bd48b29 +Subproject commit 414fecf9c28e72a9a5a4ac188f0fc6ef2e83eb2a From ba6e7b59cac29453916a9b8f634c09267a5a0dc0 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Tue, 21 Jul 2026 13:43:12 -0700 Subject: [PATCH 12/15] Update clap-juce-extensions --- modules/clap-juce-extensions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/clap-juce-extensions b/modules/clap-juce-extensions index e44a9e5..26bab6b 160000 --- a/modules/clap-juce-extensions +++ b/modules/clap-juce-extensions @@ -1 +1 @@ -Subproject commit e44a9e53ea8d22e2fbe2f366921d494534bb2b52 +Subproject commit 26bab6be8c428ba9537fdd2fd80d2dbb07dd9164 From 5797f8b8b7fcaa95d754cc5651b4cb54ffa631ca Mon Sep 17 00:00:00 2001 From: Armin Date: Tue, 28 Jul 2026 16:27:38 +0200 Subject: [PATCH 13/15] add modules to gitignore, remove tracked modules --- .gitignore | 6 +- AGENTS.md | 174 ++++++++++++++++++++ Installer/build.sh | 44 ++--- Installer/win/Wavetable.iss | 2 +- README.md | 292 ++++++++++++++++++++++++++++++++- modules/MTS-ESP | 1 - modules/clap-juce-extensions | 1 - modules/gin | 1 - modules/juce | 1 - modules/melatonin_inspector | 1 - modules/plugin_sdk | 1 - plugin/Source/PluginEditor.cpp | 2 +- 12 files changed, 488 insertions(+), 38 deletions(-) create mode 100644 AGENTS.md delete mode 160000 modules/MTS-ESP delete mode 160000 modules/clap-juce-extensions delete mode 160000 modules/gin delete mode 160000 modules/juce delete mode 160000 modules/melatonin_inspector delete mode 160000 modules/plugin_sdk diff --git a/.gitignore b/.gitignore index 9d078de..792c923 100644 --- a/.gitignore +++ b/.gitignore @@ -38,4 +38,8 @@ Installer/macOS/bin Installer/win/bin Installer/_flat_presets .DS_Store -.claude \ No newline at end of file +.claude + +# modules +modules + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6814a83 --- /dev/null +++ b/AGENTS.md @@ -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). diff --git a/Installer/build.sh b/Installer/build.sh index 3aa595b..43dca8b 100755 --- a/Installer/build.sh +++ b/Installer/build.sh @@ -48,8 +48,8 @@ fetch_reporter () { # $1 platform, $2 output file # # Reset staging # -rm -Rf "$PROJECT_ROOT/Installer/$PLATFORM/bin" -mkdir -p "$PROJECT_ROOT/Installer/$PLATFORM/bin" +rm -Rf "$PROJECT_ROOT/installer/$PLATFORM/bin" +mkdir -p "$PROJECT_ROOT/installer/$PLATFORM/bin" rm -Rf "$PROJECT_ROOT/bin" mkdir -p "$PROJECT_ROOT/bin" @@ -58,7 +58,7 @@ mkdir -p "$PROJECT_ROOT/bin" # gin's loadDirectory() doesn't recurse, and the legacy BinaryData flow stored # 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" mkdir -p "$FLAT_PRESETS" find "$PROJECT_ROOT/plugin/Resources/Presets" -name "*.xml" -type f -exec cp {} "$FLAT_PRESETS/" \; @@ -101,8 +101,8 @@ if [ "$PLATFORM" = "macOS" ]; then cmake --preset xcode cmake --build --preset xcode --config Release - STAGE="$PROJECT_ROOT/Installer/macOS/bin/stage" - PKG_DIR="$PROJECT_ROOT/Installer/macOS/bin/pkgs" + STAGE="$PROJECT_ROOT/installer/macOS/bin/stage" + PKG_DIR="$PROJECT_ROOT/installer/macOS/bin/pkgs" rm -Rf "$STAGE" "$PKG_DIR" mkdir -p "$STAGE/vst" "$STAGE/vst3" "$STAGE/au" "$STAGE/clap" mkdir -p "$STAGE/resources/Library/Audio/Presets/$VENDOR/$PLUGIN" @@ -166,13 +166,13 @@ if [ "$PLATFORM" = "macOS" ]; then --install-location "/" \ --identifier "${BUNDLE_BASE}.resources.pkg" \ --version "$VERSION" \ - --scripts "$PROJECT_ROOT/Installer/macOS/scripts" \ + --scripts "$PROJECT_ROOT/installer/macOS/scripts" \ "$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_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" @@ -180,34 +180,34 @@ if [ "$PLATFORM" = "macOS" ]; 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" + 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" + 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" + 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" \ + --scripts "$PROJECT_ROOT/installer/macOS/reporter-scripts" \ "$PKG_DIR/reporter.pkg" # productbuild — combine into one signed installer - 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/EULA.rtf" "$PKG_DIR/EULA.rtf" + 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" \ --resources "$PKG_DIR" \ --version "$VERSION" \ @@ -278,7 +278,7 @@ else cmake --build --preset vs --config 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" mkdir -p "$STAGE/VST" "$STAGE/VST3" "$STAGE/CLAP" @@ -292,12 +292,12 @@ else 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" + cp "$PROJECT_ROOT/installer/crashreporter.json" "$REP_DIR/wavetable.json" # # Sign binaries via Microsoft Trusted Signing. # 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}$' WIN_SIGN=0 @@ -325,7 +325,7 @@ else nuget install Microsoft.Trusted.Signing.Client -Version 1.0.86 \ -OutputDirectory "$TOOLS_DIR" -ExcludeVersion -NonInteractive 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 () { "$SIGNTOOL" sign -v -fd SHA256 \ @@ -341,14 +341,14 @@ else fi # Build installer .exe - cd "$PROJECT_ROOT/Installer/win" + cd "$PROJECT_ROOT/installer/win" ISCC="/c/Program Files (x86)/Inno Setup 6/ISCC.exe" if [ ! -f "$ISCC" ]; then ISCC="/c/Program Files/Inno Setup 6/ISCC.exe" 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 if [ "$WIN_SIGN" = "1" ]; then diff --git a/Installer/win/Wavetable.iss b/Installer/win/Wavetable.iss index 133a24a..1aa5ae1 100644 --- a/Installer/win/Wavetable.iss +++ b/Installer/win/Wavetable.iss @@ -72,7 +72,7 @@ Source: "bin\VST3\Wavetable.vst3\*"; DestDir: "{commoncf64}\VST3\Wavetable.vst3\ Source: "bin\CLAP\Wavetable.clap"; DestDir: "{commoncf64}\CLAP"; Flags: ignoreversion overwritereadonly; Components: clap ; 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: "..\..\plugin\Resources\WavetablesFLAC\*.wt2048"; DestDir: "{commonappdata}\SocaLabs\Wavetable\Wavetables\"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: resources diff --git a/README.md b/README.md index 1a3feb1..7c380c5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A 2 oscillator wavetable synthesizer with flexible modulation options. -![Screenshot](Screenshots/Screenshot1.png) +![Screenshot](screenshots/Screenshot1.png) [Download](https://github.com/FigBug/Wavetable/releases) | [Product Page](https://socalabs.com/synths/Wavetable/) @@ -48,22 +48,300 @@ A 2 oscillator wavetable synthesizer with flexible modulation options. - VST3 - VST2 (requires VST2 SDK) - AU (macOS) +- CLAP - LV2 - Standalone -## Building +## System Requirements -Requirements: -- CMake 3.16+ -- C++20 compatible compiler +- macOS 10.13 or later +- Windows 10 or later +- 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 git clone --recursive https://github.com/FigBug/Wavetable.git 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 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. diff --git a/modules/MTS-ESP b/modules/MTS-ESP deleted file mode 160000 index 2d7c013..0000000 --- a/modules/MTS-ESP +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2d7c013ebf4a076c35811e62293e8f819d053a91 diff --git a/modules/clap-juce-extensions b/modules/clap-juce-extensions deleted file mode 160000 index 26bab6b..0000000 --- a/modules/clap-juce-extensions +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 26bab6be8c428ba9537fdd2fd80d2dbb07dd9164 diff --git a/modules/gin b/modules/gin deleted file mode 160000 index 414fecf..0000000 --- a/modules/gin +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 414fecf9c28e72a9a5a4ac188f0fc6ef2e83eb2a diff --git a/modules/juce b/modules/juce deleted file mode 160000 index f8f8864..0000000 --- a/modules/juce +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f8f8864172464b9adf9eba6101e1f784838d1597 diff --git a/modules/melatonin_inspector b/modules/melatonin_inspector deleted file mode 160000 index d0e42b8..0000000 --- a/modules/melatonin_inspector +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d0e42b81bb7b747b0b7b51a993366a1f46ea3a55 diff --git a/modules/plugin_sdk b/modules/plugin_sdk deleted file mode 160000 index bcbef19..0000000 --- a/modules/plugin_sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bcbef199f4dd78b883aebd6477cc104dad850e1b diff --git a/plugin/Source/PluginEditor.cpp b/plugin/Source/PluginEditor.cpp index 565ac4c..aa3f50e 100644 --- a/plugin/Source/PluginEditor.cpp +++ b/plugin/Source/PluginEditor.cpp @@ -102,5 +102,5 @@ void WavetableAudioProcessorEditor::addMenuItems (juce::PopupMenu& m) 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(); }); } From 3001ed82719f7094fdad2dc7e627eac734e7fe27 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 2 Aug 2026 22:02:11 +0200 Subject: [PATCH 14/15] rename: Screenshots -> screenshots --- {Screenshots => screenshots}/Screenshot1.png | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename {Screenshots => screenshots}/Screenshot1.png (100%) diff --git a/Screenshots/Screenshot1.png b/screenshots/Screenshot1.png similarity index 100% rename from Screenshots/Screenshot1.png rename to screenshots/Screenshot1.png From 0399fa39dc50a5ec83d181c9b1aeeb7b7124bf67 Mon Sep 17 00:00:00 2001 From: Armin Date: Sun, 2 Aug 2026 22:06:13 +0200 Subject: [PATCH 15/15] update README --- LICENSE | 1 + README.md | 13 +++---------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/LICENSE b/LICENSE index f386d22..5c36cb9 100644 --- a/LICENSE +++ b/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, 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. + diff --git a/README.md b/README.md index 7c380c5..a23f073 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,9 @@ -# Wavetable +# Wavetable - personal fork with some modifications -![Build](https://github.com/FigBug/Wavetable/workflows/Build/badge.svg) - -A 2 oscillator wavetable synthesizer with flexible modulation options. +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. ![Screenshot](screenshots/Screenshot1.png) -[Download](https://github.com/FigBug/Wavetable/releases) | [Product Page](https://socalabs.com/synths/Wavetable/) - ## Features ### Oscillators @@ -344,8 +340,5 @@ Effects can be reordered by dragging. ## 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/