ElectroBow is a JUCE-based VST3 audio plugin that detects the pitch of incoming audio and emits MIDI notes.
- CMake 3.22 or newer
- A JUCE source checkout (JUCE is not bundled with this repository)
- A C++17 compiler
- Node.js 20 or newer and npm (used to build the embedded React UI)
On Windows, install Visual Studio with the Desktop development with C++ workload. On macOS, install Xcode or the Xcode Command Line Tools. On Linux, install GCC or Clang and the usual build tools for your distribution.
To prepare a new checkout, install the required developer dependencies and enable the repository hooks with the setup script:
./setup.sh # macOS/Linux
setup.bat # Windows Command PromptThe scripts verify Git, Node.js/npm, Python, CMake, a C++ compiler, and
clang-format; download JUCE 9.0.2 into JUCE/ when needed; install the UI
dependencies with npm ci; and configure the local Git hooks. They do not pull
or modify repository history. Install platform-specific compiler packages and
the Windows WebView2 SDK separately when your build requires them.
Use the same Python command on Windows, macOS, and Linux. Pass the path to your JUCE checkout the first time:
python3 build.py "$HOME/path/to/JUCE"The first build installs the frontend dependencies from UI/package-lock.json and
builds the TypeScript/React/Tailwind bundle before CMake embeds it in the plugin.
If you configure with CMake directly, run npm ci && npm run build from UI/
first.
On Windows, use python instead of python3 if that is the command available on your system. The script configures the project automatically when needed and builds the Release configuration. Subsequent builds need no JUCE argument because the path is stored in the CMake build directory:
python3 build.py # macOS/Linux
python build.py # WindowsIf a JUCE checkout is placed in a JUCE/ folder beside the project, build.py detects it automatically. You can also set JUCE_PATH once instead of passing it as an argument:
export JUCE_PATH=/path/to/JUCE # macOS/Linux
set JUCE_PATH=C:\path\to\JUCE # Windows Command PromptFor direct CMake use, the equivalent commands are:
cmake -S . -B build -DJUCE_PATH=/path/to/JUCE
cmake --build build --config ReleaseThe generated VST3 plugin is placed under build/ElectroBow_artefacts/Release/VST3/ (the exact bundle/file layout varies slightly by platform).
The Windows release is a VST3 package, not a VST2 .dll: after extracting
ElectroBow-vst3-windows.zip, copy the included ElectroBow.vst3 folder to a
VST3 scan location such as C:\Program Files\Common Files\VST3, then rescan
plugins in the DAW.
The release workflow builds the macOS plugin as a universal binary for both Apple Silicon (arm64) and Intel (x86_64) Macs. Local builds use all available CPU cores through CMake's parallel build mode.
The test suite uses CTest and covers generated monophonic and polyphonic signals, including isolated voice buffers, guitar-like harmonics, weak fundamentals, continuous pitch bends, and noise rejection:
ctest --test-dir build --build-config Release --output-on-failureFor a convenient configure/build/run workflow, use the Python test wrapper:
python3 run_tests.py /path/to/JUCE
python3 run_tests.py # reuse the configured build directory
python3 run_tests.py --verbose # show detailed CTest output
python3 run_tests.py --list # list tests without running themOn Windows, use python run_tests.py. The wrapper builds only the
ElectroBowPitchDetectorTests target before invoking CTest. Use --reconfigure
after changing CMake options, or --no-build to run an already-built test binary.
GitHub Actions runs the build and tests on every push and pull request for Windows, macOS, and Linux. Release builds run the same tests before packaging. CMake build directories are cached when the platform, JUCE version, and source inputs match.
Install the CMake Tools and C/C++ extensions, then configure the project once so CMake generates build/compile_commands.json:
python3 build.py /path/to/JUCEThe repository includes VS Code settings that use this compilation database, providing the JUCE and aubio include paths for IntelliSense. If diagnostics remain after configuring, run CMake: Delete Cache and Reconfigure and reload the editor window.
Visual Studio is only used as the compiler/generator on Windows; no solution file is required or checked into the repository. CMake will select an appropriate native generator unless one is specified explicitly.
Source/PluginProcessor.*contains the audio/business logic and the small native UI bridge.Source/PluginEditor.*hosts JUCE's WebView and serves the embedded frontend assets.UI/contains the TypeScript/React/Tailwind frontend. Its production bundle is generated inUI/dist/and embedded into the VST3 during the CMake build.Source/PitchDetector.hcontains the aubio-based pitch detector.ThirdParty/contains the vendored aubio and STK sources used by the plugin.CMakeLists.txtdefines the platform-independent build.
The vendored dependencies retain their upstream licenses in ThirdParty/aubio-src/COPYING and ThirdParty/stk/LICENSE.
Project C/C++ files are formatted automatically by the pre-commit hook. Vendored files under ThirdParty/ are intentionally excluded.
Install LLVM, which provides clang-format and clang-tidy:
# macOS
brew install llvm
export PATH="$(brew --prefix llvm)/bin:$PATH"
# Ubuntu/Debian
sudo apt-get install clang-format clang-tidyOn Windows, install LLVM with winget install LLVM.LLVM, then make sure its bin directory is on PATH.
Enable the committed hook once per checkout:
git config core.hooksPath .githooksEvery commit will format staged project C/C++ files and stage the formatting changes. clang-tidy configuration is provided in .clang-tidy; run it from a configured CMake build directory with compile_commands.json when doing lint checks. Release builds do not run linting.
Releases are built automatically by GitHub Actions for Windows, macOS, and Linux. The workflow runs when either a v1.3.0 or 1.3.0 semantic-version tag is pushed, for example:
git tag v1.3.0
git push origin v1.3.0The workflow file must be committed and pushed before creating the tag. It can also be started manually from the Actions tab; manual runs build the artifacts but do not publish a release.
The workflow builds and tests the plugin before packaging one VST3 archive per operating system. Each archive has ElectroBow.vst3 at its root; on Windows the plugin binary is inside that package at Contents/x86_64-win/ElectroBow.vst3. Release notes are created from the matching version section in CHANGELOG.md.
Keep the changelog in this strict structure:
## [X.Y.Z] - YYYY-MM-DD
### Added
- Change description.
Allowed category headings are Added, Changed, Deprecated, Removed, Fixed, and Security. The release workflow requires the exact version heading and date before publishing.