diff --git a/data/presets/AudioFileProcessor/Erazor.xpf b/data/presets/AudioFileProcessor/Erazor.xpf index c448829fad8..4b55b2d52f3 100644 --- a/data/presets/AudioFileProcessor/Erazor.xpf +++ b/data/presets/AudioFileProcessor/Erazor.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + @@ -42,7 +42,7 @@ - + diff --git a/data/presets/AudioFileProcessor/SString.xpf b/data/presets/AudioFileProcessor/SString.xpf index 6e5214b0dea..6ade93d1dbf 100644 --- a/data/presets/AudioFileProcessor/SString.xpf +++ b/data/presets/AudioFileProcessor/SString.xpf @@ -16,7 +16,7 @@ - + @@ -28,11 +28,11 @@ - + - + @@ -48,7 +48,7 @@ - + diff --git a/data/presets/AudioFileProcessor/orion.xpf b/data/presets/AudioFileProcessor/orion.xpf index 0b11e00cf29..767c0cb24e1 100644 --- a/data/presets/AudioFileProcessor/orion.xpf +++ b/data/presets/AudioFileProcessor/orion.xpf @@ -16,7 +16,7 @@ - + @@ -32,7 +32,7 @@ - + @@ -44,7 +44,7 @@ - + diff --git a/data/presets/BitInvader/alien_strings.xpf b/data/presets/BitInvader/alien_strings.xpf index 938b4be36db..6201150fcf0 100644 --- a/data/presets/BitInvader/alien_strings.xpf +++ b/data/presets/BitInvader/alien_strings.xpf @@ -14,7 +14,7 @@ - + diff --git a/data/presets/BitInvader/drama.xpf b/data/presets/BitInvader/drama.xpf index d0ca7ed45b1..f5b4d564d8b 100644 --- a/data/presets/BitInvader/drama.xpf +++ b/data/presets/BitInvader/drama.xpf @@ -14,7 +14,7 @@ - + diff --git a/data/presets/BitInvader/invaders_must_die.xpf b/data/presets/BitInvader/invaders_must_die.xpf index bbdbbbbfe7f..6a5dda6b70a 100644 --- a/data/presets/BitInvader/invaders_must_die.xpf +++ b/data/presets/BitInvader/invaders_must_die.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/data/presets/BitInvader/pluck.xpf b/data/presets/BitInvader/pluck.xpf index b71b696c1dc..b2c56766c85 100644 --- a/data/presets/BitInvader/pluck.xpf +++ b/data/presets/BitInvader/pluck.xpf @@ -14,7 +14,7 @@ - + diff --git a/data/presets/Kicker/Clap dry.xpf b/data/presets/Kicker/Clap dry.xpf index 05bc0a8003a..abc6b6c048a 100644 --- a/data/presets/Kicker/Clap dry.xpf +++ b/data/presets/Kicker/Clap dry.xpf @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ - + diff --git a/data/presets/Kicker/Clap.xpf b/data/presets/Kicker/Clap.xpf index 66cac9a9149..b3a23dd8b99 100644 --- a/data/presets/Kicker/Clap.xpf +++ b/data/presets/Kicker/Clap.xpf @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ - + diff --git a/data/presets/Kicker/SnareMarch.xpf b/data/presets/Kicker/SnareMarch.xpf index 563f3384356..04a44fc3f76 100644 --- a/data/presets/Kicker/SnareMarch.xpf +++ b/data/presets/Kicker/SnareMarch.xpf @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -46,7 +46,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -104,7 +104,7 @@ - + @@ -137,7 +137,7 @@ - + diff --git a/data/presets/LB302/AcidLead.xpf b/data/presets/LB302/AcidLead.xpf index af7be34fcf9..ec127a54c8c 100644 --- a/data/presets/LB302/AcidLead.xpf +++ b/data/presets/LB302/AcidLead.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/LB302/AngryLead.xpf b/data/presets/LB302/AngryLead.xpf index 1ad94ea1bb9..b3665f7cffe 100644 --- a/data/presets/LB302/AngryLead.xpf +++ b/data/presets/LB302/AngryLead.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/LB302/STrash.xpf b/data/presets/LB302/STrash.xpf index c6d3cf48b0f..c8a1ad712a5 100644 --- a/data/presets/LB302/STrash.xpf +++ b/data/presets/LB302/STrash.xpf @@ -8,18 +8,18 @@ - + - + - + diff --git a/data/presets/Monstro/Growl.xpf b/data/presets/Monstro/Growl.xpf index d21804885cf..de115bdaaf5 100644 --- a/data/presets/Monstro/Growl.xpf +++ b/data/presets/Monstro/Growl.xpf @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -44,11 +44,11 @@ - + - + @@ -62,7 +62,7 @@ - + @@ -74,7 +74,7 @@ - + diff --git a/data/presets/Monstro/HorrorLead.xpf b/data/presets/Monstro/HorrorLead.xpf index fbe2639bc4f..cb2cafbfa20 100644 --- a/data/presets/Monstro/HorrorLead.xpf +++ b/data/presets/Monstro/HorrorLead.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + @@ -42,7 +42,7 @@ - + diff --git a/data/presets/Monstro/Phat.xpf b/data/presets/Monstro/Phat.xpf index ec572d73354..f2c0b9fe0f1 100644 --- a/data/presets/Monstro/Phat.xpf +++ b/data/presets/Monstro/Phat.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/Monstro/ScaryBell.xpf b/data/presets/Monstro/ScaryBell.xpf index 034521ad426..c441c19e39c 100644 --- a/data/presets/Monstro/ScaryBell.xpf +++ b/data/presets/Monstro/ScaryBell.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/data/presets/Nescaline/Detune_lead.xpf b/data/presets/Nescaline/Detune_lead.xpf index 94173d6909d..29f2a82dde6 100644 --- a/data/presets/Nescaline/Detune_lead.xpf +++ b/data/presets/Nescaline/Detune_lead.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/Nescaline/Fireball_flick.xpf b/data/presets/Nescaline/Fireball_flick.xpf index c2ce19aaaee..a84d7075c67 100644 --- a/data/presets/Nescaline/Fireball_flick.xpf +++ b/data/presets/Nescaline/Fireball_flick.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/OpulenZ/Bagpipe.xpf b/data/presets/OpulenZ/Bagpipe.xpf index 41a80c1e312..aedf62c50b3 100644 --- a/data/presets/OpulenZ/Bagpipe.xpf +++ b/data/presets/OpulenZ/Bagpipe.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/OpulenZ/Combo_organ.xpf b/data/presets/OpulenZ/Combo_organ.xpf index 457c3f31866..7828ba50233 100644 --- a/data/presets/OpulenZ/Combo_organ.xpf +++ b/data/presets/OpulenZ/Combo_organ.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/OpulenZ/Funky.xpf b/data/presets/OpulenZ/Funky.xpf index 5394d54dbc8..df323a99938 100644 --- a/data/presets/OpulenZ/Funky.xpf +++ b/data/presets/OpulenZ/Funky.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/OpulenZ/Harp.xpf b/data/presets/OpulenZ/Harp.xpf index c78e4e8964c..c5a894669de 100644 --- a/data/presets/OpulenZ/Harp.xpf +++ b/data/presets/OpulenZ/Harp.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/OpulenZ/Organ_leslie.xpf b/data/presets/OpulenZ/Organ_leslie.xpf index 6d1bfbe77ea..57ccd784591 100644 --- a/data/presets/OpulenZ/Organ_leslie.xpf +++ b/data/presets/OpulenZ/Organ_leslie.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/OpulenZ/Square.xpf b/data/presets/OpulenZ/Square.xpf index 349debf6bc5..6a5109d9497 100644 --- a/data/presets/OpulenZ/Square.xpf +++ b/data/presets/OpulenZ/Square.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/Organic/Pwnage.xpf b/data/presets/Organic/Pwnage.xpf index 39aac12e749..48874af108f 100644 --- a/data/presets/Organic/Pwnage.xpf +++ b/data/presets/Organic/Pwnage.xpf @@ -16,7 +16,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -66,7 +66,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -98,7 +98,7 @@ - + @@ -112,7 +112,7 @@ - + diff --git a/data/presets/Organic/Rubberband.xpf b/data/presets/Organic/Rubberband.xpf index 2e65f8c6ee2..da4a56f56d3 100644 --- a/data/presets/Organic/Rubberband.xpf +++ b/data/presets/Organic/Rubberband.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/SID/CheesyGuitar.xpf b/data/presets/SID/CheesyGuitar.xpf index 5e5e2e348a8..cea9adab870 100644 --- a/data/presets/SID/CheesyGuitar.xpf +++ b/data/presets/SID/CheesyGuitar.xpf @@ -16,7 +16,7 @@ - + @@ -25,7 +25,7 @@ - + diff --git a/data/presets/SID/MadMind.xpf b/data/presets/SID/MadMind.xpf index a5c2d2bf6b7..910786f87a5 100644 --- a/data/presets/SID/MadMind.xpf +++ b/data/presets/SID/MadMind.xpf @@ -16,7 +16,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/data/presets/SID/Overdrive.xpf b/data/presets/SID/Overdrive.xpf index fcfa8a86333..c947de3c2bb 100644 --- a/data/presets/SID/Overdrive.xpf +++ b/data/presets/SID/Overdrive.xpf @@ -16,7 +16,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -39,7 +39,7 @@ - + diff --git a/data/presets/TripleOscillator/Bell.xpf b/data/presets/TripleOscillator/Bell.xpf index 181462ac99d..6681d9094e2 100644 --- a/data/presets/TripleOscillator/Bell.xpf +++ b/data/presets/TripleOscillator/Bell.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/BrokenToy.xpf b/data/presets/TripleOscillator/BrokenToy.xpf index b12a57e8c7c..5ad1e3c1a6d 100644 --- a/data/presets/TripleOscillator/BrokenToy.xpf +++ b/data/presets/TripleOscillator/BrokenToy.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/CryingPads.xpf b/data/presets/TripleOscillator/CryingPads.xpf index 47ec11889f5..99976ed298d 100644 --- a/data/presets/TripleOscillator/CryingPads.xpf +++ b/data/presets/TripleOscillator/CryingPads.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/DetunedGhost.xpf b/data/presets/TripleOscillator/DetunedGhost.xpf index e72a6e365f5..5a98f06202a 100644 --- a/data/presets/TripleOscillator/DetunedGhost.xpf +++ b/data/presets/TripleOscillator/DetunedGhost.xpf @@ -18,7 +18,7 @@ - + diff --git a/data/presets/TripleOscillator/DirtyReece.xpf b/data/presets/TripleOscillator/DirtyReece.xpf index 095c3e66525..96d15f7be43 100644 --- a/data/presets/TripleOscillator/DirtyReece.xpf +++ b/data/presets/TripleOscillator/DirtyReece.xpf @@ -16,7 +16,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -63,7 +63,7 @@ - + diff --git a/data/presets/TripleOscillator/Drums_HardKick.xpf b/data/presets/TripleOscillator/Drums_HardKick.xpf index 104c4066e4b..4be935391b5 100644 --- a/data/presets/TripleOscillator/Drums_HardKick.xpf +++ b/data/presets/TripleOscillator/Drums_HardKick.xpf @@ -16,7 +16,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -70,7 +70,7 @@ - + @@ -88,7 +88,7 @@ - + diff --git a/data/presets/TripleOscillator/Drums_Kick.xpf b/data/presets/TripleOscillator/Drums_Kick.xpf index 30c8284e6a5..b65e9d18c11 100644 --- a/data/presets/TripleOscillator/Drums_Kick.xpf +++ b/data/presets/TripleOscillator/Drums_Kick.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/Drums_Snare.xpf b/data/presets/TripleOscillator/Drums_Snare.xpf index 62f6c55dbd3..40d6d6ae74d 100644 --- a/data/presets/TripleOscillator/Drums_Snare.xpf +++ b/data/presets/TripleOscillator/Drums_Snare.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/E-Organ2.xpf b/data/presets/TripleOscillator/E-Organ2.xpf index cc96f9e76f7..e2a50c10aec 100644 --- a/data/presets/TripleOscillator/E-Organ2.xpf +++ b/data/presets/TripleOscillator/E-Organ2.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/ElectricOboe.xpf b/data/presets/TripleOscillator/ElectricOboe.xpf index 70035a87f25..474e8553492 100644 --- a/data/presets/TripleOscillator/ElectricOboe.xpf +++ b/data/presets/TripleOscillator/ElectricOboe.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/data/presets/TripleOscillator/Erazzor.xpf b/data/presets/TripleOscillator/Erazzor.xpf index 3f9762190cd..fb1389d5606 100644 --- a/data/presets/TripleOscillator/Erazzor.xpf +++ b/data/presets/TripleOscillator/Erazzor.xpf @@ -16,7 +16,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -110,7 +110,7 @@ - + diff --git a/data/presets/TripleOscillator/FuzzyAnalogBass.xpf b/data/presets/TripleOscillator/FuzzyAnalogBass.xpf index 82c3f72e536..13ff3d369c8 100644 --- a/data/presets/TripleOscillator/FuzzyAnalogBass.xpf +++ b/data/presets/TripleOscillator/FuzzyAnalogBass.xpf @@ -17,7 +17,7 @@ - + diff --git a/data/presets/TripleOscillator/Garfunkel.xpf b/data/presets/TripleOscillator/Garfunkel.xpf index 0e3ba9a2471..bad7bd9b498 100644 --- a/data/presets/TripleOscillator/Garfunkel.xpf +++ b/data/presets/TripleOscillator/Garfunkel.xpf @@ -16,7 +16,7 @@ - + @@ -25,7 +25,7 @@ - + @@ -39,7 +39,7 @@ - + @@ -51,7 +51,7 @@ - + diff --git a/data/presets/TripleOscillator/GhostBoy.xpf b/data/presets/TripleOscillator/GhostBoy.xpf index 90ea1fceae2..2062c2d3281 100644 --- a/data/presets/TripleOscillator/GhostBoy.xpf +++ b/data/presets/TripleOscillator/GhostBoy.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + @@ -46,7 +46,7 @@ - + diff --git a/data/presets/TripleOscillator/OldComputerGames.xpf b/data/presets/TripleOscillator/OldComputerGames.xpf index c19b3e3525e..f3dded4c428 100644 --- a/data/presets/TripleOscillator/OldComputerGames.xpf +++ b/data/presets/TripleOscillator/OldComputerGames.xpf @@ -16,7 +16,7 @@ - + @@ -32,7 +32,7 @@ - + @@ -50,7 +50,7 @@ - + @@ -61,7 +61,7 @@ - + diff --git a/data/presets/TripleOscillator/PM-FMstring.xpf b/data/presets/TripleOscillator/PM-FMstring.xpf index 485a570f666..f55be6ded04 100644 --- a/data/presets/TripleOscillator/PM-FMstring.xpf +++ b/data/presets/TripleOscillator/PM-FMstring.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/PMFMFTWbass.xpf b/data/presets/TripleOscillator/PMFMFTWbass.xpf index 62ce53ab5f3..a48e131f9f6 100644 --- a/data/presets/TripleOscillator/PMFMFTWbass.xpf +++ b/data/presets/TripleOscillator/PMFMFTWbass.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/data/presets/TripleOscillator/PMbass.xpf b/data/presets/TripleOscillator/PMbass.xpf index 9c0f062c9f2..85765a6fc97 100644 --- a/data/presets/TripleOscillator/PMbass.xpf +++ b/data/presets/TripleOscillator/PMbass.xpf @@ -16,11 +16,11 @@ - + - + @@ -36,7 +36,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -62,7 +62,7 @@ - + diff --git a/data/presets/TripleOscillator/PercussiveBass.xpf b/data/presets/TripleOscillator/PercussiveBass.xpf index c9ebd118a7b..555fa03f0a7 100644 --- a/data/presets/TripleOscillator/PercussiveBass.xpf +++ b/data/presets/TripleOscillator/PercussiveBass.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/Play-some-rock.xpf b/data/presets/TripleOscillator/Play-some-rock.xpf index 0faeb71e3e9..1b404430f5a 100644 --- a/data/presets/TripleOscillator/Play-some-rock.xpf +++ b/data/presets/TripleOscillator/Play-some-rock.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/PowerStrings.xpf b/data/presets/TripleOscillator/PowerStrings.xpf index 0fdbd6a56ec..e4bc5315ff4 100644 --- a/data/presets/TripleOscillator/PowerStrings.xpf +++ b/data/presets/TripleOscillator/PowerStrings.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/data/presets/TripleOscillator/SEGuitar.xpf b/data/presets/TripleOscillator/SEGuitar.xpf index 3f9445ca354..20118004a6f 100644 --- a/data/presets/TripleOscillator/SEGuitar.xpf +++ b/data/presets/TripleOscillator/SEGuitar.xpf @@ -16,7 +16,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -92,7 +92,7 @@ - + diff --git a/data/presets/TripleOscillator/SquarePing.xpf b/data/presets/TripleOscillator/SquarePing.xpf index 4ce7483f4d7..47cd035666a 100644 --- a/data/presets/TripleOscillator/SquarePing.xpf +++ b/data/presets/TripleOscillator/SquarePing.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/TripleOscillator/SuperSawLead.xpf b/data/presets/TripleOscillator/SuperSawLead.xpf index 2e082e645b5..72ef40dee6d 100644 --- a/data/presets/TripleOscillator/SuperSawLead.xpf +++ b/data/presets/TripleOscillator/SuperSawLead.xpf @@ -16,7 +16,7 @@ - + @@ -34,7 +34,7 @@ - + diff --git a/data/presets/TripleOscillator/Supernova.xpf b/data/presets/TripleOscillator/Supernova.xpf index 9c76dd9de72..0abf3028901 100644 --- a/data/presets/TripleOscillator/Supernova.xpf +++ b/data/presets/TripleOscillator/Supernova.xpf @@ -16,11 +16,11 @@ - + - + @@ -36,7 +36,7 @@ - + @@ -52,14 +52,14 @@ - + - + @@ -77,7 +77,7 @@ - + @@ -86,7 +86,7 @@ - + diff --git a/data/presets/TripleOscillator/TINTNpad.xpf b/data/presets/TripleOscillator/TINTNpad.xpf index 8f2c1e90d92..11e289cccd5 100644 --- a/data/presets/TripleOscillator/TINTNpad.xpf +++ b/data/presets/TripleOscillator/TINTNpad.xpf @@ -16,7 +16,7 @@ - + @@ -28,7 +28,7 @@ - + diff --git a/data/presets/TripleOscillator/WarmStack.xpf b/data/presets/TripleOscillator/WarmStack.xpf index 6b0855e39f9..da6bd95e391 100644 --- a/data/presets/TripleOscillator/WarmStack.xpf +++ b/data/presets/TripleOscillator/WarmStack.xpf @@ -16,7 +16,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -44,7 +44,7 @@ - + diff --git a/data/presets/Watsyn/Epic_lead.xpf b/data/presets/Watsyn/Epic_lead.xpf index a45472ca12a..7cf78392123 100644 --- a/data/presets/Watsyn/Epic_lead.xpf +++ b/data/presets/Watsyn/Epic_lead.xpf @@ -16,15 +16,15 @@ - + - + - + diff --git a/data/presets/Watsyn/Pulse.xpf b/data/presets/Watsyn/Pulse.xpf index 14d58bcd532..0ff99987ef1 100644 --- a/data/presets/Watsyn/Pulse.xpf +++ b/data/presets/Watsyn/Pulse.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/presets/Xpressive/Dream.xpf b/data/presets/Xpressive/Dream.xpf index 3eb20cf6084..9ddc66a76f5 100644 --- a/data/presets/Xpressive/Dream.xpf +++ b/data/presets/Xpressive/Dream.xpf @@ -16,7 +16,7 @@ - + diff --git a/data/projects/demos/StrictProduction-DearJonDoe.mmp b/data/projects/demos/StrictProduction-DearJonDoe.mmp index 06ea96d9ffd..1e69ab51fcb 100644 --- a/data/projects/demos/StrictProduction-DearJonDoe.mmp +++ b/data/projects/demos/StrictProduction-DearJonDoe.mmp @@ -21,7 +21,7 @@ - + @@ -94,7 +94,7 @@ - + @@ -317,7 +317,7 @@ - + diff --git a/data/projects/shorties/Crunk(Demo).mmp b/data/projects/shorties/Crunk(Demo).mmp index f40a5aafb82..3f791b4b3c4 100644 --- a/data/projects/shorties/Crunk(Demo).mmp +++ b/data/projects/shorties/Crunk(Demo).mmp @@ -66,7 +66,7 @@ - + @@ -131,7 +131,7 @@ - + diff --git a/include/Effect.h b/include/Effect.h index 7eb911701a0..3c6a6e37d50 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -26,10 +26,12 @@ #ifndef LMMS_EFFECT_H #define LMMS_EFFECT_H -#include "Plugin.h" -#include "Engine.h" +#include + #include "AudioEngine.h" #include "AutomatableModel.h" +#include "Engine.h" +#include "Plugin.h" #include "TempoSyncKnobModel.h" namespace lmms @@ -66,16 +68,6 @@ class LMMS_EXPORT Effect : public Plugin //! Returns true if audio was processed and should continue being processed bool processAudioBuffer(SampleFrame* buf, const fpp_t frames); - inline ch_cnt_t processorCount() const - { - return m_processors; - } - - inline void setProcessorCount( ch_cnt_t _processors ) - { - m_processors = _processors; - } - inline bool isOkay() const { return m_okay; @@ -92,14 +84,15 @@ class LMMS_EXPORT Effect : public Plugin return m_running; } - inline void startRunning() - { - m_bufferCount = 0; - m_running = true; + void startRunning() + { + m_quietBufferCount = 0; + m_running = true; } - inline void stopRunning() + void stopRunning() { + m_quietBufferCount = 0; m_running = false; } @@ -124,27 +117,6 @@ class LMMS_EXPORT Effect : public Plugin return 1.0f - m_wetDryModel.value(); } - inline float gate() const - { - const float level = m_gateModel.value(); - return level*level * m_processors; - } - - inline f_cnt_t bufferCount() const - { - return m_bufferCount; - } - - inline void resetBufferCount() - { - m_bufferCount = 0; - } - - inline void incrementBufferCount() - { - ++m_bufferCount; - } - inline bool dontRun() const { return m_noRun; @@ -160,6 +132,11 @@ class LMMS_EXPORT Effect : public Plugin return &m_autoQuitModel; } + bool autoQuitEnabled() const + { + return m_autoQuitEnabled; + } + EffectChain * effectChain() const { return m_parent; @@ -227,11 +204,11 @@ class LMMS_EXPORT Effect : public Plugin private: /** - If the setting "Keep effects running even without input" is disabled, - after "decay" ms of a signal below "gate", the effect is turned off - and won't be processed again until it receives new audio input - */ - void checkGate(double outSum); + * If auto-quit is enabled ("Keep effects running even without input" setting is disabled), + * after "decay" ms of the output buffer remaining below the silence threshold, the effect is + * turned off and won't be processed again until it receives new audio input. + */ + void handleAutoQuit(std::span output); EffectChain * m_parent; @@ -240,19 +217,18 @@ class LMMS_EXPORT Effect : public Plugin SampleFrame* _dst_buf, sample_rate_t _dst_sr, const f_cnt_t _frames ); - ch_cnt_t m_processors; - bool m_okay; bool m_noRun; bool m_running; - f_cnt_t m_bufferCount; + + //! The number of consecutive periods where output buffers remain below the silence threshold + f_cnt_t m_quietBufferCount = 0; BoolModel m_enabledModel; FloatModel m_wetDryModel; - FloatModel m_gateModel; TempoSyncKnobModel m_autoQuitModel; - - bool m_autoQuitDisabled; + + bool m_autoQuitEnabled = false; SRC_DATA m_srcData[2]; SRC_STATE * m_srcState[2]; diff --git a/include/EffectView.h b/include/EffectView.h index 805e4a4279c..cd45b735e77 100644 --- a/include/EffectView.h +++ b/include/EffectView.h @@ -92,7 +92,6 @@ public slots: LedCheckBox * m_bypass; Knob * m_wetDry; TempoSyncKnob * m_autoQuit; - Knob * m_gate; QMdiSubWindow * m_subWindow; EffectControlDialog * m_controlView; diff --git a/plugins/LadspaEffect/LadspaEffect.cpp b/plugins/LadspaEffect/LadspaEffect.cpp index eebe6938cad..ff6a184747a 100644 --- a/plugins/LadspaEffect/LadspaEffect.cpp +++ b/plugins/LadspaEffect/LadspaEffect.cpp @@ -280,7 +280,7 @@ void LadspaEffect::pluginInstantiation() // Calculate how many processing units are needed. int effect_channels = manager->getDescription( m_key )->inputChannels; - setProcessorCount(DEFAULT_CHANNELS / effect_channels); + m_processors = DEFAULT_CHANNELS / effect_channels; // get inPlaceBroken property m_inPlaceBroken = manager->isInplaceBroken( m_key ); diff --git a/plugins/LadspaEffect/LadspaEffect.h b/plugins/LadspaEffect/LadspaEffect.h index 0cfa186821f..7d2f73baf59 100644 --- a/plugins/LadspaEffect/LadspaEffect.h +++ b/plugins/LadspaEffect/LadspaEffect.h @@ -61,6 +61,10 @@ class LadspaEffect : public Effect return m_portControls; } + ch_cnt_t processorCount() const + { + return m_processors; + } private slots: void changeSampleRate(); @@ -87,7 +91,8 @@ private slots: QVector m_ports; multi_proc_t m_portControls; -} ; + ch_cnt_t m_processors = 1; +}; } // namespace lmms diff --git a/src/core/Effect.cpp b/src/core/Effect.cpp index 37133d4d5dd..979237ea82a 100644 --- a/src/core/Effect.cpp +++ b/src/core/Effect.cpp @@ -43,27 +43,19 @@ Effect::Effect( const Plugin::Descriptor * _desc, const Descriptor::SubPluginFeatures::Key * _key ) : Plugin( _desc, _parent, _key ), m_parent( nullptr ), - m_processors( 1 ), m_okay( true ), m_noRun( false ), m_running( false ), - m_bufferCount( 0 ), m_enabledModel( true, this, tr( "Effect enabled" ) ), m_wetDryModel( 1.0f, -1.0f, 1.0f, 0.01f, this, tr( "Wet/Dry mix" ) ), - m_gateModel( 0.0f, 0.0f, 1.0f, 0.01f, this, tr( "Gate" ) ), m_autoQuitModel( 1.0f, 1.0f, 8000.0f, 100.0f, 1.0f, this, tr( "Decay" ) ), - m_autoQuitDisabled( false ) + m_autoQuitEnabled(ConfigManager::inst()->value("ui", "disableautoquit", "1").toInt() == 0) { m_wetDryModel.setCenterValue(0); m_srcState[0] = m_srcState[1] = nullptr; reinitSRC(); - if( ConfigManager::inst()->value( "ui", "disableautoquit").toInt() ) - { - m_autoQuitDisabled = true; - } - // Call the virtual method onEnabledChanged so that effects can react to changes, // e.g. by resetting state. connect(&m_enabledModel, &BoolModel::dataChanged, [this] { onEnabledChanged(); }); @@ -91,7 +83,6 @@ void Effect::saveSettings( QDomDocument & _doc, QDomElement & _this ) m_enabledModel.saveSettings( _doc, _this, "on" ); m_wetDryModel.saveSettings( _doc, _this, "wet" ); m_autoQuitModel.saveSettings( _doc, _this, "autoquit" ); - m_gateModel.saveSettings( _doc, _this, "gate" ); controls()->saveState( _doc, _this ); } @@ -103,7 +94,6 @@ void Effect::loadSettings( const QDomElement & _this ) m_enabledModel.loadSettings( _this, "on" ); m_wetDryModel.loadSettings( _this, "wet" ); m_autoQuitModel.loadSettings( _this, "autoquit" ); - m_gateModel.loadSettings( _this, "gate" ); QDomNode node = _this.firstChild(); while( !node.isNull() ) @@ -136,16 +126,8 @@ bool Effect::processAudioBuffer(SampleFrame* buf, const fpp_t frames) case ProcessStatus::Continue: break; case ProcessStatus::ContinueIfNotQuiet: - { - double outSum = 0.0; - for (std::size_t idx = 0; idx < frames; ++idx) - { - outSum += buf[idx].sumOfSquaredAmplitudes(); - } - - checkGate(outSum / frames); + handleAutoQuit({buf, frames}); break; - } case ProcessStatus::Sleep: return false; default: @@ -181,27 +163,55 @@ Effect * Effect::instantiate( const QString& pluginName, -void Effect::checkGate(double outSum) +void Effect::handleAutoQuit(std::span output) { - if( m_autoQuitDisabled ) + if (!m_autoQuitEnabled) { return; } - // Check whether we need to continue processing input. Restart the + /* + * In the past, the RMS was calculated then compared with a threshold of 10^(-10). + * Now we use a different algorithm to determine whether a buffer is non-quiet, so + * a new threshold is needed for the best compatibility. The following is how it's derived. + * + * Old method: + * RMS = average (L^2 + R^2) across stereo buffer. + * RMS threshold = 10^(-10) + * + * So for a single channel, it would be: + * RMS/2 = average M^2 across single channel buffer. + * RMS/2 threshold = 5^(-11) + * + * The new algorithm for determining whether a buffer is non-silent compares M with the threshold, + * not M^2, so the square root of M^2's threshold should give us the most compatible threshold for + * the new algorithm: + * + * (RMS/2)^0.5 = (5^(-11))^0.5 = 0.0001431 (approx.) + * + * In practice though, the exact value shouldn't really matter so long as it's sufficiently small. + */ + static constexpr auto threshold = 0.0001431f; + + // Check whether we need to continue processing input. Restart the // counter if the threshold has been exceeded. - if (outSum - gate() <= F_EPSILON) + + for (const SampleFrame& frame : output) { - incrementBufferCount(); - if( bufferCount() > timeout() ) + const auto abs = frame.abs(); + if (abs.left() >= threshold || abs.right() >= threshold) { - stopRunning(); - resetBufferCount(); + // The output buffer is not quiet + m_quietBufferCount = 0; + return; } } - else + + // The output buffer is quiet, so check if auto-quit should be activated yet + if (++m_quietBufferCount > timeout()) { - resetBufferCount(); + // Activate auto-quit + stopRunning(); } } diff --git a/src/gui/EffectView.cpp b/src/gui/EffectView.cpp index a77fc1d967b..428035b9564 100644 --- a/src/gui/EffectView.cpp +++ b/src/gui/EffectView.cpp @@ -71,16 +71,9 @@ EffectView::EffectView( Effect * _model, QWidget * _parent ) : m_autoQuit = new TempoSyncKnob(KnobType::Bright26, tr("DECAY"), this, Knob::LabelRendering::LegacyFixedFontSize); m_autoQuit->move( 78 - m_autoQuit->width() / 2, 5 ); - m_autoQuit->setEnabled( isEnabled && !effect()->m_autoQuitDisabled ); + m_autoQuit->setEnabled(isEnabled && effect()->autoQuitEnabled()); m_autoQuit->setHintText( tr( "Time:" ), "ms" ); - - m_gate = new Knob(KnobType::Bright26, tr("GATE"), this, Knob::LabelRendering::LegacyFixedFontSize); - m_gate->move( 116 - m_gate->width() / 2, 5 ); - m_gate->setEnabled( isEnabled && !effect()->m_autoQuitDisabled ); - m_gate->setHintText( tr( "Gate:" ), "" ); - - setModel( _model ); if( effect()->controls()->controlCount() > 0 ) @@ -275,7 +268,6 @@ void EffectView::modelChanged() m_bypass->setModel( &effect()->m_enabledModel ); m_wetDry->setModel( &effect()->m_wetDryModel ); m_autoQuit->setModel( &effect()->m_autoQuitModel ); - m_gate->setModel( &effect()->m_gateModel ); } } // namespace lmms::gui