diff --git a/data/presets/AudioFileProcessor/Erazor.xpf b/data/presets/AudioFileProcessor/Erazor.xpf
index c448829fa..4b55b2d52 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 6e5214b0d..6ade93d1d 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 0b11e00cf..767c0cb24 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 938b4be36..6201150fc 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 d0ca7ed45..f5b4d564d 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 bbdbbbbfe..6a5dda6b7 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 b71b696c1..b2c56766c 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 05bc0a800..abc6b6c04 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 66cac9a91..b3a23dd8b 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 563f33843..04a44fc3f 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 af7be34fc..ec127a54c 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 1ad94ea1b..b3665f7cf 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 c6d3cf48b..c8a1ad712 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 d21804885..de115bdaa 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 fbe2639bc..cb2cafbfa 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 ec572d733..f2c0b9fe0 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 034521ad4..c441c19e3 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 94173d690..29f2a82dd 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 c2ce19aaa..a84d7075c 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 41a80c1e3..aedf62c50 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 457c3f318..7828ba502 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 5394d54db..df323a999 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 c78e4e896..c5a894669 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 6d1bfbe77..57ccd7845 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 349debf6b..6a5109d94 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 39aac12e7..48874af10 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 2e65f8c6e..da4a56f56 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 5e5e2e348..cea9adab8 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 a5c2d2bf6..910786f87 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 fcfa8a863..c947de3c2 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 181462ac9..6681d9094 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 b12a57e8c..5ad1e3c1a 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 47ec11889..99976ed29 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 e72a6e365..5a98f0620 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 095c3e665..96d15f7be 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 104c4066e..4be935391 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 30c8284e6..b65e9d18c 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 62f6c55db..40d6d6ae7 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 cc96f9e76..e2a50c10a 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 70035a87f..474e85534 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 3f9762190..fb1389d56 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 82c3f72e5..13ff3d369 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 0e3ba9a24..bad7bd9b4 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 90ea1fcea..2062c2d32 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 c19b3e352..f3dded4c4 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 485a570f6..f55be6ded 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 62ce53ab5..a48e131f9 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 9c0f062c9..85765a6fc 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 c9ebd118a..555fa03f0 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 0faeb71e3..1b404430f 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 0fdbd6a56..e4bc5315f 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 3f9445ca3..20118004a 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 4ce7483f4..47cd03566 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 2e082e645..72ef40dee 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 9c76dd9de..0abf30289 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 8f2c1e90d..11e289ccc 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 6b0855e39..da6bd95e3 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 a45472ca1..7cf783921 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 14d58bcd5..0ff99987e 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 3eb20cf60..9ddc66a76 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 06ea96d9f..1e69ab51f 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 f40a5aafb..3f791b4b3 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 7eb911701..3c6a6e37d 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 @@ public:
//! 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 @@ public:
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 @@ public:
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 @@ public:
return &m_autoQuitModel;
}
+ bool autoQuitEnabled() const
+ {
+ return m_autoQuitEnabled;
+ }
+
EffectChain * effectChain() const
{
return m_parent;
@@ -227,11 +204,11 @@ protected:
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 @@ private:
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 805e4a427..cd45b735e 100644
--- a/include/EffectView.h
+++ b/include/EffectView.h
@@ -92,7 +92,6 @@ private:
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 49fc74401..b29a8584e 100644
--- a/plugins/LadspaEffect/LadspaEffect.cpp
+++ b/plugins/LadspaEffect/LadspaEffect.cpp
@@ -279,7 +279,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 0cfa18682..7d2f73baf 100644
--- a/plugins/LadspaEffect/LadspaEffect.h
+++ b/plugins/LadspaEffect/LadspaEffect.h
@@ -61,6 +61,10 @@ public:
return m_portControls;
}
+ ch_cnt_t processorCount() const
+ {
+ return m_processors;
+ }
private slots:
void changeSampleRate();
@@ -87,7 +91,8 @@ private:
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 d5355a56d..02b6f32b5 100644
--- a/src/core/Effect.cpp
+++ b/src/core/Effect.cpp
@@ -42,27 +42,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(); });
@@ -90,7 +82,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 );
}
@@ -102,7 +93,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() )
@@ -135,16 +125,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:
@@ -180,27 +162,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 a77fc1d96..428035b95 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