Demo XFade + Release Alignment + Audio Device Robustness + other enhancements
This release contains experimental audio, loading and stability improvements for GrandOrgue, based on upstream version 3.17.3.
The main new addition in this build is an audio device robustness layer. It is intended to make GrandOrgue behave more gracefully when an audio device disappears, a USB audio interface is unplugged/replugged, or the operating system enters suspend/resume.
As before, this is an experimental demo build. The features are useful for testing and feedback, but some parts are not upstream-ready yet.
Audio Device Robustness (feature/audio-device-robustness) — EXPERIMENTAL
This release reworks how GrandOrgue talks to the audio driver.
Previously, several audio driver operations could happen directly from the caller path. That is fragile with some real-world audio drivers, especially USB audio interfaces and drivers that block, hang, or behave badly when the device is removed or the system goes to sleep.
This build routes audio device lifecycle operations through a dedicated persistent worker thread and tracks the device state explicitly.
Current implementation details:
- audio driver calls are serialized through one worker thread
- device enumeration is routed through the same worker path
- "Open()", "StartStream()" and "Close()" are no longer scattered across unrelated caller threads
- device lifecycle states are tracked explicitly
- device-lost situations can be detected and handled
- automatic reconnect retry while the device is in "DEVICE_LOST" state
- retry interval currently tuned to 500 ms
- audio callback watchdog detects when callbacks stop arriving
- Windows suspend/resume events are handled:
- before suspend, GrandOrgue closes the audio device
- after resume, GrandOrgue reopens the audio device if it was previously running
- routine suspend/resume messages are logged less aggressively
- logging from realtime-sensitive audio paths was reduced or removed
- exceptions in audio worker tasks are caught instead of crashing the application
- closing a device that is already known to be lost avoids unsafe driver calls where possible
In practice, this should make GrandOrgue much more robust with USB audio interfaces. Unplugging and replugging an interface should no longer necessarily require restarting GrandOrgue.
This is especially useful for systems where the audio driver does not survive sleep/wakeup cleanly, or where unplugging a USB audio interface previously left GrandOrgue in a broken audio state.
Known limitations:
- This cannot fix every possible driver bug.
- If the operating system exposes the reconnected device as a different device, manual selection may still be required.
- Suspend/resume handling is currently most relevant on Windows.
- More testing with different audio backends and USB interfaces is welcome.
Release Alignment (feature/release-alignment) — EXPERIMENTAL
Adds a correlation-based release alignment system.
When a key is released, GrandOrgue has to switch from the currently playing sustain loop to a separate release sample. If the waveform phase does not match well at that point, this can produce clicks, rough transitions, or unstable release onsets. This is especially noticeable with short key presses, short release samples, or sample sets where the release phase does not naturally line up with the sustain loop.
This feature analyses the attack/sustain sample and the corresponding release sample during organ loading and builds a small per-pipe lookup table. At runtime, GrandOrgue uses this table to choose a better release start position depending on the current loop position / key hold duration.
The goal is to reduce phase-related clicks and make release transitions smoother and more natural.
Current implementation details:
- correlation-based matching between sustain-loop windows and release-sample windows
- sparse per-pipe lookup table instead of a full brute-force table
- runtime interpolation between LUT points
- support for different release ranges / key-hold durations
- improved period handling for non-octave stops, aliquots, mixtures and small-period cases
- fallback behaviour for cases where no reliable LUT can be built
- optional diagnostic logging and Python verification tools for comparing GrandOrgue’s generated LUT with the reference algorithm
This is still experimental. The algorithm has already been tested on large sample sets, but edge cases are still possible, especially with noisy releases, unusual loops, very short periods, or difficult mixtures.
Crossfade Curves (feature/crossfade-curves)
Adds selectable crossfade curve shapes for smoother transitions between the sustain loop and the release sample:
- Linear — simple straight-line fade
- Sin Equal Power — sine-based equal-power crossfade
- Sin² — squared sine curve
- Sqrt Equal Power — square-root equal-power curve
- X² — squared linear curve
The active curve can be selected from the Audio menu / function-key shortcuts.
A small lookup table cache is used for the curve calculation, avoiding expensive per-sample "sin()" or "sqrt()" calls in the audio thread.
Note: the current F12 mode is a diagnostic instant-switch mode without crossfade. It is expected to click. This mode is useful for testing whether release alignment itself is working, because it makes phase mismatches very obvious.
Loading Progress Improvements (feature/progress-improvements)
Improves feedback while loading large organs:
- monotone progress bar with no jumps backwards
- more realistic ETA calculation
- progress reporting during ODF parsing and model-building phases
- individual loading steps for ranks, manuals, stops, couplers and tremulants
- loading can be cancelled earlier, not only during the final wave-loading phase
- typed abort handling for early and partial cancellation
- central "GOProgressMonitor" interface
- optional timing / GUI gap profiling macros, off by default
This is especially noticeable with large sample sets where ODF parsing and internal data-structure creation can take a significant amount of time.
Polyphony Load Dropping (feature/polyphony-load-dropping)
Improves voice stealing when the CPU is under heavy load:
- panic mode starts earlier to avoid audio dropouts
- new soft-drop path at 80% of the soft polyphony limit
- randomized fade-out times for more natural-sounding voice stealing
- avoids many voices being dropped with identical fade timing
The goal is not to make overload inaudible, but to fail more gracefully when the configured polyphony limit is too high for the current system.
RAM Limit Warning (feature/memory-limit-warning)
Adds a live warning indicator in the settings when the configured RAM limit exceeds 85% of available system memory.
The warning is shown in red, helping the user notice potentially unsafe settings before loading a very large organ.
Release Gain Scaling (feature/release-scaling) — EXPERIMENTAL / WIP
Scales the release sample gain depending on how long a key was held.
Short key presses produce softer releases, while longer key holds produce fuller releases. This is intended to model the fact that a pipe has not necessarily reached its full steady-state amplitude during very short attacks.
Current state:
- release gain is scaled by actual hold time
- selected Chamade test values are hardcoded for proof-of-concept testing
- general pipes use a simple fallback model
- debug code is present but disabled by default
This is still a proof of concept. The current version mainly uses default / hardcoded parameters. The long-term goal would be to make per-pipe parameters readable from the ODF if the feature proves useful enough.
Not recommended for production use yet.
Additional fixes and cleanup
This build also includes several smaller fixes and development improvements:
- fixed an output task / meter info update overflow
- improved behaviour when closing a port that is already known to be device-lost
- reduced unsafe logging from realtime-sensitive audio paths
- improved Windows debug-symbol build handling
- fixed macOS bundle/build issues around Berkeley DB dependencies
- restored release crossfade behaviour after upstream merge regressions
- general clang-format / cleanup work
Notes
- Based on GrandOrgue upstream 3.17.3
- Main features are kept in separate feature branches where possible
- Audio Device Robustness is experimental and needs testing with different drivers and USB audio interfaces
- Release Alignment is experimental and should be tested with different sample sets
- Release Gain Scaling is a proof of concept and not upstream-ready
- F12 is currently a diagnostic no-crossfade / instant-switch mode and is expected to click
- Windows, Linux, AppImage and macOS builds are provided where CI packaging succeeds
Feedback is very welcome, especially about:
- USB audio device removal / reconnect behaviour
- suspend/resume behaviour
- ASIO / WASAPI / ALSA / CoreAudio driver differences
- release alignment quality on difficult sample sets
- regressions compared to official GrandOrgue