feat(stages): add tremolo effect with sine→square killswitch shape#258
Merged
Conversation
Amplitude-modulation effect registered as an Effect-category stage, appearing in the Effects tab alongside Delay/Reverb/EQ. A phase-accumulator sine LFO modulates signal gain. A continuous Shape control morphs the LFO from a smooth sine (vintage tremolo) toward a hard square via tanh waveshaping — at full Depth + full Shape this is a square-wave "killswitch" stutter (Tom Morello toggle-switch chop). Depth is one-pole smoothed to avoid zipper noise; the LFO output is left unsmoothed so square edges stay crisp. Controls: Rate (0.1–20 Hz), Depth (0–100%), Shape (sine→square). Wires the standard stage-registration surface: core stage + config, StageType/StageConfig, UI view + gui_stage_registry, EN/ZH i18n, minimap abbreviation, and plugin per-slot params. Covered by 9 unit tests (passthrough, full-chop silence/unity, unit-range gain, LFO periodicity, sine fidelity, validation, clamping).
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new Tremolo effect stage (amplitude modulation via an LFO) across the core DSP, UI stage registry/view, localization, minimap labeling, and plugin parameter surfaces so it can be inserted and automated like existing Effects stages.
Changes:
- Implemented a new
TremoloStage+TremoloConfiginrustortion-core, wired intoStageType/StageConfig. - Registered the Tremolo stage in the UI (stage registry + dedicated view) and extended EN/ZH translations + minimap abbreviation.
- Added per-slot Tremolo automation parameter structs/arrays in the plugin params.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| rustortion-core/src/amp/stages/tremolo.rs | New DSP stage implementation + unit tests for tremolo LFO, shaping, and parameter validation. |
| rustortion-core/src/amp/stages/mod.rs | Exposes the new tremolo stage module. |
| rustortion-core/src/preset/stage_config.rs | Adds Tremolo to stage enums/config wiring and marks it as an Effect-category stage. |
| rustortion-ui/src/stages/tremolo.rs | New UI view + message/apply plumbing for the tremolo controls. |
| rustortion-ui/src/stages/mod.rs | Registers Tremolo in the gui_stage_registry! so it appears as a selectable stage. |
| rustortion-ui/src/i18n/mod.rs | Adds Tremolo label + control labels (rate, depth, shape) for EN and ZH_CN. |
| rustortion-ui/src/components/minimap.rs | Adds a minimap abbreviation for Tremolo stages. |
| rustortion-plugin/src/params.rs | Adds TremoloSlotParams and an 8-slot tremolo params array for host automation parity. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+69
to
+72
| // Morph sine -> square. At `MIN_DRIVE` the ratio reproduces `raw`; | ||
| // at `MAX_DRIVE` it clamps to ~±1 everywhere but the zero crossings. | ||
| let drive = (MAX_DRIVE - MIN_DRIVE).mul_add(self.shape, MIN_DRIVE); | ||
| let sharp = (raw * drive).tanh() / drive.tanh(); |
…test
Address review feedback on the tremolo stage:
- Cache `drive` and `drive_norm = 1/tanh(drive)` in the stage and refresh
them only in `new()` and on `set_parameter("shape", _)`, instead of
recomputing `drive.tanh()` every sample. Saves one tanh per sample on
the audio thread; the per-sample numerator is unchanged. Output is
bit-for-bit equivalent (same formula, just hoisted).
- Add `tremolo_stage_does_not_allocate` to the no_alloc RT-safety suite,
matching the convention every other effect stage follows.
- Add `set_shape_matches_constructed` guarding the new cache: changing
shape via set_parameter must match a stage built with that shape.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a Tremolo effect — amplitude modulation by an LFO — registered as an
Effect-category stage. It shows up in the Effects tab next to Delay/Reverb/EQ.A phase-accumulator sine LFO modulates signal gain. A continuous Shape control morphs the LFO from a smooth sine (vintage tremolo) toward a hard square via
tanhwaveshaping. At full Depth + full Shape this becomes a square-wave killswitch stutter — the Tom Morello toggle-switch chop — in a single stage.Controls
DSP notes
[1 − depth, 1], so full depth dips all the way to silence at each trough.Surface touched
Standard stage-registration set:
rustortion-core— newtremolo.rsstage +TremoloConfig;StageType/StageConfigarms (category → Effect)rustortion-ui— newtremolo.rsview (3 sliders) +gui_stage_registry!line; EN/ZH i18n (stage_tremolo,rate,depth,shape); minimap abbreviationrustortion-plugin—TremoloSlotParams+ per-slot array (host-automation parity)Tests
9 new core unit tests: dry passthrough at depth 0, full-chop silence + unity at the killswitch extreme, gain stays in
[0,1], LFO periodicity, sine fidelity at shape 0, parameter validation, constructor clamping, default config.Verification
cargo fmt --all— cleancargo clippy --workspace --all-targets -D warnings -D clippy::all -D clippy::pedantic -D clippy::nursery— cleanmake test— 162 core tests pass (incl. 9 new tremolo)Follow-ups (deferred)