diff --git a/plugins/editor/layout/main.fl b/plugins/editor/layout/main.fl
index 63effffff..78bf50ce8 100644
--- a/plugins/editor/layout/main.fl
+++ b/plugins/editor/layout/main.fl
@@ -3,11 +3,11 @@ version 1.0304
 header_name {.h}
 code_name {.cxx}
 widget_class mainView {open
-  xywh {108 91 800 475} type Double
+  xywh {607 439 800 475} type Double
   class LogicalGroup visible
 } {
   Fl_Box imageContainer_ {
-    image {../resources/background.png} xywh {5 110 790 285}
+    image {../resources/background.png} xywh {90 110 790 285}
     class Background
   }
   Fl_Group {} {
@@ -15,7 +15,7 @@ widget_class mainView {open
     xywh {0 0 814 110}
     class LogicalGroup
   } {
-    Fl_Group {} {open
+    Fl_Group {} {
       xywh {5 4 175 101} box ROUNDED_BOX align 0
       class RoundedGroup
     } {
@@ -45,7 +45,7 @@ widget_class mainView {open
         class HomeButton
       }
     }
-    Fl_Group {} {open
+    Fl_Group {} {
       xywh {185 5 390 100} box ROUNDED_BOX
       class RoundedGroup
     } {
@@ -126,7 +126,7 @@ widget_class mainView {open
         class ChevronValueDropDown
       }
     }
-    Fl_Group {} {open
+    Fl_Group {} {
       xywh {580 5 215 100} box ROUNDED_BOX
       class RoundedGroup
     } {
@@ -155,17 +155,17 @@ widget_class mainView {open
         xywh {739 10 23 90} box BORDER_BOX
         class VMeter
       }
-      Fl_Box {meters_[1]} {selected
+      Fl_Box {meters_[1]} {
         xywh {763 10 23 90} box BORDER_BOX
         class VMeter
       }
     }
   }
-  Fl_Group {subPanels_[kPanelInfo]} {
+  Fl_Group {subPanels_[kPanelInfo]} {open
     xywh {5 110 790 285} hide
     class LogicalGroup
   } {
-    Fl_Group {} {open
+    Fl_Group {} {
       xywh {5 110 790 285} box ROUNDED_BOX
       class RoundedGroup
     } {
@@ -225,7 +225,7 @@ widget_class mainView {open
     xywh {5 110 790 285} hide
     class LogicalGroup
   } {
-    Fl_Group {} {open
+    Fl_Group {} {
       xywh {5 110 790 285} box ROUNDED_BOX
       class RoundedGroup
     } {
@@ -235,150 +235,216 @@ widget_class mainView {open
       } {}
     }
   }
-  Fl_Group {subPanels_[kPanelSettings]} {
-    xywh {5 110 790 285}
+  Fl_Group {subPanels_[kPanelSettings]} {open
+    xywh {0 110 825 360}
     class LogicalGroup
   } {
-    Fl_Group {} {
-      label Engine open
-      xywh {305 135 195 100} box ROUNDED_BOX labelsize 12 align 17
-      class TitleGroup
+    Fl_Group {} {open
+      xywh {5 110 790 285} box ROUNDED_BOX
+      class RoundedGroup
     } {
       Fl_Spinner oversamplingSlider_ {
         comment {tag=kTagSetOversampling}
-        xywh {330 195 60 25} labelsize 12 textsize 12
+        xywh {175 195 70 25} labelsize 12 textsize 12
         class ValueMenu
       }
       Fl_Box {} {
         label Oversampling
-        xywh {320 155 80 25} labelsize 12
-        class ValueLabel
+        xywh {20 195 85 25} labelsize 12 align 20
+        class Label
       }
       Fl_Box {} {
         label {Preload size}
-        xywh {405 155 80 25} labelsize 12
-        class ValueLabel
+        xywh {20 170 75 25} labelsize 12 align 20
+        class Label
       }
       Fl_Spinner preloadSizeSlider_ {
         comment {tag=kTagSetPreloadSize}
-        xywh {415 195 60 25} labelsize 12 textsize 12
+        xywh {175 170 70 25} labelsize 12 textsize 12
+        class ValueMenu
+      }
+      Fl_Spinner sampleQualitySlider_ {
+        comment {tag=kTagSetSampleQuality}
+        xywh {435 145 80 25} labelsize 12 textsize 12
         class ValueMenu
       }
-    }
-    Fl_Group {} {
-      label Tuning open
-      xywh {175 270 415 100} box ROUNDED_BOX labelsize 12 align 17
-      class TitleGroup
-    } {
       Fl_Box {} {
-        label {Root key}
-        xywh {330 290 80 25} labelsize 12
-        class ValueLabel
+        label Sample
+        xywh {290 145 50 25} labelsize 12 align 20
+        class Label
       }
-      Fl_Spinner tuningFrequencySlider_ {
-        comment {tag=kTagSetTuningFrequency}
-        xywh {425 330 60 25} labelsize 12 textsize 12
+      Fl_Box {} {
+        label Oscillator
+        xywh {290 195 60 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Spinner oscillatorQualitySlider_ {
+        comment {tag=kTagSetOscillatorQuality}
+        xywh {435 195 80 25} labelsize 12 textsize 12
         class ValueMenu
       }
+      Fl_Spinner themeMenu_ {
+        comment {tag=kTagThemeMenu}
+        xywh {680 145 100 25} labelsize 12 textsize 12
+        class OptionMenu
+      }
+      Fl_Box {} {
+        label Theme
+        xywh {555 145 45 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Box {} {
+        label {User SFZ folder}
+        xywh {555 170 95 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Button userFilesDirButton_ {
+        label DefaultPath
+        comment {tag=kTagChooseUserFilesDir}
+        xywh {680 170 100 25} labelsize 12
+        class ValueButton
+      }
+      Fl_Box {} {
+        label {Root key}
+        xywh {555 285 60 25} labelsize 12 align 20
+        class Label
+      }
       Fl_Box {} {
         label Frequency
-        xywh {415 290 80 25} labelsize 12
-        class ValueLabel
+        xywh {555 310 70 25} labelsize 12 align 20
+        class Label
       }
       Fl_Dial stretchedTuningSlider_ {
         comment {tag=kTagSetStretchedTuning}
-        xywh {515 315 48 48} value 0.5
+        xywh {720 337 48 48} value 0.5
         class StyledKnob
       }
       Fl_Box {} {
         label Stretch
-        xywh {500 290 80 25} labelsize 12
-        class ValueLabel
+        xywh {555 345 50 25} labelsize 12 align 20
+        class Label
       }
       Fl_Box {} {
         label {Scala file}
-        xywh {195 290 100 25} labelsize 12
-        class ValueLabel
+        xywh {555 260 60 25} labelsize 12 align 20
+        class Label
       }
       Fl_Button scalaFileButton_ {
         label DefaultScale
         comment {tag=kTagLoadScalaFile}
-        xywh {195 330 100 25} labelsize 12
+        xywh {655 260 100 25} labelsize 12
         class ValueButton
       }
       Fl_Spinner scalaRootKeySlider_ {
         comment {tag=kTagSetScalaRootKey}
-        xywh {340 330 35 25} labelsize 12 textsize 12
+        xywh {715 285 35 25} labelsize 12 textsize 12
         class ValueMenu
       }
       Fl_Spinner scalaRootOctaveSlider_ {
         comment {tag=kTagSetScalaRootKey}
-        xywh {375 330 30 25} labelsize 12 textsize 12
+        xywh {750 285 30 25} labelsize 12 textsize 12
         class ValueMenu
       }
       Fl_Button scalaResetButton_ {
         comment {tag=kTagResetScalaFile}
-        xywh {295 330 25 25} labelsize 12
+        xywh {755 260 25 25} labelsize 12
         class ResetSomethingButton
       }
-    }
-    Fl_Group userFilesGroup_ {
-      label Files open
-      xywh {620 270 139 100} box ROUNDED_BOX labelsize 12 align 17
-      class TitleGroup
-    } {
       Fl_Box {} {
-        label {User SFZ folder}
-        xywh {640 290 100 25} labelsize 12
-        class ValueLabel
-      }
-      Fl_Button userFilesDirButton_ {
-        label DefaultPath
-        comment {tag=kTagChooseUserFilesDir}
-        xywh {640 330 100 25} labelsize 12
-        class ValueButton
+        label {... when freewheeling}
+        xywh {290 170 145 25} labelsize 12 align 20
+        class Label
       }
-    }
-    Fl_Group {} {
-      label Quality open
-      xywh {530 135 195 100} box ROUNDED_BOX labelsize 12 align 17
-      class TitleGroup
-    } {
-      Fl_Spinner sampleQualitySlider_ {
-        comment {tag=kTagSetSampleQuality}
-        xywh {545 195 80 25} labelsize 12 textsize 12
+      Fl_Spinner freewheelingSampleQualitySlider_ {
+        comment {tag=kTagSetFreewheelingSampleQuality}
+        xywh {435 170 80 25} labelsize 12 textsize 12
         class ValueMenu
       }
       Fl_Box {} {
-        label Sample
-        xywh {545 155 80 25} labelsize 12
-        class ValueLabel
+        label {Sustain cancels release}
+        xywh {20 220 145 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Check_Button sustainCancelsReleaseCheckbox_ {
+        comment {tag=kTagSetSustainCancelsRelease} selected
+        xywh {200 220 25 25} down_box DOWN_BOX
+        class Checkbox
+      }
+      Fl_Box sfizzVersionLabel_ {
+        label SFIZZ_VERSION
+        xywh {20 145 225 20} labelsize 10
+        class Label
       }
       Fl_Box {} {
-        label Oscillator
-        xywh {630 155 80 25} labelsize 12
-        class ValueLabel
+        label {Rendering quality}
+        xywh {290 115 110 25} labelsize 12 align 20
+        class Label
       }
-      Fl_Spinner oscillatorQualitySlider_ {
-        comment {tag=kTagSetOscillatorQuality}
-        xywh {630 195 80 25} labelsize 12 textsize 12
-        class ValueMenu
+      Fl_Box {} {
+        label {Separator 2}
+        xywh {20 135 225 5} box BORDER_BOX labeltype NO_LABEL
+        class HLine
       }
-    }
-    Fl_Group {} {
-      label Appearance open
-      xywh {40 270 105 100} box ROUNDED_BOX labelsize 12 align 17
-      class TitleGroup
-    } {
-      Fl_Spinner themeMenu_ {
-        comment {tag=kTagThemeMenu}
-        xywh {60 330 65 25} labelsize 12 textsize 12
-        class OptionMenu
+      Fl_Box {} {
+        label {Engine options}
+        xywh {20 115 95 25} labelsize 12 align 20
+        class Label
       }
       Fl_Box {} {
-        label Theme
-        xywh {50 295 80 25} labelsize 12
-        class ValueLabel
+        label {Separator 2}
+        xywh {580 135 185 5} box BORDER_BOX labeltype NO_LABEL
+        class HLine
+      }
+      Fl_Box {} {
+        label Other
+        xywh {555 115 40 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Box {} {
+        label Tuning
+        xywh {555 230 225 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Box {} {
+        label {Separator 2}
+        xywh {290 135 225 5} box BORDER_BOX labeltype NO_LABEL
+        class HLine
+      }
+      Fl_Box {} {
+        label {Separator 2}
+        xywh {555 135 225 5} box BORDER_BOX labeltype NO_LABEL
+        class HLine
+      }
+      Fl_Box {} {
+        label {Separator 2}
+        xywh {555 250 225 5} box BORDER_BOX labeltype NO_LABEL
+        class HLine
+      }
+      Fl_Button tuningFrequencyDropdown_ {
+        comment {tag=kTagSetTuningFrequency}
+        xywh {755 310 25 25} labelsize 24
+        class ChevronValueDropDown
+      }
+      Fl_Text_Editor tuningFrequencyEdit_ {
+        comment {tag=kTagSetTuningFrequency}
+        xywh {695 310 60 25} labelsize 12
+        class TextEdit
+      }
+      Fl_Button settingsAboutButton_ {
+        label {About sfizz}
+        comment {tag=kTagAbout}
+        xywh {610 205 115 25} labelsize 12
+        class ValueButton
+      }
+      Fl_Box {} {
+        label {... when freewheeling}
+        xywh {290 220 145 25} labelsize 12 align 20
+        class Label
+      }
+      Fl_Spinner freewheelingOscillatorQualitySlider_ {
+        comment {tag=kTagSetFreewheelingOscillatorQuality}
+        xywh {435 220 80 25} labelsize 12 textsize 12
+        class ValueMenu
       }
     }
   }
diff --git a/plugins/editor/src/editor/EditIds.cpp b/plugins/editor/src/editor/EditIds.cpp
index a88feb29e..c4de6bbd7 100644
--- a/plugins/editor/src/editor/EditIds.cpp
+++ b/plugins/editor/src/editor/EditIds.cpp
@@ -27,9 +27,15 @@ EditRange EditRange::get(EditId id)
     case EditId::StretchTuning:
         return { 0, 0, 1 };
     case EditId::SampleQuality:
-        return { 1, 0, 10 };
+        return { 2, 0, 10 };
     case EditId::OscillatorQuality:
         return { 1, 0, 3 };
+    case EditId::FreewheelingSampleQuality:
+        return { 10, 0, 10 };
+    case EditId::FreewheelingOscillatorQuality:
+        return { 3, 0, 3 };
+    case EditId::SustainCancelsRelease:
+        return { 0, 0, 1 };
     case EditId::UIActivePanel:
         return { 0, 0, 255 };
     }
diff --git a/plugins/editor/src/editor/EditIds.h b/plugins/editor/src/editor/EditIds.h
index e2ac0d89a..897c7ee33 100644
--- a/plugins/editor/src/editor/EditIds.h
+++ b/plugins/editor/src/editor/EditIds.h
@@ -20,6 +20,9 @@ enum class EditId : int {
     StretchTuning,
     SampleQuality,
     OscillatorQuality,
+    FreewheelingSampleQuality,
+    FreewheelingOscillatorQuality,
+    SustainCancelsRelease,
     CanEditUserFilesDir,
     UserFilesDir,
     FallbackFilesDir,
diff --git a/plugins/editor/src/editor/Editor.cpp b/plugins/editor/src/editor/Editor.cpp
index a9e02003a..fc5e0357e 100644
--- a/plugins/editor/src/editor/Editor.cpp
+++ b/plugins/editor/src/editor/Editor.cpp
@@ -10,6 +10,7 @@
 #include "GUIComponents.h"
 #include "GUIHelpers.h"
 #include "GUIPiano.h"
+#include "GitBuildId.h"
 #include "DlgAbout.h"
 #include "ImageHelpers.h"
 #include "NativeHelpers.h"
@@ -20,6 +21,7 @@
 #include <absl/strings/string_view.h>
 #include <absl/strings/match.h>
 #include <absl/strings/ascii.h>
+#include <absl/strings/str_cat.h>
 #include <absl/strings/numbers.h>
 #include <ghc/fs_std.hpp>
 #include <array>
@@ -96,6 +98,9 @@ struct Editor::Impl : EditorController::Receiver,
         kTagSetStretchedTuning,
         kTagSetSampleQuality,
         kTagSetOscillatorQuality,
+        kTagSetFreewheelingSampleQuality,
+        kTagSetFreewheelingOscillatorQuality,
+        kTagSetSustainCancelsRelease,
         kTagSetCCVolume,
         kTagSetCCPan,
         kTagChooseUserFilesDir,
@@ -120,12 +125,17 @@ struct Editor::Impl : EditorController::Receiver,
     SValueMenu *scalaRootKeySlider_ = nullptr;
     SValueMenu *scalaRootOctaveSlider_ = nullptr;
     CTextLabel* scalaRootKeyLabel_ = nullptr;
-    SValueMenu *tuningFrequencySlider_ = nullptr;
+    SValueMenu* tuningFrequencyDropdown_ = nullptr;
+    CTextEdit* tuningFrequencyEdit_ = nullptr;
+    STextButton *settingsAboutButton_ = nullptr;
     CTextLabel* tuningFrequencyLabel_ = nullptr;
     CControl *stretchedTuningSlider_ = nullptr;
     CTextLabel* stretchedTuningLabel_ = nullptr;
     SValueMenu *sampleQualitySlider_ = nullptr;
     SValueMenu *oscillatorQualitySlider_ = nullptr;
+    SValueMenu *freewheelingSampleQualitySlider_ = nullptr;
+    SValueMenu *freewheelingOscillatorQualitySlider_ = nullptr;
+    CCheckBox *sustainCancelsReleaseCheckbox_ = nullptr;
     CTextLabel* keyswitchLabel_ = nullptr;
     CTextLabel* keyswitchInactiveLabel_ = nullptr;
     CTextLabel* keyswitchBadge_ = nullptr;
@@ -161,6 +171,8 @@ struct Editor::Impl : EditorController::Receiver,
     SharedPointer<CBitmap> backgroundBitmap_;
     SharedPointer<CBitmap> defaultBackgroundBitmap_;
 
+    CTextLabel* sfizzVersionLabel_ = nullptr;
+
     SKnobCCBox* getSecondaryCCKnob(unsigned cc)
     {
         switch (cc) {
@@ -219,7 +231,6 @@ struct Editor::Impl : EditorController::Receiver,
     void updateOversamplingLabel(int oversamplingLog2);
     void updatePreloadSizeLabel(int preloadSize);
     void updateScalaRootKeyLabel(int rootKey);
-    void updateTuningFrequencyLabel(float tuningFrequency);
     void updateStretchedTuningLabel(float stretchedTuning);
 
     absl::string_view getCurrentKeyswitchName() const;
@@ -410,9 +421,8 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v)
     case EditId::TuningFrequency:
         {
             const float value = v.to_float();
-            if (tuningFrequencySlider_)
-                tuningFrequencySlider_->setValue(value);
-            updateTuningFrequencyLabel(value);
+            if (tuningFrequencyEdit_)
+                tuningFrequencyEdit_->setValue(value);
         }
         break;
     case EditId::StretchTuning:
@@ -441,6 +451,33 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v)
             }
         }
         break;
+    case EditId::FreewheelingSampleQuality:
+        {
+            const int value = static_cast<int>(v.to_float());
+            if (CControl* slider = freewheelingSampleQualitySlider_) {
+                slider->setValue(float(value));
+                slider->invalid();
+            }
+        }
+        break;
+    case EditId::FreewheelingOscillatorQuality:
+        {
+            const int value = static_cast<int>(v.to_float());
+            if (CControl* slider = freewheelingOscillatorQualitySlider_) {
+                slider->setValue(float(value));
+                slider->invalid();
+            }
+        }
+        break;
+    case EditId::SustainCancelsRelease:
+        {
+            const bool value = v.to_float();
+            if (CControl* checkbox = sustainCancelsReleaseCheckbox_) {
+                checkbox->setValue(value);
+                checkbox->invalid();
+            }
+        }
+        break;
     case EditId::CanEditUserFilesDir:
         {
             if (STitleContainer* group = userFilesGroup_)
@@ -695,6 +732,7 @@ void Editor::Impl::createFrameContents()
             });
             return box;
         };
+#if 0
         auto createTitleGroup = [this, &palette](const CRect& bounds, int, const char* label, CHoriTxtAlign, int fontsize) {
             auto* box =  new STitleContainer(bounds, label);
             box->setCornerRadius(10.0);
@@ -707,6 +745,7 @@ void Editor::Impl::createFrameContents()
             box->setTitleFont(font);
             return box;
         };
+#endif
         auto createAboutButton = [this, &iconShaded](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int) {
             return new CKickButton(bounds, this, tag, 0.0f, iconShaded);
         };
@@ -734,11 +773,13 @@ void Editor::Impl::createFrameContents()
             lbl->setFont(font);
             return lbl;
         };
-        auto createHLine = [](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
+        auto createHLine = [this, &palette](const CRect& bounds, int, const char*, CHoriTxtAlign, int) {
             int y = static_cast<int>(0.5 * (bounds.top + bounds.bottom));
             CRect lineBounds(bounds.left, y, bounds.right, y + 1);
             CViewContainer* hline = new CViewContainer(lineBounds);
-            hline->setBackgroundColor(CColor(0xff, 0xff, 0xff, 0xff));
+            OnThemeChanged.push_back([hline, palette]() {
+                hline->setBackgroundColor(palette->text);
+            });
             return hline;
         };
         auto createValueLabel = [this, &palette](const CRect& bounds, int, const char* label, CHoriTxtAlign align, int fontsize) {
@@ -767,15 +808,7 @@ void Editor::Impl::createFrameContents()
             lbl->setFont(font);
             return lbl;
         };
-#if 0
-        auto createButton = [this](const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) {
-            CTextButton* button = new CTextButton(bounds, this, tag, label);
-            auto font = makeOwned<CFontDesc>("Roboto", fontsize);
-            button->setFont(font);
-            button->setTextAlignment(align);
-            return button;
-        };
-#endif
+
         auto createClickableLabel = [this, &palette](const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) {
             STextButton* button = new STextButton(bounds, this, tag, label);
             auto font = makeOwned<CFontDesc>("Roboto", fontsize);
@@ -982,6 +1015,26 @@ void Editor::Impl::createFrameContents()
             return panel;
         };
 
+        auto createCheckbox = [this, &palette](const CRect& bounds, int tag, const char* label, CHoriTxtAlign, int) {
+            auto* checkbox = new CCheckBox(bounds, this, tag, label);
+            return checkbox;
+        };
+
+        auto createTextEdit = [this, &palette] (const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) {
+            auto* edit = new CTextEdit(bounds, this, tag, label, nullptr);
+            auto font = makeOwned<CFontDesc>("Roboto", fontsize);
+            edit->setFont(font);
+            edit->setHoriAlign(align);
+            edit->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00));
+            edit->setStyle(CParamDisplay::kRoundRectStyle);
+            edit->setRoundRectRadius(5.0);
+            OnThemeChanged.push_back([edit, palette]() {
+                edit->setFontColor(palette->valueText);
+                edit->setBackColor(palette->valueBackground);
+            });
+            return edit;
+        };
+
         #include "layout/main.hpp"
 
         OnThemeChanged.push_back([mainView, theme]() {
@@ -1025,6 +1078,11 @@ void Editor::Impl::createFrameContents()
         mainView_ = owned(mainView);
     }
 
+    if (CTextLabel* label = sfizzVersionLabel_) {
+        std::string version = GitBuildId[0] ? absl::StrCat(SFIZZ_VERSION ".", GitBuildId) : SFIZZ_VERSION;
+        label->setText(absl::StrCat(u8"sfizz ", version));
+    }
+
     ///
     currentThemeName_ = theme->loadCurrentName();
     theme->load(currentThemeName_);
@@ -1061,11 +1119,15 @@ void Editor::Impl::createFrameContents()
         scalaRootOctaveSlider_->setDefaultValue(
             static_cast<int>(EditRange::get(EditId::ScalaRootKey).def) / 12);
     }
-    adjustMinMaxToEditRange(tuningFrequencySlider_, EditId::TuningFrequency);
-    tuningFrequencySlider_->setWheelInc(0.1f / EditRange::get(EditId::TuningFrequency).extent());
+    adjustMinMaxToEditRange(tuningFrequencyDropdown_, EditId::TuningFrequency);
+    adjustMinMaxToEditRange(tuningFrequencyEdit_, EditId::TuningFrequency);
+    tuningFrequencyEdit_->setWheelInc(0.1f / EditRange::get(EditId::TuningFrequency).extent());
     adjustMinMaxToEditRange(stretchedTuningSlider_, EditId::StretchTuning);
     adjustMinMaxToEditRange(sampleQualitySlider_, EditId::SampleQuality);
     adjustMinMaxToEditRange(oscillatorQualitySlider_, EditId::OscillatorQuality);
+    adjustMinMaxToEditRange(freewheelingSampleQualitySlider_, EditId::FreewheelingSampleQuality);
+    adjustMinMaxToEditRange(freewheelingOscillatorQualitySlider_, EditId::FreewheelingOscillatorQuality);
+    adjustMinMaxToEditRange(sustainCancelsReleaseCheckbox_, EditId::SustainCancelsRelease);
 
     for (int value : {1, 2, 4, 8, 16, 32, 64, 96, 128, 160, 192, 224, 256})
         numVoicesSlider_->addEntry(std::to_string(value), value);
@@ -1110,14 +1172,25 @@ void Editor::Impl::createFrameContents()
     };
 
     for (std::pair<float, const char*> value : tuningFrequencies)
-        tuningFrequencySlider_->addEntry(value.second, value.first);
-    tuningFrequencySlider_->setValueToStringFunction(
+        tuningFrequencyDropdown_->addEntry(value.second, value.first);
+
+    tuningFrequencyEdit_->setValueToStringFunction(
         [](float value, char result[256], CParamDisplay*) -> bool
         {
             sprintf(result, "%.1f Hz", value);
             return true;
         });
 
+    tuningFrequencyEdit_->setStringToValueFunction([](UTF8StringPtr txt, float& result, CTextEdit*) -> bool {
+        float value;
+        if (absl::SimpleAtof(txt, &value)) {
+            result = value;
+            return true;
+        }
+
+        return false;
+    });
+
     static const char* notesInOctave[12] = {
         "C", "C#", "D", "D#", "E",
         "F", "F#", "G", "G#", "A", "A#", "B",
@@ -1146,36 +1219,49 @@ void Editor::Impl::createFrameContents()
         menu->addEntry("Open SFZ folder", kTagOpenSfzFolder);
     }
 
-    if (SValueMenu *menu = sampleQualitySlider_) {
-        static const std::array<const char*, 11> labels {{
-            "Nearest", "Linear", "Polynomial",
-            "Sinc 8", "Sinc 12", "Sinc 16", "Sinc 24",
-            "Sinc 36", "Sinc 48", "Sinc 60", "Sinc 72",
-        }};
-        for (size_t i = 0; i < labels.size(); ++i)
-            menu->addEntry(labels[i], float(i));
-        menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
-            int index = int(value);
-            if (index < 0 || unsigned(index) >= labels.size())
-                return false;
-            result = labels[unsigned(index)];
-            return true;
-        });
-    }
-    if (SValueMenu *menu = oscillatorQualitySlider_) {
-        static const std::array<const char*, 4> labels {{
-            "Nearest", "Linear", "High", "Dual-High",
-        }};
-        for (size_t i = 0; i < labels.size(); ++i)
-            menu->addEntry(labels[i], float(i));
-        menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
-            int index = int(value);
-            if (index < 0 || unsigned(index) >= labels.size())
-                return false;
-            result = labels[unsigned(index)];
-            return true;
-        });
-    }
+    static const std::array<const char*, 11> sampleQualityLabels {{
+        "Nearest", "Linear", "Polynomial",
+        "Sinc 8", "Sinc 12", "Sinc 16", "Sinc 24",
+        "Sinc 36", "Sinc 48", "Sinc 60", "Sinc 72",
+    }};
+
+    auto setupSampleQualityMenu = [&] (SValueMenu* menu) {
+        if (menu) {
+            for (size_t i = 0; i < sampleQualityLabels.size(); ++i)
+                menu->addEntry(sampleQualityLabels[i], float(i));
+            menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
+                int index = int(value);
+                if (index < 0 || unsigned(index) >= sampleQualityLabels.size())
+                    return false;
+                result = sampleQualityLabels[unsigned(index)];
+                return true;
+            });
+        }
+    };
+
+    setupSampleQualityMenu(sampleQualitySlider_);
+    setupSampleQualityMenu(freewheelingSampleQualitySlider_);
+
+    static const std::array<const char*, 4> oscillatorQualityLabels {{
+        "Nearest", "Linear", "High", "Dual-High",
+    }};
+
+    auto setupOscillatorQualityMenu = [&] (SValueMenu* menu) {
+        if (menu) {
+            for (size_t i = 0; i < oscillatorQualityLabels.size(); ++i)
+                menu->addEntry(oscillatorQualityLabels[i], float(i));
+            menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
+                int index = int(value);
+                if (index < 0 || unsigned(index) >= oscillatorQualityLabels.size())
+                    return false;
+                result = oscillatorQualityLabels[unsigned(index)];
+                return true;
+            });
+        }
+    };
+
+    setupOscillatorQualityMenu(oscillatorQualitySlider_);
+    setupOscillatorQualityMenu(freewheelingOscillatorQualitySlider_);
 
     if (SPiano* piano = piano_) {
         piano->onKeyPressed = [this](unsigned key, float vel) {
@@ -1616,18 +1702,6 @@ void Editor::Impl::updateScalaRootKeyLabel(int rootKey)
     label->setText(noteName(rootKey));
 }
 
-void Editor::Impl::updateTuningFrequencyLabel(float tuningFrequency)
-{
-    CTextLabel* label = tuningFrequencyLabel_;
-    if (!label)
-        return;
-
-    char text[64];
-    sprintf(text, "%.1f", tuningFrequency);
-    text[sizeof(text) - 1] = '\0';
-    label->setText(text);
-}
-
 void Editor::Impl::updateStretchedTuningLabel(float stretchedTuning)
 {
     CTextLabel* label = stretchedTuningLabel_;
@@ -1962,7 +2036,8 @@ void Editor::Impl::valueChanged(CControl* ctl)
 
     case kTagSetTuningFrequency:
         ctrl.uiSendValue(EditId::TuningFrequency, value);
-        updateTuningFrequencyLabel(value);
+        if (tuningFrequencyEdit_)
+            tuningFrequencyEdit_->setValue(value);
         break;
 
     case kTagSetSampleQuality:
@@ -1973,6 +2048,18 @@ void Editor::Impl::valueChanged(CControl* ctl)
         ctrl.uiSendValue(EditId::OscillatorQuality, value);
         break;
 
+    case kTagSetFreewheelingSampleQuality:
+        ctrl.uiSendValue(EditId::FreewheelingSampleQuality, value);
+        break;
+
+    case kTagSetFreewheelingOscillatorQuality:
+        ctrl.uiSendValue(EditId::FreewheelingOscillatorQuality, value);
+        break;
+
+    case kTagSetSustainCancelsRelease:
+        ctrl.uiSendValue(EditId::SustainCancelsRelease, value);
+        break;
+
     case kTagSetStretchedTuning:
         ctrl.uiSendValue(EditId::StretchTuning, value);
         updateStretchedTuningLabel(value);
diff --git a/plugins/editor/src/editor/layout/main.hpp b/plugins/editor/src/editor/layout/main.hpp
index f640d4472..546601660 100644
--- a/plugins/editor/src/editor/layout/main.hpp
+++ b/plugins/editor/src/editor/layout/main.hpp
@@ -1,7 +1,7 @@
 /* This file is generated by the layout maker tool. */
 auto* const view__0 = createLogicalGroup(CRect(0, 0, 800, 475), -1, "", kCenterText, 14);
 mainView = view__0;
-auto* const view__1 = createBackground(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
+auto* const view__1 = createBackground(CRect(90, 110, 880, 395), -1, "", kCenterText, 14);
 imageContainer_ = view__1;
 view__0->addView(view__1);
 enterPalette(invertedPalette);
@@ -128,80 +128,113 @@ view__45->addView(view__46);
 auto* const view__47 = createControlsPanel(CRect(0, 0, 790, 285), -1, "", kCenterText, 12);
 controlsPanel_ = view__47;
 view__46->addView(view__47);
-auto* const view__48 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
+auto* const view__48 = createLogicalGroup(CRect(0, 110, 825, 470), -1, "", kCenterText, 14);
 subPanels_[kPanelSettings] = view__48;
 view__0->addView(view__48);
-auto* const view__49 = createTitleGroup(CRect(300, 25, 495, 125), -1, "Engine", kCenterText, 12);
+auto* const view__49 = createRoundedGroup(CRect(5, 0, 795, 285), -1, "", kCenterText, 14);
 view__48->addView(view__49);
-auto* const view__50 = createValueMenu(CRect(25, 60, 85, 85), kTagSetOversampling, "", kCenterText, 12);
+auto* const view__50 = createValueMenu(CRect(170, 85, 240, 110), kTagSetOversampling, "", kCenterText, 12);
 oversamplingSlider_ = view__50;
 view__49->addView(view__50);
-auto* const view__51 = createValueLabel(CRect(15, 20, 95, 45), -1, "Oversampling", kCenterText, 12);
+auto* const view__51 = createLabel(CRect(15, 85, 100, 110), -1, "Oversampling", kLeftText, 12);
 view__49->addView(view__51);
-auto* const view__52 = createValueLabel(CRect(100, 20, 180, 45), -1, "Preload size", kCenterText, 12);
+auto* const view__52 = createLabel(CRect(15, 60, 90, 85), -1, "Preload size", kLeftText, 12);
 view__49->addView(view__52);
-auto* const view__53 = createValueMenu(CRect(110, 60, 170, 85), kTagSetPreloadSize, "", kCenterText, 12);
+auto* const view__53 = createValueMenu(CRect(170, 60, 240, 85), kTagSetPreloadSize, "", kCenterText, 12);
 preloadSizeSlider_ = view__53;
 view__49->addView(view__53);
-auto* const view__54 = createTitleGroup(CRect(170, 160, 585, 260), -1, "Tuning", kCenterText, 12);
-view__48->addView(view__54);
-auto* const view__55 = createValueLabel(CRect(155, 20, 235, 45), -1, "Root key", kCenterText, 12);
-view__54->addView(view__55);
-auto* const view__56 = createValueMenu(CRect(250, 60, 310, 85), kTagSetTuningFrequency, "", kCenterText, 12);
-tuningFrequencySlider_ = view__56;
-view__54->addView(view__56);
-auto* const view__57 = createValueLabel(CRect(240, 20, 320, 45), -1, "Frequency", kCenterText, 12);
-view__54->addView(view__57);
-auto* const view__58 = createStyledKnob(CRect(340, 45, 388, 93), kTagSetStretchedTuning, "", kCenterText, 14);
-stretchedTuningSlider_ = view__58;
-view__54->addView(view__58);
-auto* const view__59 = createValueLabel(CRect(325, 20, 405, 45), -1, "Stretch", kCenterText, 12);
-view__54->addView(view__59);
-auto* const view__60 = createValueLabel(CRect(20, 20, 120, 45), -1, "Scala file", kCenterText, 12);
-view__54->addView(view__60);
-auto* const view__61 = createValueButton(CRect(20, 60, 120, 85), kTagLoadScalaFile, "DefaultScale", kCenterText, 12);
-scalaFileButton_ = view__61;
-view__54->addView(view__61);
-auto* const view__62 = createValueMenu(CRect(165, 60, 200, 85), kTagSetScalaRootKey, "", kCenterText, 12);
-scalaRootKeySlider_ = view__62;
-view__54->addView(view__62);
-auto* const view__63 = createValueMenu(CRect(200, 60, 230, 85), kTagSetScalaRootKey, "", kCenterText, 12);
-scalaRootOctaveSlider_ = view__63;
-view__54->addView(view__63);
-auto* const view__64 = createResetSomethingButton(CRect(120, 60, 145, 85), kTagResetScalaFile, "", kCenterText, 12);
-scalaResetButton_ = view__64;
-view__54->addView(view__64);
-auto* const view__65 = createTitleGroup(CRect(615, 160, 754, 260), -1, "Files", kCenterText, 12);
-userFilesGroup_ = view__65;
-view__48->addView(view__65);
-auto* const view__66 = createValueLabel(CRect(20, 20, 120, 45), -1, "User SFZ folder", kCenterText, 12);
-view__65->addView(view__66);
-auto* const view__67 = createValueButton(CRect(20, 60, 120, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12);
-userFilesDirButton_ = view__67;
-view__65->addView(view__67);
-auto* const view__68 = createTitleGroup(CRect(525, 25, 720, 125), -1, "Quality", kCenterText, 12);
-view__48->addView(view__68);
-auto* const view__69 = createValueMenu(CRect(15, 60, 95, 85), kTagSetSampleQuality, "", kCenterText, 12);
-sampleQualitySlider_ = view__69;
-view__68->addView(view__69);
-auto* const view__70 = createValueLabel(CRect(15, 20, 95, 45), -1, "Sample", kCenterText, 12);
-view__68->addView(view__70);
-auto* const view__71 = createValueLabel(CRect(100, 20, 180, 45), -1, "Oscillator", kCenterText, 12);
-view__68->addView(view__71);
-auto* const view__72 = createValueMenu(CRect(100, 60, 180, 85), kTagSetOscillatorQuality, "", kCenterText, 12);
-oscillatorQualitySlider_ = view__72;
-view__68->addView(view__72);
-auto* const view__73 = createTitleGroup(CRect(35, 160, 140, 260), -1, "Appearance", kCenterText, 12);
-view__48->addView(view__73);
-auto* const view__74 = createOptionMenu(CRect(20, 60, 85, 85), kTagThemeMenu, "", kCenterText, 12);
-themeMenu_ = view__74;
-view__73->addView(view__74);
-auto* const view__75 = createValueLabel(CRect(10, 25, 90, 50), -1, "Theme", kCenterText, 12);
-view__73->addView(view__75);
-auto* const view__76 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
-piano_ = view__76;
-view__0->addView(view__76);
-auto* const view__77 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
-subPanels_[kPanelGeneral] = view__77;
-view__0->addView(view__77);
-view__77->setVisible(false);
+auto* const view__54 = createValueMenu(CRect(430, 35, 510, 60), kTagSetSampleQuality, "", kCenterText, 12);
+sampleQualitySlider_ = view__54;
+view__49->addView(view__54);
+auto* const view__55 = createLabel(CRect(285, 35, 335, 60), -1, "Sample", kLeftText, 12);
+view__49->addView(view__55);
+auto* const view__56 = createLabel(CRect(285, 85, 345, 110), -1, "Oscillator", kLeftText, 12);
+view__49->addView(view__56);
+auto* const view__57 = createValueMenu(CRect(430, 85, 510, 110), kTagSetOscillatorQuality, "", kCenterText, 12);
+oscillatorQualitySlider_ = view__57;
+view__49->addView(view__57);
+auto* const view__58 = createOptionMenu(CRect(675, 35, 775, 60), kTagThemeMenu, "", kCenterText, 12);
+themeMenu_ = view__58;
+view__49->addView(view__58);
+auto* const view__59 = createLabel(CRect(550, 35, 595, 60), -1, "Theme", kLeftText, 12);
+view__49->addView(view__59);
+auto* const view__60 = createLabel(CRect(550, 60, 645, 85), -1, "User SFZ folder", kLeftText, 12);
+view__49->addView(view__60);
+auto* const view__61 = createValueButton(CRect(675, 60, 775, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12);
+userFilesDirButton_ = view__61;
+view__49->addView(view__61);
+auto* const view__62 = createLabel(CRect(550, 175, 610, 200), -1, "Root key", kLeftText, 12);
+view__49->addView(view__62);
+auto* const view__63 = createLabel(CRect(550, 200, 620, 225), -1, "Frequency", kLeftText, 12);
+view__49->addView(view__63);
+auto* const view__64 = createStyledKnob(CRect(715, 227, 763, 275), kTagSetStretchedTuning, "", kCenterText, 14);
+stretchedTuningSlider_ = view__64;
+view__49->addView(view__64);
+auto* const view__65 = createLabel(CRect(550, 235, 600, 260), -1, "Stretch", kLeftText, 12);
+view__49->addView(view__65);
+auto* const view__66 = createLabel(CRect(550, 150, 610, 175), -1, "Scala file", kLeftText, 12);
+view__49->addView(view__66);
+auto* const view__67 = createValueButton(CRect(650, 150, 750, 175), kTagLoadScalaFile, "DefaultScale", kCenterText, 12);
+scalaFileButton_ = view__67;
+view__49->addView(view__67);
+auto* const view__68 = createValueMenu(CRect(710, 175, 745, 200), kTagSetScalaRootKey, "", kCenterText, 12);
+scalaRootKeySlider_ = view__68;
+view__49->addView(view__68);
+auto* const view__69 = createValueMenu(CRect(745, 175, 775, 200), kTagSetScalaRootKey, "", kCenterText, 12);
+scalaRootOctaveSlider_ = view__69;
+view__49->addView(view__69);
+auto* const view__70 = createResetSomethingButton(CRect(750, 150, 775, 175), kTagResetScalaFile, "", kCenterText, 12);
+scalaResetButton_ = view__70;
+view__49->addView(view__70);
+auto* const view__71 = createLabel(CRect(285, 60, 430, 85), -1, "... when freewheeling", kLeftText, 12);
+view__49->addView(view__71);
+auto* const view__72 = createValueMenu(CRect(430, 60, 510, 85), kTagSetFreewheelingSampleQuality, "", kCenterText, 12);
+freewheelingSampleQualitySlider_ = view__72;
+view__49->addView(view__72);
+auto* const view__73 = createLabel(CRect(15, 110, 160, 135), -1, "Sustain cancels release", kLeftText, 12);
+view__49->addView(view__73);
+auto* const view__74 = createCheckbox(CRect(195, 110, 220, 135), kTagSetSustainCancelsRelease, "", kCenterText, 14);
+sustainCancelsReleaseCheckbox_ = view__74;
+view__49->addView(view__74);
+auto* const view__75 = createLabel(CRect(15, 35, 240, 55), -1, "SFIZZ_VERSION", kCenterText, 10);
+sfizzVersionLabel_ = view__75;
+view__49->addView(view__75);
+auto* const view__76 = createLabel(CRect(285, 5, 395, 30), -1, "Rendering quality", kLeftText, 12);
+view__49->addView(view__76);
+auto* const view__77 = createHLine(CRect(15, 25, 240, 30), -1, "", kCenterText, 14);
+view__49->addView(view__77);
+auto* const view__78 = createLabel(CRect(15, 5, 110, 30), -1, "Engine options", kLeftText, 12);
+view__49->addView(view__78);
+auto* const view__79 = createHLine(CRect(575, 25, 760, 30), -1, "", kCenterText, 14);
+view__49->addView(view__79);
+auto* const view__80 = createLabel(CRect(550, 5, 590, 30), -1, "Other", kLeftText, 12);
+view__49->addView(view__80);
+auto* const view__81 = createLabel(CRect(550, 120, 775, 145), -1, "Tuning", kLeftText, 12);
+view__49->addView(view__81);
+auto* const view__82 = createHLine(CRect(285, 25, 510, 30), -1, "", kCenterText, 14);
+view__49->addView(view__82);
+auto* const view__83 = createHLine(CRect(550, 25, 775, 30), -1, "", kCenterText, 14);
+view__49->addView(view__83);
+auto* const view__84 = createHLine(CRect(550, 140, 775, 145), -1, "", kCenterText, 14);
+view__49->addView(view__84);
+auto* const view__85 = createChevronValueDropDown(CRect(750, 200, 775, 225), kTagSetTuningFrequency, "", kCenterText, 24);
+tuningFrequencyDropdown_ = view__85;
+view__49->addView(view__85);
+auto* const view__86 = createTextEdit(CRect(690, 200, 750, 225), kTagSetTuningFrequency, "", kCenterText, 12);
+tuningFrequencyEdit_ = view__86;
+view__49->addView(view__86);
+auto* const view__87 = createValueButton(CRect(605, 95, 720, 120), kTagAbout, "About sfizz", kCenterText, 12);
+settingsAboutButton_ = view__87;
+view__49->addView(view__87);
+auto* const view__88 = createLabel(CRect(285, 110, 430, 135), -1, "... when freewheeling", kLeftText, 12);
+view__49->addView(view__88);
+auto* const view__89 = createValueMenu(CRect(430, 110, 510, 135), kTagSetFreewheelingOscillatorQuality, "", kCenterText, 12);
+freewheelingOscillatorQualitySlider_ = view__89;
+view__49->addView(view__89);
+auto* const view__90 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
+piano_ = view__90;
+view__0->addView(view__90);
+auto* const view__91 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14);
+subPanels_[kPanelGeneral] = view__91;
+view__0->addView(view__91);
+view__91->setVisible(false);
diff --git a/plugins/lv2/sfizz.cpp b/plugins/lv2/sfizz.cpp
index a4f097e5b..03321b922 100644
--- a/plugins/lv2/sfizz.cpp
+++ b/plugins/lv2/sfizz.cpp
@@ -259,6 +259,15 @@ connect_port_stereo(LV2_Handle instance,
     case SFIZZ_NUM_SAMPLES:
         self->num_samples_port = (float *)data;
         break;
+    case SFIZZ_FREEWHEELING_SAMPLE_QUALITY:
+        self->freewheeling_sample_quality_port = (const float *)data;
+        break;
+    case SFIZZ_FREEWHEELING_OSCILLATOR_QUALITY:
+        self->freewheeling_oscillator_quality_port = (const float *)data;
+        break;
+    case SFIZZ_SUSTAIN_CANCELS_RELEASE:
+        self->sustain_cancels_release_port = (const float *)data;
+        break;
     default:
         break;
     }
@@ -374,6 +383,15 @@ connect_port_multi(LV2_Handle instance,
     case SFIZZ_MULTI_NUM_SAMPLES:
         self->num_samples_port = (float *)data;
         break;
+    case SFIZZ_MULTI_FREEWHEELING_SAMPLE_QUALITY:
+        self->freewheeling_sample_quality_port = (const float *)data;
+        break;
+    case SFIZZ_MULTI_FREEWHEELING_OSCILLATOR_QUALITY:
+        self->freewheeling_oscillator_quality_port = (const float *)data;
+        break;
+    case SFIZZ_MULTI_SUSTAIN_CANCELS_RELEASE:
+        self->sustain_cancels_release_port = (const float *)data;
+        break;
     default:
         break;
     }
@@ -1177,6 +1195,9 @@ run(LV2_Handle instance, uint32_t sample_count)
     sfizz_set_tuning_frequency(self->synth, *(self->tuning_frequency_port));
     sfizz_set_sample_quality(self->synth, SFIZZ_PROCESS_LIVE, (int)(*self->sample_quality_port));
     sfizz_set_oscillator_quality(self->synth, SFIZZ_PROCESS_LIVE, (int)(*self->oscillator_quality_port));
+    sfizz_set_sample_quality(self->synth, SFIZZ_PROCESS_FREEWHEELING, (int)(*self->freewheeling_sample_quality_port));
+    sfizz_set_oscillator_quality(self->synth, SFIZZ_PROCESS_FREEWHEELING, (int)(*self->freewheeling_oscillator_quality_port));
+    sfizz_set_sustain_cancels_release(self->synth, (*self->sustain_cancels_release_port > 0.0f));
     sfizz_lv2_check_stretch_tuning(self);
     sfizz_lv2_check_preload_size(self);
     sfizz_lv2_check_oversampling(self);
diff --git a/plugins/lv2/sfizz.ttl.in b/plugins/lv2/sfizz.ttl.in
index e8eae3a8e..5d7a8f66d 100644
--- a/plugins/lv2/sfizz.ttl.in
+++ b/plugins/lv2/sfizz.ttl.in
@@ -325,7 +325,7 @@ midnam:update a lv2:Feature .
     lv2:name "Sample quality",
       "Qualité des échantillons"@fr ,
       "Qualità del campione"@it ;
-    pg:group <@LV2PLUGIN_URI@#tuning> ;
+    pg:group <@LV2PLUGIN_URI@#config> ;
     lv2:default 2.0 ;
     lv2:minimum 0.0 ;
     lv2:maximum 10.0
@@ -336,7 +336,7 @@ midnam:update a lv2:Feature .
     lv2:name "Oscillator quality",
       "Qualité des oscillateurs"@fr ,
       "Qualità dell'oscillatore"@it ;
-    pg:group <@LV2PLUGIN_URI@#tuning> ;
+    pg:group <@LV2PLUGIN_URI@#config> ;
     lv2:default 1.0 ;
     lv2:minimum 0.0 ;
     lv2:maximum 3.0
@@ -406,6 +406,36 @@ midnam:update a lv2:Feature .
     lv2:default 0 ;
     lv2:minimum 0 ;
     lv2:maximum 65535 ;
+  ] , [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 20 ;
+    lv2:symbol "freewheeling_sample_quality" ;
+    lv2:name "Freewheeling Sample quality",
+      "Qualité des échantillons en roue libre"@fr;
+    pg:group <@LV2PLUGIN_URI@#config> ;
+    lv2:default 10.0 ;
+    lv2:minimum 0.0 ;
+    lv2:maximum 10.0
+  ] , [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 21 ;
+    lv2:symbol "freewheeling_oscillator_quality" ;
+    lv2:name "Freewheeling Oscillator quality",
+      "Qualité des oscillateurs en roue libre"@fr ;
+    pg:group <@LV2PLUGIN_URI@#config> ;
+    lv2:default 3.0 ;
+    lv2:minimum 0.0 ;
+    lv2:maximum 3.0
+  ] , [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 22 ;
+    lv2:symbol "sustain_cancels_release" ;
+    lv2:name "Sustain cancels release";
+    pg:group <@LV2PLUGIN_URI@#config> ;
+    lv2:portProperty lv2:toggled ;
+    lv2:default 0 ;
+    lv2:minimum 0 ;
+    lv2:maximum 1 ;
   ] ;
 
   rdfs:seeAlso <controllers.ttl> .
@@ -764,7 +794,7 @@ midnam:update a lv2:Feature .
     lv2:name "Sample quality",
       "Qualité des échantillons"@fr ,
       "Qualità del campione"@it ;
-    pg:group <@LV2PLUGIN_URI@#tuning> ;
+    pg:group <@LV2PLUGIN_URI@#config> ;
     lv2:default 2.0 ;
     lv2:minimum 0.0 ;
     lv2:maximum 10.0
@@ -775,7 +805,7 @@ midnam:update a lv2:Feature .
     lv2:name "Oscillator quality",
       "Qualité des oscillateurs"@fr ,
       "Qualità dell'oscillatore"@it ;
-    pg:group <@LV2PLUGIN_URI@#tuning> ;
+    pg:group <@LV2PLUGIN_URI@#config> ;
     lv2:default 1.0 ;
     lv2:minimum 0.0 ;
     lv2:maximum 3.0
@@ -845,6 +875,36 @@ midnam:update a lv2:Feature .
     lv2:default 0 ;
     lv2:minimum 0 ;
     lv2:maximum 65535 ;
+  ] , [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 34 ;
+    lv2:symbol "freewheeling_sample_quality" ;
+    lv2:name "Freewheeling Sample quality",
+      "Qualité des échantillons en roue libre"@fr;
+    pg:group <@LV2PLUGIN_URI@#config> ;
+    lv2:default 10.0 ;
+    lv2:minimum 0.0 ;
+    lv2:maximum 10.0
+  ] , [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 35 ;
+    lv2:symbol "freewheeling_oscillator_quality" ;
+    lv2:name "Freewheeling Oscillator quality",
+      "Qualité des oscillateurs en roue libre"@fr ;
+    pg:group <@LV2PLUGIN_URI@#config> ;
+    lv2:default 3.0 ;
+    lv2:minimum 0.0 ;
+    lv2:maximum 3.0
+  ] , [
+    a lv2:InputPort, lv2:ControlPort ;
+    lv2:index 36 ;
+    lv2:symbol "sustain_cancels_release" ;
+    lv2:name "Sustain cancels release";
+    pg:group <@LV2PLUGIN_URI@#config> ;
+    lv2:portProperty lv2:toggled ;
+    lv2:default 0 ;
+    lv2:minimum 0 ;
+    lv2:maximum 1 ;
   ] ;
 
   rdfs:seeAlso <controllers.ttl> .
diff --git a/plugins/lv2/sfizz_lv2.h b/plugins/lv2/sfizz_lv2.h
index c99f8bbb0..69867119f 100644
--- a/plugins/lv2/sfizz_lv2.h
+++ b/plugins/lv2/sfizz_lv2.h
@@ -73,6 +73,9 @@ enum
     SFIZZ_NUM_GROUPS = 17,
     SFIZZ_NUM_REGIONS = 18,
     SFIZZ_NUM_SAMPLES = 19,
+    SFIZZ_FREEWHEELING_SAMPLE_QUALITY = 20,
+    SFIZZ_FREEWHEELING_OSCILLATOR_QUALITY = 21,
+    SFIZZ_SUSTAIN_CANCELS_RELEASE = 22,
 };
 
 enum
@@ -111,6 +114,9 @@ enum
     SFIZZ_MULTI_NUM_GROUPS = 31,
     SFIZZ_MULTI_NUM_REGIONS = 32,
     SFIZZ_MULTI_NUM_SAMPLES = 33,
+    SFIZZ_MULTI_FREEWHEELING_SAMPLE_QUALITY = 34,
+    SFIZZ_MULTI_FREEWHEELING_OSCILLATOR_QUALITY = 35,
+    SFIZZ_MULTI_SUSTAIN_CANCELS_RELEASE = 36,
 };
 
 // For use with instance-access
diff --git a/plugins/lv2/sfizz_lv2_plugin.h b/plugins/lv2/sfizz_lv2_plugin.h
index e7a41c19b..26119138a 100644
--- a/plugins/lv2/sfizz_lv2_plugin.h
+++ b/plugins/lv2/sfizz_lv2_plugin.h
@@ -47,6 +47,9 @@ struct sfizz_plugin_t
     const float *stretch_tuning_port {};
     const float *sample_quality_port {};
     const float *oscillator_quality_port {};
+    const float *freewheeling_sample_quality_port {};
+    const float *freewheeling_oscillator_quality_port {};
+    const float *sustain_cancels_release_port {};
     float *active_voices_port {};
     float *num_curves_port {};
     float *num_masters_port {};
diff --git a/plugins/lv2/sfizz_ui.cpp b/plugins/lv2/sfizz_ui.cpp
index af98100e8..cd25d2881 100644
--- a/plugins/lv2/sfizz_ui.cpp
+++ b/plugins/lv2/sfizz_ui.cpp
@@ -354,6 +354,15 @@ port_event_stereo(sfizz_ui_t *self, uint32_t port_index, const void *buffer)
     case SFIZZ_NUM_SAMPLES:
         self->uiReceiveValue(EditId::UINumPreloadedSamples, v);
         break;
+    case SFIZZ_FREEWHEELING_SAMPLE_QUALITY:
+        self->uiReceiveValue(EditId::FreewheelingSampleQuality, v);
+        break;
+    case SFIZZ_FREEWHEELING_OSCILLATOR_QUALITY:
+        self->uiReceiveValue(EditId::FreewheelingOscillatorQuality, v);
+        break;
+    case SFIZZ_SUSTAIN_CANCELS_RELEASE:
+        self->uiReceiveValue(EditId::SustainCancelsRelease, v);
+        break;
     }
 }
 
@@ -408,6 +417,15 @@ port_event_multi(sfizz_ui_t *self, uint32_t port_index, const void *buffer)
     case SFIZZ_MULTI_NUM_SAMPLES:
         self->uiReceiveValue(EditId::UINumPreloadedSamples, v);
         break;
+    case SFIZZ_MULTI_FREEWHEELING_SAMPLE_QUALITY:
+        self->uiReceiveValue(EditId::FreewheelingSampleQuality, v);
+        break;
+    case SFIZZ_MULTI_FREEWHEELING_OSCILLATOR_QUALITY:
+        self->uiReceiveValue(EditId::FreewheelingOscillatorQuality, v);
+        break;
+    case SFIZZ_MULTI_SUSTAIN_CANCELS_RELEASE:
+        self->uiReceiveValue(EditId::SustainCancelsRelease, v);
+        break;
     }
 }
 
@@ -663,31 +681,76 @@ void sfizz_ui_t::uiSendValue(EditId id, const EditValue& v)
 
     switch (id) {
     case EditId::Volume:
-        sendFloat(SFIZZ_VOLUME, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_VOLUME, v.to_float());
+        else
+            sendFloat(SFIZZ_VOLUME, v.to_float());
         break;
     case EditId::Polyphony:
-        sendFloat(SFIZZ_POLYPHONY, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_POLYPHONY, v.to_float());
+        else
+            sendFloat(SFIZZ_POLYPHONY, v.to_float());
         break;
     case EditId::Oversampling:
-        sendFloat(SFIZZ_OVERSAMPLING, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_OVERSAMPLING, v.to_float());
+        else
+            sendFloat(SFIZZ_OVERSAMPLING, v.to_float());
         break;
     case EditId::PreloadSize:
-        sendFloat(SFIZZ_PRELOAD, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_PRELOAD, v.to_float());
+        else
+            sendFloat(SFIZZ_PRELOAD, v.to_float());
         break;
     case EditId::ScalaRootKey:
-        sendFloat(SFIZZ_SCALA_ROOT_KEY, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_SCALA_ROOT_KEY, v.to_float());
+        else
+            sendFloat(SFIZZ_SCALA_ROOT_KEY, v.to_float());
         break;
     case EditId::TuningFrequency:
-        sendFloat(SFIZZ_TUNING_FREQUENCY, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_TUNING_FREQUENCY, v.to_float());
+        else
+            sendFloat(SFIZZ_TUNING_FREQUENCY, v.to_float());
         break;
     case EditId::StretchTuning:
-        sendFloat(SFIZZ_STRETCH_TUNING, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_STRETCH_TUNING, v.to_float());
+        else
+            sendFloat(SFIZZ_STRETCH_TUNING, v.to_float());
         break;
     case EditId::SampleQuality:
-        sendFloat(SFIZZ_SAMPLE_QUALITY, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_SAMPLE_QUALITY, v.to_float());
+        else
+            sendFloat(SFIZZ_SAMPLE_QUALITY, v.to_float());
         break;
     case EditId::OscillatorQuality:
-        sendFloat(SFIZZ_OSCILLATOR_QUALITY, v.to_float());
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_OSCILLATOR_QUALITY, v.to_float());
+        else
+            sendFloat(SFIZZ_OSCILLATOR_QUALITY, v.to_float());
+        break;
+    case EditId::FreewheelingSampleQuality:
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_FREEWHEELING_SAMPLE_QUALITY, v.to_float());
+        else
+            sendFloat(SFIZZ_FREEWHEELING_SAMPLE_QUALITY, v.to_float());
+        break;
+    case EditId::FreewheelingOscillatorQuality:
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_FREEWHEELING_OSCILLATOR_QUALITY, v.to_float());
+        else
+            sendFloat(SFIZZ_FREEWHEELING_OSCILLATOR_QUALITY, v.to_float());
+        break;
+    case EditId::SustainCancelsRelease:
+        if (multi_out)
+            sendFloat(SFIZZ_MULTI_SUSTAIN_CANCELS_RELEASE, v.to_float());
+        else
+            sendFloat(SFIZZ_SUSTAIN_CANCELS_RELEASE, v.to_float());
         break;
     case EditId::SfzFile:
         sendPath(sfizz_sfz_file_uri, v.to_string());
diff --git a/plugins/vst/SfizzVstController.cpp b/plugins/vst/SfizzVstController.cpp
index 500acf95c..3dab25185 100644
--- a/plugins/vst/SfizzVstController.cpp
+++ b/plugins/vst/SfizzVstController.cpp
@@ -80,6 +80,18 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
         SfizzRange::getForParameter(kPidOscillatorQuality).createParameter(
             Steinberg::String("Oscillator quality"), pid++, nullptr,
             0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId));
+    parameters.addParameter(
+        SfizzRange::getForParameter(kPidFreewheelingSampleQuality).createParameter(
+            Steinberg::String("Freewheeling sample quality"), pid++, nullptr,
+            0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId));
+    parameters.addParameter(
+        SfizzRange::getForParameter(kPidFreewheelingOscillatorQuality).createParameter(
+            Steinberg::String("Freewheeling oscillator quality"), pid++, nullptr,
+            0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId));
+    parameters.addParameter(
+        SfizzRange::getForParameter(kPidSustainCancelsRelease).createParameter(
+            Steinberg::String("Sustain cancels release"), pid++, nullptr,
+            1, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId));
 
     // MIDI special controllers
     parameters.addParameter(
@@ -267,6 +279,9 @@ tresult PLUGIN_API SfizzVstControllerNoUi::setComponentState(IBStream* stream)
     setParam(kPidStretchedTuning, s.stretchedTuning);
     setParam(kPidSampleQuality, s.sampleQuality);
     setParam(kPidOscillatorQuality, s.oscillatorQuality);
+    setParam(kPidFreewheelingSampleQuality, s.freewheelingSampleQuality);
+    setParam(kPidFreewheelingOscillatorQuality, s.freewheelingOscillatorQuality);
+    setParam(kPidSustainCancelsRelease, s.sustainCancelsRelease);
 
     uint32 ccLimit = uint32(std::min(s.controllers.size(), size_t(sfz::config::numCCs)));
     for (uint32 cc = 0; cc < ccLimit; ++cc) {
diff --git a/plugins/vst/SfizzVstEditor.cpp b/plugins/vst/SfizzVstEditor.cpp
index ea9cf26c0..758b88fcf 100644
--- a/plugins/vst/SfizzVstEditor.cpp
+++ b/plugins/vst/SfizzVstEditor.cpp
@@ -343,6 +343,15 @@ void SfizzVstEditor::updateParameter(Vst::Parameter* parameterToUpdate)
         case kPidOscillatorQuality:
             uiReceiveValue(EditId::OscillatorQuality, range.denormalize(value));
             break;
+        case kPidFreewheelingSampleQuality:
+            uiReceiveValue(EditId::FreewheelingSampleQuality, range.denormalize(value));
+            break;
+        case kPidFreewheelingOscillatorQuality:
+            uiReceiveValue(EditId::FreewheelingOscillatorQuality, range.denormalize(value));
+            break;
+        case kPidSustainCancelsRelease:
+            uiReceiveValue(EditId::SustainCancelsRelease, range.denormalize(value));
+            break;
         case kPidNumOutputs:
             uiReceiveValue(EditId::PluginOutputs, (int32)range.denormalize(value));
             break;
@@ -406,7 +415,15 @@ void SfizzVstEditor::uiSendValue(EditId id, const EditValue& v)
         case EditId::OscillatorQuality:
             normalizeAndSet(kPidOscillatorQuality, v.to_float());
             break;
-
+        case EditId::FreewheelingSampleQuality:
+            normalizeAndSet(kPidFreewheelingSampleQuality, v.to_float());
+            break;
+        case EditId::FreewheelingOscillatorQuality:
+            normalizeAndSet(kPidFreewheelingOscillatorQuality, v.to_float());
+            break;
+        case EditId::SustainCancelsRelease:
+            normalizeAndSet(kPidSustainCancelsRelease, v.to_float());
+            break;
         case EditId::UserFilesDir:
             SfizzPaths::setSfzConfigDefaultPath(fs::u8path(v.to_string()));
             break;
diff --git a/plugins/vst/SfizzVstParameters.h b/plugins/vst/SfizzVstParameters.h
index 6f9c4e9a4..07d3bb4c3 100644
--- a/plugins/vst/SfizzVstParameters.h
+++ b/plugins/vst/SfizzVstParameters.h
@@ -22,6 +22,9 @@ enum {
     kPidStretchedTuning,
     kPidSampleQuality,
     kPidOscillatorQuality,
+    kPidFreewheelingSampleQuality,
+    kPidFreewheelingOscillatorQuality,
+    kPidSustainCancelsRelease,
     kPidAftertouch,
     kPidPitchBend,
     kPidCC0,
@@ -78,6 +81,12 @@ struct SfizzRange {
             return {2.0, 0.0, 10.0};
         case kPidOscillatorQuality:
             return {1.0, 0.0, 3.0};
+        case kPidFreewheelingSampleQuality:
+            return {10.0, 0.0, 10.0};
+        case kPidFreewheelingOscillatorQuality:
+            return {3.0, 0.0, 3.0};
+        case kPidSustainCancelsRelease:
+            return {0.0, 0.0, 1.0};
         case kPidAftertouch:
             return {0.0, 0.0, 1.0};
         case kPidPitchBend:
diff --git a/plugins/vst/SfizzVstProcessor.cpp b/plugins/vst/SfizzVstProcessor.cpp
index 3457fcac8..7df8689d3 100644
--- a/plugins/vst/SfizzVstProcessor.cpp
+++ b/plugins/vst/SfizzVstProcessor.cpp
@@ -334,6 +334,9 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data)
     }
     synth.setSampleQuality(sfz::Sfizz::ProcessLive, _state.sampleQuality);
     synth.setOscillatorQuality(sfz::Sfizz::ProcessLive, _state.oscillatorQuality);
+    synth.setSampleQuality(sfz::Sfizz::ProcessFreewheeling, _state.freewheelingSampleQuality);
+    synth.setOscillatorQuality(sfz::Sfizz::ProcessFreewheeling, _state.freewheelingOscillatorQuality);
+    synth.setSustainCancelsRelease(_state.sustainCancelsRelease);
 
     synth.renderBlock(outputs, numFrames, data.numOutputs);
 
@@ -450,6 +453,15 @@ void SfizzVstProcessor::playOrderedParameter(int32 sampleOffset, Vst::ParamID id
     case kPidOscillatorQuality:
         _state.oscillatorQuality = static_cast<int32>(range.denormalize(value));
         break;
+    case kPidFreewheelingSampleQuality:
+        _state.freewheelingSampleQuality = static_cast<int32>(range.denormalize(value));
+        break;
+    case kPidFreewheelingOscillatorQuality:
+        _state.freewheelingOscillatorQuality = static_cast<int32>(range.denormalize(value));
+        break;
+    case kPidSustainCancelsRelease:
+        _state.sustainCancelsRelease = (range.denormalize(value) > 0.0f);
+        break;
     case kPidAftertouch:
         synth.hdChannelAftertouch(sampleOffset, value);
         break;
diff --git a/plugins/vst/SfizzVstState.cpp b/plugins/vst/SfizzVstState.cpp
index 160d7abbe..091995915 100644
--- a/plugins/vst/SfizzVstState.cpp
+++ b/plugins/vst/SfizzVstState.cpp
@@ -73,6 +73,17 @@ tresult SfizzVstState::load(IBStream* state)
         oscillatorQuality = defaults.oscillatorQuality;
     }
 
+    if (version >= 5) {
+        if (!s.readInt32(freewheelingSampleQuality))
+            return kResultFalse;
+
+        if (!s.readInt32(freewheelingOscillatorQuality))
+            return kResultFalse;
+
+        if (!s.readBool(sustainCancelsRelease))
+            return kResultFalse;
+    }
+
     if (version >= 4) {
         if (!s.readInt32(lastKeyswitch))
             return kResultFalse;
@@ -143,6 +154,15 @@ tresult SfizzVstState::store(IBStream* state) const
     if (!s.writeInt32(oscillatorQuality))
         return kResultFalse;
 
+    if (!s.writeInt32(freewheelingSampleQuality))
+        return kResultFalse;
+
+    if (!s.writeInt32(freewheelingOscillatorQuality))
+        return kResultFalse;
+
+    if (!s.writeBool(sustainCancelsRelease))
+        return kResultFalse;
+
     if (!s.writeInt32(lastKeyswitch))
         return kResultFalse;
 
diff --git a/plugins/vst/SfizzVstState.h b/plugins/vst/SfizzVstState.h
index 93a7a4ec4..3b43ccfa9 100644
--- a/plugins/vst/SfizzVstState.h
+++ b/plugins/vst/SfizzVstState.h
@@ -27,10 +27,13 @@ class SfizzVstState {
     float stretchedTuning = 0.0;
     int32 sampleQuality = 2;
     int32 oscillatorQuality = 1;
+    int32 freewheelingSampleQuality = 10;
+    int32 freewheelingOscillatorQuality = 3;
+    bool sustainCancelsRelease = false;
     int32 lastKeyswitch = -1;
     std::vector<absl::optional<float>> controllers;
 
-    static constexpr uint64 currentStateVersion = 4;
+    static constexpr uint64 currentStateVersion = 5;
 
     tresult load(IBStream* state);
     tresult store(IBStream* state) const;
diff --git a/src/sfizz.h b/src/sfizz.h
index a709a6b43..0e55ed93b 100644
--- a/src/sfizz.h
+++ b/src/sfizz.h
@@ -833,6 +833,14 @@ SFIZZ_EXPORTED_API int sfizz_get_oscillator_quality(sfizz_synth_t* synth, sfizz_
  */
 SFIZZ_EXPORTED_API void sfizz_set_oscillator_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality);
 
+/**
+ * @brief Set whether pressing the sustain pedal cancels the release stage
+ *
+ * @param      synth    The synth.
+ * @param value
+*/
+SFIZZ_EXPORTED_API void sfizz_set_sustain_cancels_release(sfizz_synth_t* synth, bool value);
+
 /**
  * @brief Set the global instrument volume.
  * @since 0.2.0
diff --git a/src/sfizz.hpp b/src/sfizz.hpp
index 6b42db6fe..4ed458aea 100644
--- a/src/sfizz.hpp
+++ b/src/sfizz.hpp
@@ -360,6 +360,13 @@ class SFIZZ_EXPORTED_API Sfizz
      */
     void setOscillatorQuality(ProcessMode mode, int quality);
 
+    /**
+     * @brief Set whether pressing the sustain pedal cancels the release stage
+     *
+     * @param value
+     */
+    void setSustainCancelsRelease(bool value);
+
     /**
      * @brief Return the current value for the volume, in dB.
      * @since 0.2.0
diff --git a/src/sfizz/Defaults.cpp b/src/sfizz/Defaults.cpp
index 70bc3d014..319933368 100644
--- a/src/sfizz/Defaults.cpp
+++ b/src/sfizz/Defaults.cpp
@@ -40,7 +40,6 @@ FloatSpec oscillatorDetune { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds };
 FloatSpec oscillatorDetuneMod { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds };
 FloatSpec oscillatorModDepth { 0.0f, {0.0f, 10000.0f}, kNormalizePercent|kPermissiveBounds };
 FloatSpec oscillatorModDepthMod { 0.0f, {0.0f, 10000.0f}, kNormalizePercent|kPermissiveBounds };
-Int32Spec oscillatorQuality { 1, {0, 3}, 0 };
 Int64Spec group { 0, {-int32_t_max, uint32_t_max}, 0 };
 UInt16Spec output { 0, {0, config::maxChannels / 2 - 1}, kEnforceBounds };
 FloatSpec offTime { 6e-3f, {0.0f, 100.0f}, kPermissiveBounds };
@@ -162,6 +161,9 @@ FloatSpec flexEGPointLevel { 0.0f, {-1.0f, 1.0f}, kPermissiveBounds };
 FloatSpec flexEGPointLevelMod { 0.0f, {-1.0f, 1.0f}, kPermissiveBounds };
 FloatSpec flexEGPointShape { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds };
 Int32Spec sampleQuality { 2, {0, 10}, 0 };
+Int32Spec oscillatorQuality { 1, {0, 3}, 0 };
+Int32Spec freewheelingSampleQuality { 10, {0, 10}, 0 };
+Int32Spec freewheelingOscillatorQuality { 3, {0, 3}, 0 };
 Int32Spec octaveOffset { 0, {-10, 10}, kPermissiveBounds };
 Int32Spec noteOffset { 0, {-127, 127}, kPermissiveBounds };
 
diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h
index 9387369e8..0ddcba3e5 100644
--- a/src/sfizz/Defaults.h
+++ b/src/sfizz/Defaults.h
@@ -274,6 +274,8 @@ namespace Default
     extern const OpcodeSpec<float> flexEGPointLevelMod;
     extern const OpcodeSpec<float> flexEGPointShape;
     extern const OpcodeSpec<int32_t> sampleQuality;
+    extern const OpcodeSpec<int32_t> freewheelingSampleQuality;
+    extern const OpcodeSpec<int32_t> freewheelingOscillatorQuality;
     extern const OpcodeSpec<int32_t> octaveOffset;
     extern const OpcodeSpec<int32_t> noteOffset;
     extern const OpcodeSpec<float> effect;
@@ -335,8 +337,6 @@ namespace Default
 
     // Various defaut values
     // e.g. "additional" or multiple defautl values
-    constexpr int freewheelingSampleQuality { 10 };
-    constexpr int freewheelingOscillatorQuality { 3 };
     constexpr float globalVolume { -7.35f };
     constexpr float defaultEQFreq [numEQs] { 50.0f, 500.0f, 5000.0f };
 } // namespace Default
diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp
index 810f0fc25..f5749ff62 100644
--- a/src/sfizz/Synth.cpp
+++ b/src/sfizz/Synth.cpp
@@ -1810,6 +1810,7 @@ void Synth::setSampleQuality(ProcessMode mode, int quality)
         synthConfig.liveSampleQuality = quality;
         break;
     case ProcessFreewheeling:
+        // DBG("Set freewheeling quality" << quality);
         synthConfig.freeWheelingSampleQuality = quality;
         break;
     default:
@@ -1845,6 +1846,7 @@ void Synth::setOscillatorQuality(ProcessMode mode, int quality)
         synthConfig.liveOscillatorQuality = quality;
         break;
     case ProcessFreewheeling:
+        // DBG("Set freewheeling oscillator quality" << quality);
         synthConfig.freeWheelingOscillatorQuality = quality;
         break;
     default:
@@ -1853,6 +1855,11 @@ void Synth::setOscillatorQuality(ProcessMode mode, int quality)
     }
 }
 
+void Synth::setSustainCancelsRelease(bool value)
+{
+    impl_->resources_.getSynthConfig().sustainCancelsRelease = value;
+}
+
 float Synth::getVolume() const noexcept
 {
     Impl& impl = *impl_;
diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h
index 036500dd1..59e846223 100644
--- a/src/sfizz/Synth.h
+++ b/src/sfizz/Synth.h
@@ -334,6 +334,12 @@ class Synth final {
      * @param quality the quality setting
      */
     void setOscillatorQuality(ProcessMode mode, int quality);
+    /**
+     * @brief Set whether pressing the sustain pedal cancels the releases
+     *
+     * @param value
+     */
+    void setSustainCancelsRelease(bool value);
     /**
      * @brief Get the current value for the volume, in dB.
      *
diff --git a/src/sfizz/SynthMessaging.cpp b/src/sfizz/SynthMessaging.cpp
index d57a70fcb..95cbce8dd 100644
--- a/src/sfizz/SynthMessaging.cpp
+++ b/src/sfizz/SynthMessaging.cpp
@@ -8,6 +8,7 @@
 #include "FilePool.h"
 #include "Curve.h"
 #include "MidiState.h"
+#include "SynthConfig.h"
 #include "utility/StringViewHelpers.h"
 #include <absl/strings/ascii.h>
 #include <cstring>
@@ -1534,6 +1535,34 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
         // Setting values
         // Note: all these must be rt-safe within the parseOpcode method in region
 
+        MATCH("/sample_quality", "i") {
+            impl.resources_.getSynthConfig().liveSampleQuality =
+                Opcode::transform(Default::sampleQuality, static_cast<int>(args[0].i));
+        } break;
+
+        MATCH("/oscillator_quality", "i") {
+            impl.resources_.getSynthConfig().liveOscillatorQuality =
+                Opcode::transform(Default::oscillatorQuality, static_cast<int>(args[0].i));
+        } break;
+
+        MATCH("/freewheeling_sample_quality", "i") {
+            impl.resources_.getSynthConfig().freeWheelingSampleQuality =
+                Opcode::transform(Default::freewheelingSampleQuality, static_cast<int>(args[0].i));
+        } break;
+
+        MATCH("/freewheeling_oscillator_quality", "i") {
+            impl.resources_.getSynthConfig().freeWheelingOscillatorQuality =
+                Opcode::transform(Default::freewheelingOscillatorQuality, static_cast<int>(args[0].i));
+        } break;
+
+        MATCH("/sustain_cancels_release", "T") {
+            impl.resources_.getSynthConfig().sustainCancelsRelease = true;
+        } break;
+
+        MATCH("/sustain_cancels_release", "F") {
+            impl.resources_.getSynthConfig().sustainCancelsRelease = false;
+        } break;
+
         #define GET_REGION_OR_BREAK(idx)            \
             if (idx >= impl.layers_.size())         \
                 break;                              \
diff --git a/src/sfizz/sfizz.cpp b/src/sfizz/sfizz.cpp
index 4c96a69a5..be67cc064 100644
--- a/src/sfizz/sfizz.cpp
+++ b/src/sfizz/sfizz.cpp
@@ -150,6 +150,11 @@ void sfz::Sfizz::setOscillatorQuality(ProcessMode mode, int quality)
     synth->synth.setOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
 }
 
+void sfz::Sfizz::setSustainCancelsRelease(bool value)
+{
+    synth->synth.setSustainCancelsRelease(value);
+}
+
 float sfz::Sfizz::getVolume() const noexcept
 {
     return synth->synth.getVolume();
diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp
index 0c9a3b350..bfa0983a5 100644
--- a/src/sfizz/sfizz_wrapper.cpp
+++ b/src/sfizz/sfizz_wrapper.cpp
@@ -236,6 +236,11 @@ void sfizz_set_oscillator_quality(sfizz_synth_t* synth, sfizz_process_mode_t mod
     return synth->synth.setOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
 }
 
+void sfizz_set_sustain_cancels_release(sfizz_synth_t* synth, bool value)
+{
+    return synth->synth.setSustainCancelsRelease(value);
+}
+
 void sfizz_set_volume(sfizz_synth_t* synth, float volume)
 {
     synth->synth.setVolume(volume);