EffeTune Build and Packaging Guide
This document provides instructions for setting up the development environment, validating the web app, and building the EffeTune desktop application using Electron.
Prerequisites
Before you begin, ensure you have the following installed on your system:
- Node.js (v22.12 or later)
- npm (v10 or later)
- Git (for cloning the repository)
- Ruby with the GitHub Pages gem used by the deployment workflow (
gem install github-pages -v 232) when previewing the documentation site
Development Environment Setup
1. Clone the Repository
git clone https://github.com/your-username/effetune.git
cd effetune
2. Install Dependencies
Install all required dependencies for the project:
npm install
This will install:
- Electron (as specified in
package.json) - Electron Builder
- Other dependencies required by the application
The committed .npmrc sets ignore-scripts=true, so no dependency runs a
preinstall, install, or postinstall script during any install in this
repository. Nothing in the tree needs one: Electron downloads its binary lazily
on first use rather than from an install script, esbuild resolves its executable
from the @esbuild/* platform package, and the remaining two packages that ship
install scripts (electron-winstaller, fsevents) are never on a path this
project builds. npm run check:install-scripts fails when that stops holding or
when the setting is removed, and it runs as part of npm run verify.
To run a blocked script deliberately, name its package; a plain npm rebuild
silently does nothing while the setting is active:
npm rebuild --ignore-scripts=false --foreground-scripts <package>
Because ignore-scripts also suppresses implicit pre/post hooks for
npm run, every script in package.json chains its prerequisites explicitly
with &&. Keep new scripts self-contained the same way instead of relying on a
pre<name> entry, which would be skipped without warning.
CI installs with npm ci --ignore-scripts and additionally runs
npm audit signatures, which rejects the run if any installed package fails to
match its registry signature. It also verifies that every workflow action is
pinned to a full commit SHA; see CONTRIBUTING.md for that convention.
3. Run Quality Checks
Run the default validation before handing code changes back:
npm run verify
This runs:
npm run assets:web:check: rebuilds the browser vendor assets and checks the committed PWA precache for freshness without writing itnpm run check:install-scripts: dependency install-script audit that fails when a package ships apreinstall,install, orpostinstallscript or whenignore-scriptsis removednpm run lint: ESLint checks for JavaScript syntax and high-confidence correctness hazards across Electron, renderer, plugin, feature, tool, and test codenpm test: Node.js tests with the repository’s coverage thresholds and test hygiene checks
The precache check never regenerates a stale sw-precache.js; if it fails, run
npm run assets:web and then rerun npm run verify.
Before every commit, run the owning audit and outdated checks for every dependency manifest. For the root npm dependency graph, run:
npm audit --audit-level=moderate
npm outdated
Also inspect all current Dependabot alerts and pull requests, including GitHub Actions updates. Resolve every available update in the prospective commit or an earlier local commit; routine and development-only updates are not deferred to a later Dependabot run.
Install or configure missing audit and analysis tooling as part of commit readiness. Run every check supported by the current host. When a check genuinely requires an unavailable operating system, hardware capability, credential, external service, or equivalent environment, record only that omitted scope and its residual risk and continue with the remaining checks; a missing local tool or ordinary configuration is not by itself an acceptable omission.
When dependency metadata changes, reproduce the CI install and supply-chain
checks before the normal verification. Do not use --force or
--legacy-peer-deps to conceal an incompatible update.
npm ci --ignore-scripts
npm audit signatures
npm run verify
For narrower verification, use:
npm run lint
npm test
Music Library Web correctness and scale diagnostics
The Web Music Library catalog uses the vendored official SQLite WASM build in a dedicated
Worker, with one opfs-sahpool connection and rollback journaling. The browser contract and
browser checks start and stop their own temporary loopback origin and use an isolated
Playwright browser context; do not start a separate development server.
Changes that affect Music Library storage, scanning, paging, search, durable operations, playlists, playback sequences, or artwork must run the browser contract:
npm run test:library-sqlite:web
Performance measurements are local, manually invoked development diagnostics. They are not
required before a commit or release, are not part of npm test or npm run verify, and must not
be added to GitHub Actions. The recommended production-path measurement uses one retained
reference-computer manifest; see tests/scale/README.md for the initialization and measurement
commands. You can also run the Web-only million-track diagnostic explicitly:
npm run test:library-scale:web-sqlite
Do not treat either result as a release gate or a general performance guarantee.
test:library-sqlite:webcovers fresh creation, reopen, Worker restart, the repository domains, one-to-two-character word-prefix search, three-or-more-character trigram substring search, message limits, foreign keys, and integrity.test:library-scale:referencemeasures the production Electron utility, Web catalog Worker, and AudioWorklet on the same retained reference computer.test:library-scale:web-sqlitewrites one million tracks through the production Web repository in bounded batches with realistic metadata and path lengths, verifies first/middle/end pages and the reopen order digest, and records insertion time, OPFS size, browser/Worker memory, and page and search timings.- SQLite vendor hashes and the Web precache are verified by
npm run assets:webandnpm run verifybefore the browser checks.
Release notes should state that EffeTune starts with a new Music Library, earlier Library state is not inherited, and folders must be added and scanned again. This is ordinary release information, not a migration detector or prerequisite workflow.
Changes to the power-saving policy, audio-pipeline lifetime, input ownership, or resume behavior must also pass the browser smoke test:
npx playwright install chromium
npm run test:power-browser
The Playwright install command is needed only when Chromium is not already available. The smoke-test runner starts and stops its own temporary loopback server; do not start a separate development server for this command.
Windows sleep-resume recovery also requires npm run test:rolling-pcm:electron.
For hardware verification, play audio through both standard and low-latency output,
put Windows to sleep, and confirm that playback and live input recover without a
page reload after waking. Check that the effect settings and playback position are
preserved. With audio intentionally suspended by the power policy, waking Windows
must leave it suspended; requesting audio again should recreate the audio resources
before resuming. Automated resume tests simulate the notification and resource
states; actual driver recovery requires this hardware check.
4. Build and Test the DSP Core
The committed WebAssembly DSP artifacts let JavaScript-only contributors run the app
without Emscripten. Changes under dsp/, plugins/dsp/, or a plugin’s DSP parameter
schema require the pinned toolchain recorded in dsp/EMSDK_VERSION (currently 6.0.11),
CMake 3.24 or newer, Ninja, Python 3.10 or newer, and a C++20 compiler.
npm run gen:dsp
npm run test:dsp:warnings
npm run test:dsp -- --native-build-type=Debug
npm run test:dsp -- --native-build-type=Release
npm run build:dsp
npm run test:dsp:parity
gen:dspvalidates everyparams.jsonand updates the generated C++ and JavaScript parameter layouts.test:dsp:warningsuses the pinned Emscripten Clang frontend to compile every native test source registered with CMake using warnings as errors, including-Wunused-but-set-variable.- The two
test:dspruns build the native core, allocation guard, and parity runner, then run CTest in both configurations used by CI. build:dspverifies the active Emscripten version and rebuilds the committed baseline and SIMD modules plus deterministic metadata underplugins/dsp/; it also runs the native-test warning check before building the modules.test:dsp:paritychecks both shipped modules against the committed JavaScript goldens.
Note Spectrogram ships fixed float32 HarmNet weights in the generated hex-float
header dsp/plugins/analyzer/note_spectrogram/harmnet_weights.h. Its adjacent
harmnet_weights.provenance.json records the architecture, calibration, artifact
digest, and dataset-level training proportions. Replace both when updating the
model, then regenerate its native parity goldens and DSP modules.
Rhythm Analyzer’s onset lanes (rhythm_d_low, rhythm_d_mid, and
rhythm_d_high in dsp/plugins/analyzer/rhythm_analyzer/) ship learned tree
models as .bin files with small JSON manifests. The shared
dsp/plugins/analyzer/tree_models/ folder
owns the format, the evaluators (heap_tree_model.h and oblivious_tree_model.h),
the tools (compact_model.py and embed_models.py), and models.cmake, which
lists every model and embeds it into the effetune_tree_models target. Replace a
complete binary and its manifest when updating a model; retain the training
provenance at dataset level and update the reference fixtures if the predictions
change. The binary format concatenates, in
order and all little-endian: split feature indices (uint8); split thresholds;
for index8 thresholds, the per-feature borders (IEEE 754 binary32) and their
start offsets (uint32); leaf values; and for integer leaves, one binary32 scale
per tree and output. Align each array to its element width with zero padding.
thresholdType is float (binary32 values) or index8 (indices into the
feature’s strictly increasing borders). leafType is float, double, int16,
or int8 (value = stored integer × scale). With "layout": "oblivious", each
tree stores one split per level, and split k sets bit k of the leaf index. The
manifest records format version 1, model dimensions, constants, output count,
layout, threshold and leaf types, the border count for index8, the source-model
hash, and the SHA-256 of the complete binary.
Export float thresholds and float or double leaves, then run
python compact_model.py <manifest.json> to rewrite the model in place. It
converts the thresholds to index8 when no feature has more than 256 distinct
thresholds, which is exact. Add --oblivious to store symmetric trees in the
oblivious layout, which is also exact, and --leaves int16 or --leaves int8 to
quantize float leaves; this is lossy, so accept it only after evaluating the
model’s predictions. The oblivious layout requires index8 thresholds and int16
or int8 leaves, and int8 leaves require the oblivious layout, so pass --leaves
together with --oblivious.
CMake runs embed_models.py when a model or its generator changes, validating the
hash, dimensions, feature and threshold indices, border order, and finite numeric
values. It produces small declaration headers and embeds the data directly in a
read-only section: assembler .incbin for Linux, macOS, and WASM, or a
relocation-free COFF object for MSVC x64 and ARM64. Generated files stay in the
build directory. Models require no runtime file access, decoding pass, allocation,
or extra copy, and do not pass through the C++ compiler as millions of numeric
literals. Binary inputs are hashed byte-for-byte
by the DSP artifact freshness check. Model reader tests run in native CTest.
Rhythm Analyzer’s beat path uses the fixed T48M causal TCN in
tc_tcn_weights.h: binary16 weights and float32 input normalization values.
tc_constants.h supplies derived frontend and rate-conversion tables;
rhythm_d_tables.h supplies the onset detector and supported-rate constants.
The RD6 decoder derives its state topology and transition constants during
Rd6Decoder::prepare; these are not learned parameters. Its
rd6_decoder.provenance.json records the decoder source and Python reference
hashes and the derivation settings.
Each shipped model and generated header has adjacent provenance describing its
artifact digest, dataset-level training information or derived-constant method,
and numerical or runtime contract. Update that provenance with the artifact;
keep individual input files and selection records private.
tools/rhythm-analyzer/export.py reproduces the frozen TCN export and generates
weight and frontend header candidates, while the tools in the same directory
provide the ordered numerical reference and evaluation checks. See
tools/rhythm-analyzer/README.md for the required inputs and commands. Normal
DSP builds compile or embed the committed artifacts without retraining or
regenerating their values.
Regenerate an affected golden whenever DSP behavior or an input that defines the golden changes. Those inputs include the reference implementation, cases, comparison policy or tolerance, and revision metadata; a metadata-only mismatch is still stale generated state. Exact native parity can also vary by compiler or architecture, so run the native acceptance path on every available CI-equivalent platform and report unavailable platforms as residual risk rather than changing a tolerance from CI evidence alone.
The root Node.js suite does not run installed Python wheel tests. Changes to a
DSP binding, generated cross-language contract, or its tests must also run that
binding’s package and acceptance checks. For Python, build and install a
candidate wheel, then use the same unittest, native-export audit, and golden
runner sequence defined in .github/workflows/dsp-library-ci.yml.
Set EMSDK to the activated SDK root on Windows. Use npm run build:dsp -- --check for
a write-free freshness check. Kernel preparation and instance creation run between audio quanta and may
grow WASM memory; processing itself must never allocate, lock, perform I/O, or grow
memory. See dsp/README.md for the ABI and kernel workflow.
Before rebuilding artifacts for a commit that changes C++ under dsp/, format the changed
sources and run the same repository-wide non-vendor check as the DSP Core workflow:
find dsp -path dsp/vendor -prune -o \( -name '*.cpp' -o -name '*.h' \) -print0 | xargs -0 clang-format --dry-run --Werror
On Windows PowerShell, use the equivalent check:
Get-ChildItem dsp -Recurse -File |
Where-Object { $_.Extension -in '.cpp', '.h' -and $_.FullName -notmatch '[\\/]dsp[\\/]vendor[\\/]' } |
ForEach-Object { clang-format --dry-run --Werror $_.FullName }
Use a current clang-format version that accepts the repository’s .clang-format; the LLVM
binary bundled with the current Visual Studio installation is suitable on Windows. A parser
or configuration error is a failed check. npm run verify does not include this C++ check.
Run formatting before npm run build:dsp because formatting changes the committed DSP source
digest. After the build, rerun it and confirm that no managed files change on the second run.
For a browser runtime check, open the served app, start the audio graph with a user
gesture, and confirm the console stays free of [dsp-wasm] warnings. Repeat once with
?dsp=off and confirm that the JavaScript compatibility path starts without any
[dsp-wasm] messages. Browsers that do not acknowledge a cloned compiled module are
retried automatically with the retained WASM bytes.
5. Run in Development Mode
To start the application in development mode:
npm start
To debug the web version in a browser with no-cache dynamic loading for plugins:
npm run dev
To test only the web app without building the DSP library or documentation site:
npm run dev -- --web-only
Open http://127.0.0.1:8000/effetune.html. This mode serves the working tree directly
with development cache suppression and uses the existing DSP artifacts. Ruby and
Jekyll are not required. Documentation pages are not rendered in this mode.
Add --port 8080 to use another port. Stop the server with Ctrl+C.
With the full npm run dev command, open:
http://localhost:8000/effetune.htmlfor the web apphttp://localhost:8000/for the local documentation site homehttp://localhost:8000/dsp/for the DSP library documentationhttp://localhost:8000/docs/i18n/ja/for a localized documentation page
The development server first builds the DSP browser package, builds _site with GitHub
Pages 232 in the production environment, and stages the complete DSP site snapshot under
the rendered guide. It then serves that output while Jekyll watches for changes, refreshing
the staged demo, schemas, catalog, LLM index, and site manifest after every Jekyll rebuild.
The initial build can take a few minutes. Documentation pages therefore use the real Liquid
layouts, kramdown renderer, navigation data, and permalink handling instead of a separate
development-only Markdown implementation. Web application assets still receive the
development server’s no-cache behavior.
Preview Multichannel UI Without Multichannel Hardware
After the app has loaded, run this in the developer Console:
uiManager.setDebugChannelCount(16);
This immediately refreshes the channel selectors, Matrix, Multi Channel Panel, Pipeline Analyzer controls, and channel-count label for layout inspection. It does not change the audio device, AudioContext, worklet, or DSP channel count. This is only a UI debug preview: playback, processing, analysis, and other operations may fail or disagree with the displayed channel count. Making those operations work in this mode is explicitly not a requirement; do not add compatibility fixes or tests requiring full functionality. Use it to inspect layouts, not to validate audio.
Pass an integer from 1 to 16 to preview another count. Clear the override with
uiManager.setDebugChannelCount(null) or reload the page. The override is not saved;
ordinary plugin edits made during the preview still follow normal save behavior.
Building the Application
EffeTune can be built as a portable application or as an installer. The build process is configured in the package.json file under the build section.
Build Configuration
The build configuration in package.json includes:
- appId:
com.frieve.effetune - productName:
EffeTune - Output directory:
dist - File associations:
.effetune_presetfiles - Build targets:
- Windows: NSIS installer and portable executable
- macOS: DMG (x64 and arm64 architectures)
- Linux: AppImage
Build Commands
To build the application, use the following npm commands:
- Build all versions:
npm run build - Build portable app only:
npm run build:portable - Build installer only:
npm run build:installer - Build macOS application (ARM64 only):
npm run build:mac:arm64 - Build macOS application (x64 only):
npm run build:mac:x64 - Build Linux application:
npm run build:linux - Clean the build directory:
npm run clean
The Electron build scripts and GitHub Pages workflow run npm run assets:web automatically before packaging or deployment. This regenerates the browser metadata parser bundle, its third-party notice file, and sw-precache.js. If you add or remove web assets outside those flows, run npm run assets:web before committing.
Keep each vendored library’s complete license and bundled dependency notices in
js/vendor/ beside its code. Update those notices when replacing a vendor file;
a license name or upstream link alone does not replace a required license text.
For desktop dependencies whose published package omits that text, retain the
upstream author and declared license in electron/THIRD_PARTY_NOTICES.txt.
Browser extension builds preserve legal comments and include the notices for
the vendor files they ship. Keep the extension’s vendor notice mapping current
when introducing another vendor file.
plugins/dsp/NOTICE.txt is the shared DSP and WebAssembly runtime notice,
including PFFFT, fdlibm, Emscripten, and musl. Desktop and web distributions
ship it under plugins/dsp/; the JavaScript package copies it to
dist/assets/NOTICE.txt, and the Python wheel installs it as
effetune/licenses/DSP-NOTICE.txt.
Keep public training-data records at dataset level, retaining the broad dataset names already published. Do not publish details identifying individual training files for reproducibility, including track IDs, file lists, paths, or hashes. Apply this granularity to the current worktree and future changes, and keep detailed usage and licensing evidence private. Model artifact hashes and structural metadata used to verify the shipped artifacts may remain public. Preserve notices required for third-party code and material actually redistributed; learning parameters from a dataset does not by itself establish a disclosure or attribution obligation.
The Tonal Balance EQ target-table generator publishes counts by style and license,
without individual track identifiers or input archive fingerprints. Verify this
with python -m unittest discover -s dsp/plugins/eq/tonal_balance_eq -p test_learn_targets.py.
Browser Extension
Build the Chrome and Edge extension separately from the desktop application:
npm run build:extension
The build writes the unpacked extension to out/extension/ and a distributable archive
to out/effetune-extension-<package.json version>.zip. The unpacked directory is the
manual-load target for Chrome or Edge; extract the ZIP before using Load unpacked.
Run the extension smoke check after changing its packaging, manifest, session handling, or editor integration:
npm run test:extension-browser
The extension is its own Manifest V3 package. Do not add extension-only files or assets
to the desktop and Web/PWA packages, and keep the generated out/ artifacts untracked.
Web and PWA Assets
The web app uses manifest.json, sw.js, and generated sw-precache.js for installable/offline app-shell support. Service Worker registration is web-only and is skipped in Electron.
Before release, verify that the web app loads normally, can be installed where supported, and still opens after going offline once the app shell has been cached.
OpenHome Sidecar
The native OpenHome sidecar requires Node.js, npm, CMake 3.21 or newer, and a 64-bit native C++ toolchain. Platform prerequisites are:
- Windows x64: Visual Studio 2022 C++ build tools, including the x64 compiler and NMake.
- macOS x64 or arm64: Xcode Command Line Tools, CMake, and Make. Build each architecture on its matching GitHub Actions runner or host architecture.
- Linux x64: GCC or Clang, CMake, Make, pkg-config,
libnl-3-dev,libnl-genl-3-dev,dpkg-dev,readelf, andldd. Exact source bundle generation also requires enableddeb-srcentries for the same Ubuntu repositories that supplied the installed binary packages.
Use the canonical producer before packaging:
npm run build:openhome-sidecar -- --no-publish-development
For macOS, select exactly one architecture on both the producer and electron-builder command line. The maintained package entry points do this and start from a clean output directory:
npm run build:mac:x64
npm run build:mac:arm64
The producer downloads revisions pinned in
native/openhome-sidecar/dependencies.lock.json, verifies every archive’s
SHA-256 hash, and reuses the ignored tmp/cache/openhome-sidecar/ directory.
It runs CTest and a stdio handshake smoke, then writes one of:
out/native/openhome-sidecar/win32-x64/effetune-openhome-sidecar.exeout/native/openhome-sidecar/darwin-x64/effetune-openhome-sidecarout/native/openhome-sidecar/darwin-arm64/effetune-openhome-sidecarout/native/openhome-sidecar/linux-x64/effetune-openhome-sidecar
Linux builds dynamically link libnl. The producer copies the exact libnl and
libnl-genl shared objects resolved by the build host’s loader beside the
sidecar, and the executable resolves them through $ORIGIN. The AppImage keeps
those files beside the sidecar under resources/openhome/ and includes the
tracked libnl license text. On Linux, the canonical producer also writes
libnl-runtime-manifest.json with each packaged binary’s SHA-256, exact dpkg
package/version/architecture, and exact source package/version before packaging
can begin. npm run smoke:openhome-package verifies that manifest against the
package contents and, on Linux, verifies packaged loader resolution.
Tagged desktop release builds enable Ubuntu deb-src entries and run:
npm run collect:openhome-linux-provenance -- --with-source
npm run verify:openhome-linux-provenance -- --require-source
This downloads the exact Debian source package set referenced by the installed
libnl binaries, verifies the .dsc SHA-256 list and dpkg-source extraction,
and fails the release if the upstream source or distribution patch/build
archive is missing. The Linux release artifact contains both
EffeTune-<version>-Linux-AppImage.zip and
EffeTune-<version>-OpenHome-Linux-Source.zip; the latter contains the source
files and the same provenance manifest shipped inside the AppImage.
Use npm run pack:win for an unpacked Windows package and smoke check, or
npm run build:linux for the Linux AppImage. The macOS commands above produce
one DMG architecture per clean build.
Desktop release packaging runs only in Frieve-A/effetune for an exact
v${package.version} tag. A preflight job must succeed before any platform job
runs. That preflight performs the full source verification once; the platform
jobs retain only host-filesystem checks plus packaged DSP and OpenHome smoke
checks. The Windows, macOS, and Linux jobs produce the same unsigned packages
as the maintained platform build commands. Central CI verifies the app’s DSP
core on a desktop tag but leaves desktop package production to this release
workflow, and it does not rebuild the separately released Python/npm DSP
Library matrix. Tags beginning with dsp-v belong to the separate DSP library
release workflow and cannot start the desktop release workflow.
For a Windows release, attach latest.yml and
EffeTune-<version>-Setup.exe.blockmap beside the NSIS installer. The in-app
updater requires these files. They are generated for that exact installer, so
do not combine a regenerated installer with metadata from another build. The
updater reads them from the v<version> release it selected, never from the
newest release of the repository, which is often a DSP library release.
Build Output
After a successful build, you’ll find the following in the dist directory:
- Windows Portable application:
EffeTune-x.xx.x-Portable.exe(where x.xx.x is the version number) - Windows Installer:
EffeTune-x.xx.x-Setup.exe(NSIS installer) - Windows update metadata:
latest.yml - Windows installer block map:
EffeTune-x.xx.x-Setup.exe.blockmap - macOS application:
EffeTune-x.xx.x-x64.dmg(Intel Mac)EffeTune-x.xx.x-arm64.dmg(Apple Silicon Mac)
- Linux application:
EffeTune-x.xx.x.AppImage - Other build artifacts: Various files created during the build process
The file naming convention has been configured in the package.json file to clearly distinguish between the portable application and the installer.
Application Structure
The EffeTune Electron application consists of several key components:
Main Process (main.js)
The main process is responsible for:
- Creating and managing the application window
- Setting up the application menu
- Handling IPC (Inter-Process Communication) with the renderer process
- Managing file system operations
- Handling audio device enumeration
Preload Script (preload.js)
The preload script securely exposes Electron APIs to the renderer process through the contextBridge:
- File system operations
- Documentation rendering
- Audio device operations
- IPC event listeners
Electron Integration (js/electron-integration.js)
This module integrates the web application with Electron-specific features:
- Detecting the Electron environment
- Handling file import/export
- Managing audio preferences
- Processing audio files
- Displaying dialogs
Customizing the Build
Application Icon
To change the application icon:
- Replace
images/favicon.ico(Windows) andimages/icon.png(macOS/Linux) with your custom icons - Ensure the icons are referenced correctly in the
buildsection ofpackage.json
Application Metadata
To modify application metadata:
- Update the relevant fields in
package.json:nameversiondescriptionauthorlicense
Installer Options
To customize the installer behavior:
- Modify the
nsissection in thebuildconfiguration inpackage.json
Bundled Files
The build.files array in package.json is an explicit allowlist of top-level directories and files to bundle into the application. This keeps repo-only assets (Jekyll site files, dev scripts, docs metadata, untracked work-in-progress files outside the allowlisted directories, etc.) out of the installer.
When adding a new top-level directory or root file that must ship with the app, add a matching entry to build.files. Otherwise the build will silently omit it.
Application stylesheets in css/ and root web assets such as sw.js, sw-precache.js, manifest.json, icons, screenshots, and vendor scripts must be included when they are required at runtime.
Troubleshooting
Common Build Issues
- Missing dependencies:
- Ensure all dependencies are installed with
npm install - Check for any peer dependency warnings
- Ensure all dependencies are installed with
- Electron download fails:
- Check your internet connection
- Antivirus blocking the build:
- Temporarily disable antivirus software
- Add exceptions for the project directory
Runtime Issues
- Audio device access problems:
- Ensure proper permissions are granted to the application
- Check the audio device configuration in the application settings
- File association issues:
- Reinstall the application using the installer
- Manually associate
.effetune_presetfiles with the application
Distribution
After building the application:
- Testing:
- Test the application thoroughly on the target platforms
- Verify all features work as expected
- Distribution:
- Upload the installer and/or portable application to your distribution platform
- Update the download links in your documentation
- Updates:
- Increment the version number in
package.jsonfor new releases - For Windows installer releases, upload the matching
latest.ymland installer block map with the installer so the in-app update can download it
- Increment the version number in