Merge pull request #1022 from paulfd/options-panel

Updated options panel and random things in the UI
This commit is contained in:
Paul Ferrand 2021-11-12 12:10:03 +01:00 committed by GitHub
commit 37613d528c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 760 additions and 267 deletions

View file

@ -3,11 +3,11 @@ version 1.0304
header_name {.h} header_name {.h}
code_name {.cxx} code_name {.cxx}
widget_class mainView {open widget_class mainView {open
xywh {108 91 800 475} type Double xywh {607 439 800 475} type Double
class LogicalGroup visible class LogicalGroup visible
} { } {
Fl_Box imageContainer_ { Fl_Box imageContainer_ {
image {../resources/background.png} xywh {5 110 790 285} image {../resources/background.png} xywh {90 110 790 285}
class Background class Background
} }
Fl_Group {} { Fl_Group {} {
@ -15,7 +15,7 @@ widget_class mainView {open
xywh {0 0 814 110} xywh {0 0 814 110}
class LogicalGroup class LogicalGroup
} { } {
Fl_Group {} {open Fl_Group {} {
xywh {5 4 175 101} box ROUNDED_BOX align 0 xywh {5 4 175 101} box ROUNDED_BOX align 0
class RoundedGroup class RoundedGroup
} { } {
@ -45,7 +45,7 @@ widget_class mainView {open
class HomeButton class HomeButton
} }
} }
Fl_Group {} {open Fl_Group {} {
xywh {185 5 390 100} box ROUNDED_BOX xywh {185 5 390 100} box ROUNDED_BOX
class RoundedGroup class RoundedGroup
} { } {
@ -126,7 +126,7 @@ widget_class mainView {open
class ChevronValueDropDown class ChevronValueDropDown
} }
} }
Fl_Group {} {open Fl_Group {} {
xywh {580 5 215 100} box ROUNDED_BOX xywh {580 5 215 100} box ROUNDED_BOX
class RoundedGroup class RoundedGroup
} { } {
@ -155,17 +155,17 @@ widget_class mainView {open
xywh {739 10 23 90} box BORDER_BOX xywh {739 10 23 90} box BORDER_BOX
class VMeter class VMeter
} }
Fl_Box {meters_[1]} {selected Fl_Box {meters_[1]} {
xywh {763 10 23 90} box BORDER_BOX xywh {763 10 23 90} box BORDER_BOX
class VMeter class VMeter
} }
} }
} }
Fl_Group {subPanels_[kPanelInfo]} { Fl_Group {subPanels_[kPanelInfo]} {open
xywh {5 110 790 285} hide xywh {5 110 790 285} hide
class LogicalGroup class LogicalGroup
} { } {
Fl_Group {} {open Fl_Group {} {
xywh {5 110 790 285} box ROUNDED_BOX xywh {5 110 790 285} box ROUNDED_BOX
class RoundedGroup class RoundedGroup
} { } {
@ -225,7 +225,7 @@ widget_class mainView {open
xywh {5 110 790 285} hide xywh {5 110 790 285} hide
class LogicalGroup class LogicalGroup
} { } {
Fl_Group {} {open Fl_Group {} {
xywh {5 110 790 285} box ROUNDED_BOX xywh {5 110 790 285} box ROUNDED_BOX
class RoundedGroup class RoundedGroup
} { } {
@ -235,150 +235,216 @@ widget_class mainView {open
} {} } {}
} }
} }
Fl_Group {subPanels_[kPanelSettings]} { Fl_Group {subPanels_[kPanelSettings]} {open
xywh {5 110 790 285} xywh {0 110 825 360}
class LogicalGroup class LogicalGroup
} { } {
Fl_Group {} { Fl_Group {} {open
label Engine open xywh {5 110 790 285} box ROUNDED_BOX
xywh {305 135 195 100} box ROUNDED_BOX labelsize 12 align 17 class RoundedGroup
class TitleGroup
} { } {
Fl_Spinner oversamplingSlider_ { Fl_Spinner oversamplingSlider_ {
comment {tag=kTagSetOversampling} comment {tag=kTagSetOversampling}
xywh {330 195 60 25} labelsize 12 textsize 12 xywh {175 195 70 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Box {} { Fl_Box {} {
label Oversampling label Oversampling
xywh {320 155 80 25} labelsize 12 xywh {20 195 85 25} labelsize 12 align 20
class ValueLabel class Label
} }
Fl_Box {} { Fl_Box {} {
label {Preload size} label {Preload size}
xywh {405 155 80 25} labelsize 12 xywh {20 170 75 25} labelsize 12 align 20
class ValueLabel class Label
} }
Fl_Spinner preloadSizeSlider_ { Fl_Spinner preloadSizeSlider_ {
comment {tag=kTagSetPreloadSize} comment {tag=kTagSetPreloadSize}
xywh {415 195 60 25} labelsize 12 textsize 12 xywh {175 170 70 25} labelsize 12 textsize 12
class ValueMenu 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
}
Fl_Spinner tuningFrequencySlider_ {
comment {tag=kTagSetTuningFrequency}
xywh {425 330 60 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Box {} {
label Frequency
xywh {415 290 80 25} labelsize 12
class ValueLabel
}
Fl_Dial stretchedTuningSlider_ {
comment {tag=kTagSetStretchedTuning}
xywh {515 315 48 48} value 0.5
class StyledKnob
}
Fl_Box {} {
label Stretch
xywh {500 290 80 25} labelsize 12
class ValueLabel
}
Fl_Box {} {
label {Scala file}
xywh {195 290 100 25} labelsize 12
class ValueLabel
}
Fl_Button scalaFileButton_ {
label DefaultScale
comment {tag=kTagLoadScalaFile}
xywh {195 330 100 25} labelsize 12
class ValueButton
}
Fl_Spinner scalaRootKeySlider_ {
comment {tag=kTagSetScalaRootKey}
xywh {340 330 35 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Spinner scalaRootOctaveSlider_ {
comment {tag=kTagSetScalaRootKey}
xywh {375 330 30 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Button scalaResetButton_ {
comment {tag=kTagResetScalaFile}
xywh {295 330 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
}
}
Fl_Group {} {
label Quality open
xywh {530 135 195 100} box ROUNDED_BOX labelsize 12 align 17
class TitleGroup
} {
Fl_Spinner sampleQualitySlider_ { Fl_Spinner sampleQualitySlider_ {
comment {tag=kTagSetSampleQuality} comment {tag=kTagSetSampleQuality}
xywh {545 195 80 25} labelsize 12 textsize 12 xywh {435 145 80 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Box {} { Fl_Box {} {
label Sample label Sample
xywh {545 155 80 25} labelsize 12 xywh {290 145 50 25} labelsize 12 align 20
class ValueLabel class Label
} }
Fl_Box {} { Fl_Box {} {
label Oscillator label Oscillator
xywh {630 155 80 25} labelsize 12 xywh {290 195 60 25} labelsize 12 align 20
class ValueLabel class Label
} }
Fl_Spinner oscillatorQualitySlider_ { Fl_Spinner oscillatorQualitySlider_ {
comment {tag=kTagSetOscillatorQuality} comment {tag=kTagSetOscillatorQuality}
xywh {630 195 80 25} labelsize 12 textsize 12 xywh {435 195 80 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
}
Fl_Group {} {
label Appearance open
xywh {40 270 105 100} box ROUNDED_BOX labelsize 12 align 17
class TitleGroup
} {
Fl_Spinner themeMenu_ { Fl_Spinner themeMenu_ {
comment {tag=kTagThemeMenu} comment {tag=kTagThemeMenu}
xywh {60 330 65 25} labelsize 12 textsize 12 xywh {680 145 100 25} labelsize 12 textsize 12
class OptionMenu class OptionMenu
} }
Fl_Box {} { Fl_Box {} {
label Theme label Theme
xywh {50 295 80 25} labelsize 12 xywh {555 145 45 25} labelsize 12 align 20
class ValueLabel 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 {555 310 70 25} labelsize 12 align 20
class Label
}
Fl_Dial stretchedTuningSlider_ {
comment {tag=kTagSetStretchedTuning}
xywh {720 337 48 48} value 0.5
class StyledKnob
}
Fl_Box {} {
label Stretch
xywh {555 345 50 25} labelsize 12 align 20
class Label
}
Fl_Box {} {
label {Scala file}
xywh {555 260 60 25} labelsize 12 align 20
class Label
}
Fl_Button scalaFileButton_ {
label DefaultScale
comment {tag=kTagLoadScalaFile}
xywh {655 260 100 25} labelsize 12
class ValueButton
}
Fl_Spinner scalaRootKeySlider_ {
comment {tag=kTagSetScalaRootKey}
xywh {715 285 35 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Spinner scalaRootOctaveSlider_ {
comment {tag=kTagSetScalaRootKey}
xywh {750 285 30 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Button scalaResetButton_ {
comment {tag=kTagResetScalaFile}
xywh {755 260 25 25} labelsize 12
class ResetSomethingButton
}
Fl_Box {} {
label {... when freewheeling}
xywh {290 170 145 25} labelsize 12 align 20
class Label
}
Fl_Spinner freewheelingSampleQualitySlider_ {
comment {tag=kTagSetFreewheelingSampleQuality}
xywh {435 170 80 25} labelsize 12 textsize 12
class ValueMenu
}
Fl_Box {} {
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 {Rendering quality}
xywh {290 115 110 25} labelsize 12 align 20
class Label
}
Fl_Box {} {
label {Separator 2}
xywh {20 135 225 5} box BORDER_BOX labeltype NO_LABEL
class HLine
}
Fl_Box {} {
label {Engine options}
xywh {20 115 95 25} labelsize 12 align 20
class Label
}
Fl_Box {} {
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
} }
} }
} }

View file

@ -27,9 +27,15 @@ EditRange EditRange::get(EditId id)
case EditId::StretchTuning: case EditId::StretchTuning:
return { 0, 0, 1 }; return { 0, 0, 1 };
case EditId::SampleQuality: case EditId::SampleQuality:
return { 1, 0, 10 }; return { 2, 0, 10 };
case EditId::OscillatorQuality: case EditId::OscillatorQuality:
return { 1, 0, 3 }; 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: case EditId::UIActivePanel:
return { 0, 0, 255 }; return { 0, 0, 255 };
} }

View file

@ -20,6 +20,9 @@ enum class EditId : int {
StretchTuning, StretchTuning,
SampleQuality, SampleQuality,
OscillatorQuality, OscillatorQuality,
FreewheelingSampleQuality,
FreewheelingOscillatorQuality,
SustainCancelsRelease,
CanEditUserFilesDir, CanEditUserFilesDir,
UserFilesDir, UserFilesDir,
FallbackFilesDir, FallbackFilesDir,

View file

@ -10,6 +10,7 @@
#include "GUIComponents.h" #include "GUIComponents.h"
#include "GUIHelpers.h" #include "GUIHelpers.h"
#include "GUIPiano.h" #include "GUIPiano.h"
#include "GitBuildId.h"
#include "DlgAbout.h" #include "DlgAbout.h"
#include "ImageHelpers.h" #include "ImageHelpers.h"
#include "NativeHelpers.h" #include "NativeHelpers.h"
@ -20,6 +21,7 @@
#include <absl/strings/string_view.h> #include <absl/strings/string_view.h>
#include <absl/strings/match.h> #include <absl/strings/match.h>
#include <absl/strings/ascii.h> #include <absl/strings/ascii.h>
#include <absl/strings/str_cat.h>
#include <absl/strings/numbers.h> #include <absl/strings/numbers.h>
#include <ghc/fs_std.hpp> #include <ghc/fs_std.hpp>
#include <array> #include <array>
@ -96,6 +98,9 @@ struct Editor::Impl : EditorController::Receiver,
kTagSetStretchedTuning, kTagSetStretchedTuning,
kTagSetSampleQuality, kTagSetSampleQuality,
kTagSetOscillatorQuality, kTagSetOscillatorQuality,
kTagSetFreewheelingSampleQuality,
kTagSetFreewheelingOscillatorQuality,
kTagSetSustainCancelsRelease,
kTagSetCCVolume, kTagSetCCVolume,
kTagSetCCPan, kTagSetCCPan,
kTagChooseUserFilesDir, kTagChooseUserFilesDir,
@ -120,12 +125,17 @@ struct Editor::Impl : EditorController::Receiver,
SValueMenu *scalaRootKeySlider_ = nullptr; SValueMenu *scalaRootKeySlider_ = nullptr;
SValueMenu *scalaRootOctaveSlider_ = nullptr; SValueMenu *scalaRootOctaveSlider_ = nullptr;
CTextLabel* scalaRootKeyLabel_ = nullptr; CTextLabel* scalaRootKeyLabel_ = nullptr;
SValueMenu *tuningFrequencySlider_ = nullptr; SValueMenu* tuningFrequencyDropdown_ = nullptr;
CTextEdit* tuningFrequencyEdit_ = nullptr;
STextButton *settingsAboutButton_ = nullptr;
CTextLabel* tuningFrequencyLabel_ = nullptr; CTextLabel* tuningFrequencyLabel_ = nullptr;
CControl *stretchedTuningSlider_ = nullptr; CControl *stretchedTuningSlider_ = nullptr;
CTextLabel* stretchedTuningLabel_ = nullptr; CTextLabel* stretchedTuningLabel_ = nullptr;
SValueMenu *sampleQualitySlider_ = nullptr; SValueMenu *sampleQualitySlider_ = nullptr;
SValueMenu *oscillatorQualitySlider_ = nullptr; SValueMenu *oscillatorQualitySlider_ = nullptr;
SValueMenu *freewheelingSampleQualitySlider_ = nullptr;
SValueMenu *freewheelingOscillatorQualitySlider_ = nullptr;
CCheckBox *sustainCancelsReleaseCheckbox_ = nullptr;
CTextLabel* keyswitchLabel_ = nullptr; CTextLabel* keyswitchLabel_ = nullptr;
CTextLabel* keyswitchInactiveLabel_ = nullptr; CTextLabel* keyswitchInactiveLabel_ = nullptr;
CTextLabel* keyswitchBadge_ = nullptr; CTextLabel* keyswitchBadge_ = nullptr;
@ -161,6 +171,8 @@ struct Editor::Impl : EditorController::Receiver,
SharedPointer<CBitmap> backgroundBitmap_; SharedPointer<CBitmap> backgroundBitmap_;
SharedPointer<CBitmap> defaultBackgroundBitmap_; SharedPointer<CBitmap> defaultBackgroundBitmap_;
CTextLabel* sfizzVersionLabel_ = nullptr;
SKnobCCBox* getSecondaryCCKnob(unsigned cc) SKnobCCBox* getSecondaryCCKnob(unsigned cc)
{ {
switch (cc) { switch (cc) {
@ -219,7 +231,6 @@ struct Editor::Impl : EditorController::Receiver,
void updateOversamplingLabel(int oversamplingLog2); void updateOversamplingLabel(int oversamplingLog2);
void updatePreloadSizeLabel(int preloadSize); void updatePreloadSizeLabel(int preloadSize);
void updateScalaRootKeyLabel(int rootKey); void updateScalaRootKeyLabel(int rootKey);
void updateTuningFrequencyLabel(float tuningFrequency);
void updateStretchedTuningLabel(float stretchedTuning); void updateStretchedTuningLabel(float stretchedTuning);
absl::string_view getCurrentKeyswitchName() const; absl::string_view getCurrentKeyswitchName() const;
@ -410,9 +421,8 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v)
case EditId::TuningFrequency: case EditId::TuningFrequency:
{ {
const float value = v.to_float(); const float value = v.to_float();
if (tuningFrequencySlider_) if (tuningFrequencyEdit_)
tuningFrequencySlider_->setValue(value); tuningFrequencyEdit_->setValue(value);
updateTuningFrequencyLabel(value);
} }
break; break;
case EditId::StretchTuning: case EditId::StretchTuning:
@ -441,6 +451,33 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v)
} }
} }
break; 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: case EditId::CanEditUserFilesDir:
{ {
if (STitleContainer* group = userFilesGroup_) if (STitleContainer* group = userFilesGroup_)
@ -695,6 +732,7 @@ void Editor::Impl::createFrameContents()
}); });
return box; return box;
}; };
#if 0
auto createTitleGroup = [this, &palette](const CRect& bounds, int, const char* label, CHoriTxtAlign, int fontsize) { auto createTitleGroup = [this, &palette](const CRect& bounds, int, const char* label, CHoriTxtAlign, int fontsize) {
auto* box = new STitleContainer(bounds, label); auto* box = new STitleContainer(bounds, label);
box->setCornerRadius(10.0); box->setCornerRadius(10.0);
@ -707,6 +745,7 @@ void Editor::Impl::createFrameContents()
box->setTitleFont(font); box->setTitleFont(font);
return box; return box;
}; };
#endif
auto createAboutButton = [this, &iconShaded](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int) { auto createAboutButton = [this, &iconShaded](const CRect& bounds, int tag, const char*, CHoriTxtAlign, int) {
return new CKickButton(bounds, this, tag, 0.0f, iconShaded); return new CKickButton(bounds, this, tag, 0.0f, iconShaded);
}; };
@ -734,11 +773,13 @@ void Editor::Impl::createFrameContents()
lbl->setFont(font); lbl->setFont(font);
return lbl; 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)); int y = static_cast<int>(0.5 * (bounds.top + bounds.bottom));
CRect lineBounds(bounds.left, y, bounds.right, y + 1); CRect lineBounds(bounds.left, y, bounds.right, y + 1);
CViewContainer* hline = new CViewContainer(lineBounds); CViewContainer* hline = new CViewContainer(lineBounds);
hline->setBackgroundColor(CColor(0xff, 0xff, 0xff, 0xff)); OnThemeChanged.push_back([hline, palette]() {
hline->setBackgroundColor(palette->text);
});
return hline; return hline;
}; };
auto createValueLabel = [this, &palette](const CRect& bounds, int, const char* label, CHoriTxtAlign align, int fontsize) { 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); lbl->setFont(font);
return lbl; 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) { auto createClickableLabel = [this, &palette](const CRect& bounds, int tag, const char* label, CHoriTxtAlign align, int fontsize) {
STextButton* button = new STextButton(bounds, this, tag, label); STextButton* button = new STextButton(bounds, this, tag, label);
auto font = makeOwned<CFontDesc>("Roboto", fontsize); auto font = makeOwned<CFontDesc>("Roboto", fontsize);
@ -982,6 +1015,26 @@ void Editor::Impl::createFrameContents()
return panel; 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" #include "layout/main.hpp"
OnThemeChanged.push_back([mainView, theme]() { OnThemeChanged.push_back([mainView, theme]() {
@ -1025,6 +1078,11 @@ void Editor::Impl::createFrameContents()
mainView_ = owned(mainView); 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(); currentThemeName_ = theme->loadCurrentName();
theme->load(currentThemeName_); theme->load(currentThemeName_);
@ -1061,11 +1119,15 @@ void Editor::Impl::createFrameContents()
scalaRootOctaveSlider_->setDefaultValue( scalaRootOctaveSlider_->setDefaultValue(
static_cast<int>(EditRange::get(EditId::ScalaRootKey).def) / 12); static_cast<int>(EditRange::get(EditId::ScalaRootKey).def) / 12);
} }
adjustMinMaxToEditRange(tuningFrequencySlider_, EditId::TuningFrequency); adjustMinMaxToEditRange(tuningFrequencyDropdown_, EditId::TuningFrequency);
tuningFrequencySlider_->setWheelInc(0.1f / EditRange::get(EditId::TuningFrequency).extent()); adjustMinMaxToEditRange(tuningFrequencyEdit_, EditId::TuningFrequency);
tuningFrequencyEdit_->setWheelInc(0.1f / EditRange::get(EditId::TuningFrequency).extent());
adjustMinMaxToEditRange(stretchedTuningSlider_, EditId::StretchTuning); adjustMinMaxToEditRange(stretchedTuningSlider_, EditId::StretchTuning);
adjustMinMaxToEditRange(sampleQualitySlider_, EditId::SampleQuality); adjustMinMaxToEditRange(sampleQualitySlider_, EditId::SampleQuality);
adjustMinMaxToEditRange(oscillatorQualitySlider_, EditId::OscillatorQuality); 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}) for (int value : {1, 2, 4, 8, 16, 32, 64, 96, 128, 160, 192, 224, 256})
numVoicesSlider_->addEntry(std::to_string(value), value); numVoicesSlider_->addEntry(std::to_string(value), value);
@ -1110,14 +1172,25 @@ void Editor::Impl::createFrameContents()
}; };
for (std::pair<float, const char*> value : tuningFrequencies) for (std::pair<float, const char*> value : tuningFrequencies)
tuningFrequencySlider_->addEntry(value.second, value.first); tuningFrequencyDropdown_->addEntry(value.second, value.first);
tuningFrequencySlider_->setValueToStringFunction(
tuningFrequencyEdit_->setValueToStringFunction(
[](float value, char result[256], CParamDisplay*) -> bool [](float value, char result[256], CParamDisplay*) -> bool
{ {
sprintf(result, "%.1f Hz", value); sprintf(result, "%.1f Hz", value);
return true; 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] = { static const char* notesInOctave[12] = {
"C", "C#", "D", "D#", "E", "C", "C#", "D", "D#", "E",
"F", "F#", "G", "G#", "A", "A#", "B", "F", "F#", "G", "G#", "A", "A#", "B",
@ -1146,36 +1219,49 @@ void Editor::Impl::createFrameContents()
menu->addEntry("Open SFZ folder", kTagOpenSfzFolder); menu->addEntry("Open SFZ folder", kTagOpenSfzFolder);
} }
if (SValueMenu *menu = sampleQualitySlider_) { static const std::array<const char*, 11> sampleQualityLabels {{
static const std::array<const char*, 11> labels {{ "Nearest", "Linear", "Polynomial",
"Nearest", "Linear", "Polynomial", "Sinc 8", "Sinc 12", "Sinc 16", "Sinc 24",
"Sinc 8", "Sinc 12", "Sinc 16", "Sinc 24", "Sinc 36", "Sinc 48", "Sinc 60", "Sinc 72",
"Sinc 36", "Sinc 48", "Sinc 60", "Sinc 72", }};
}};
for (size_t i = 0; i < labels.size(); ++i) auto setupSampleQualityMenu = [&] (SValueMenu* menu) {
menu->addEntry(labels[i], float(i)); if (menu) {
menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool { for (size_t i = 0; i < sampleQualityLabels.size(); ++i)
int index = int(value); menu->addEntry(sampleQualityLabels[i], float(i));
if (index < 0 || unsigned(index) >= labels.size()) menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
return false; int index = int(value);
result = labels[unsigned(index)]; if (index < 0 || unsigned(index) >= sampleQualityLabels.size())
return true; return false;
}); result = sampleQualityLabels[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) setupSampleQualityMenu(sampleQualitySlider_);
menu->addEntry(labels[i], float(i)); setupSampleQualityMenu(freewheelingSampleQualitySlider_);
menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
int index = int(value); static const std::array<const char*, 4> oscillatorQualityLabels {{
if (index < 0 || unsigned(index) >= labels.size()) "Nearest", "Linear", "High", "Dual-High",
return false; }};
result = labels[unsigned(index)];
return true; 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_) { if (SPiano* piano = piano_) {
piano->onKeyPressed = [this](unsigned key, float vel) { piano->onKeyPressed = [this](unsigned key, float vel) {
@ -1616,18 +1702,6 @@ void Editor::Impl::updateScalaRootKeyLabel(int rootKey)
label->setText(noteName(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) void Editor::Impl::updateStretchedTuningLabel(float stretchedTuning)
{ {
CTextLabel* label = stretchedTuningLabel_; CTextLabel* label = stretchedTuningLabel_;
@ -1962,7 +2036,8 @@ void Editor::Impl::valueChanged(CControl* ctl)
case kTagSetTuningFrequency: case kTagSetTuningFrequency:
ctrl.uiSendValue(EditId::TuningFrequency, value); ctrl.uiSendValue(EditId::TuningFrequency, value);
updateTuningFrequencyLabel(value); if (tuningFrequencyEdit_)
tuningFrequencyEdit_->setValue(value);
break; break;
case kTagSetSampleQuality: case kTagSetSampleQuality:
@ -1973,6 +2048,18 @@ void Editor::Impl::valueChanged(CControl* ctl)
ctrl.uiSendValue(EditId::OscillatorQuality, value); ctrl.uiSendValue(EditId::OscillatorQuality, value);
break; 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: case kTagSetStretchedTuning:
ctrl.uiSendValue(EditId::StretchTuning, value); ctrl.uiSendValue(EditId::StretchTuning, value);
updateStretchedTuningLabel(value); updateStretchedTuningLabel(value);

View file

@ -1,7 +1,7 @@
/* This file is generated by the layout maker tool. */ /* This file is generated by the layout maker tool. */
auto* const view__0 = createLogicalGroup(CRect(0, 0, 800, 475), -1, "", kCenterText, 14); auto* const view__0 = createLogicalGroup(CRect(0, 0, 800, 475), -1, "", kCenterText, 14);
mainView = view__0; 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; imageContainer_ = view__1;
view__0->addView(view__1); view__0->addView(view__1);
enterPalette(invertedPalette); enterPalette(invertedPalette);
@ -128,80 +128,113 @@ view__45->addView(view__46);
auto* const view__47 = createControlsPanel(CRect(0, 0, 790, 285), -1, "", kCenterText, 12); auto* const view__47 = createControlsPanel(CRect(0, 0, 790, 285), -1, "", kCenterText, 12);
controlsPanel_ = view__47; controlsPanel_ = view__47;
view__46->addView(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; subPanels_[kPanelSettings] = view__48;
view__0->addView(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); 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; oversamplingSlider_ = view__50;
view__49->addView(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); 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); 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; preloadSizeSlider_ = view__53;
view__49->addView(view__53); view__49->addView(view__53);
auto* const view__54 = createTitleGroup(CRect(170, 160, 585, 260), -1, "Tuning", kCenterText, 12); auto* const view__54 = createValueMenu(CRect(430, 35, 510, 60), kTagSetSampleQuality, "", kCenterText, 12);
view__48->addView(view__54); sampleQualitySlider_ = view__54;
auto* const view__55 = createValueLabel(CRect(155, 20, 235, 45), -1, "Root key", kCenterText, 12); view__49->addView(view__54);
view__54->addView(view__55); auto* const view__55 = createLabel(CRect(285, 35, 335, 60), -1, "Sample", kLeftText, 12);
auto* const view__56 = createValueMenu(CRect(250, 60, 310, 85), kTagSetTuningFrequency, "", kCenterText, 12); view__49->addView(view__55);
tuningFrequencySlider_ = view__56; auto* const view__56 = createLabel(CRect(285, 85, 345, 110), -1, "Oscillator", kLeftText, 12);
view__54->addView(view__56); view__49->addView(view__56);
auto* const view__57 = createValueLabel(CRect(240, 20, 320, 45), -1, "Frequency", kCenterText, 12); auto* const view__57 = createValueMenu(CRect(430, 85, 510, 110), kTagSetOscillatorQuality, "", kCenterText, 12);
view__54->addView(view__57); oscillatorQualitySlider_ = view__57;
auto* const view__58 = createStyledKnob(CRect(340, 45, 388, 93), kTagSetStretchedTuning, "", kCenterText, 14); view__49->addView(view__57);
stretchedTuningSlider_ = view__58; auto* const view__58 = createOptionMenu(CRect(675, 35, 775, 60), kTagThemeMenu, "", kCenterText, 12);
view__54->addView(view__58); themeMenu_ = view__58;
auto* const view__59 = createValueLabel(CRect(325, 20, 405, 45), -1, "Stretch", kCenterText, 12); view__49->addView(view__58);
view__54->addView(view__59); auto* const view__59 = createLabel(CRect(550, 35, 595, 60), -1, "Theme", kLeftText, 12);
auto* const view__60 = createValueLabel(CRect(20, 20, 120, 45), -1, "Scala file", kCenterText, 12); view__49->addView(view__59);
view__54->addView(view__60); auto* const view__60 = createLabel(CRect(550, 60, 645, 85), -1, "User SFZ folder", kLeftText, 12);
auto* const view__61 = createValueButton(CRect(20, 60, 120, 85), kTagLoadScalaFile, "DefaultScale", kCenterText, 12); view__49->addView(view__60);
scalaFileButton_ = view__61; auto* const view__61 = createValueButton(CRect(675, 60, 775, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12);
view__54->addView(view__61); userFilesDirButton_ = view__61;
auto* const view__62 = createValueMenu(CRect(165, 60, 200, 85), kTagSetScalaRootKey, "", kCenterText, 12); view__49->addView(view__61);
scalaRootKeySlider_ = view__62; auto* const view__62 = createLabel(CRect(550, 175, 610, 200), -1, "Root key", kLeftText, 12);
view__54->addView(view__62); view__49->addView(view__62);
auto* const view__63 = createValueMenu(CRect(200, 60, 230, 85), kTagSetScalaRootKey, "", kCenterText, 12); auto* const view__63 = createLabel(CRect(550, 200, 620, 225), -1, "Frequency", kLeftText, 12);
scalaRootOctaveSlider_ = view__63; view__49->addView(view__63);
view__54->addView(view__63); auto* const view__64 = createStyledKnob(CRect(715, 227, 763, 275), kTagSetStretchedTuning, "", kCenterText, 14);
auto* const view__64 = createResetSomethingButton(CRect(120, 60, 145, 85), kTagResetScalaFile, "", kCenterText, 12); stretchedTuningSlider_ = view__64;
scalaResetButton_ = view__64; view__49->addView(view__64);
view__54->addView(view__64); auto* const view__65 = createLabel(CRect(550, 235, 600, 260), -1, "Stretch", kLeftText, 12);
auto* const view__65 = createTitleGroup(CRect(615, 160, 754, 260), -1, "Files", kCenterText, 12); view__49->addView(view__65);
userFilesGroup_ = view__65; auto* const view__66 = createLabel(CRect(550, 150, 610, 175), -1, "Scala file", kLeftText, 12);
view__48->addView(view__65); view__49->addView(view__66);
auto* const view__66 = createValueLabel(CRect(20, 20, 120, 45), -1, "User SFZ folder", kCenterText, 12); auto* const view__67 = createValueButton(CRect(650, 150, 750, 175), kTagLoadScalaFile, "DefaultScale", kCenterText, 12);
view__65->addView(view__66); scalaFileButton_ = view__67;
auto* const view__67 = createValueButton(CRect(20, 60, 120, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12); view__49->addView(view__67);
userFilesDirButton_ = view__67; auto* const view__68 = createValueMenu(CRect(710, 175, 745, 200), kTagSetScalaRootKey, "", kCenterText, 12);
view__65->addView(view__67); scalaRootKeySlider_ = view__68;
auto* const view__68 = createTitleGroup(CRect(525, 25, 720, 125), -1, "Quality", kCenterText, 12); view__49->addView(view__68);
view__48->addView(view__68); auto* const view__69 = createValueMenu(CRect(745, 175, 775, 200), kTagSetScalaRootKey, "", kCenterText, 12);
auto* const view__69 = createValueMenu(CRect(15, 60, 95, 85), kTagSetSampleQuality, "", kCenterText, 12); scalaRootOctaveSlider_ = view__69;
sampleQualitySlider_ = view__69; view__49->addView(view__69);
view__68->addView(view__69); auto* const view__70 = createResetSomethingButton(CRect(750, 150, 775, 175), kTagResetScalaFile, "", kCenterText, 12);
auto* const view__70 = createValueLabel(CRect(15, 20, 95, 45), -1, "Sample", kCenterText, 12); scalaResetButton_ = view__70;
view__68->addView(view__70); view__49->addView(view__70);
auto* const view__71 = createValueLabel(CRect(100, 20, 180, 45), -1, "Oscillator", kCenterText, 12); auto* const view__71 = createLabel(CRect(285, 60, 430, 85), -1, "... when freewheeling", kLeftText, 12);
view__68->addView(view__71); view__49->addView(view__71);
auto* const view__72 = createValueMenu(CRect(100, 60, 180, 85), kTagSetOscillatorQuality, "", kCenterText, 12); auto* const view__72 = createValueMenu(CRect(430, 60, 510, 85), kTagSetFreewheelingSampleQuality, "", kCenterText, 12);
oscillatorQualitySlider_ = view__72; freewheelingSampleQualitySlider_ = view__72;
view__68->addView(view__72); view__49->addView(view__72);
auto* const view__73 = createTitleGroup(CRect(35, 160, 140, 260), -1, "Appearance", kCenterText, 12); auto* const view__73 = createLabel(CRect(15, 110, 160, 135), -1, "Sustain cancels release", kLeftText, 12);
view__48->addView(view__73); view__49->addView(view__73);
auto* const view__74 = createOptionMenu(CRect(20, 60, 85, 85), kTagThemeMenu, "", kCenterText, 12); auto* const view__74 = createCheckbox(CRect(195, 110, 220, 135), kTagSetSustainCancelsRelease, "", kCenterText, 14);
themeMenu_ = view__74; sustainCancelsReleaseCheckbox_ = view__74;
view__73->addView(view__74); view__49->addView(view__74);
auto* const view__75 = createValueLabel(CRect(10, 25, 90, 50), -1, "Theme", kCenterText, 12); auto* const view__75 = createLabel(CRect(15, 35, 240, 55), -1, "SFIZZ_VERSION", kCenterText, 10);
view__73->addView(view__75); sfizzVersionLabel_ = view__75;
auto* const view__76 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12); view__49->addView(view__75);
piano_ = view__76; auto* const view__76 = createLabel(CRect(285, 5, 395, 30), -1, "Rendering quality", kLeftText, 12);
view__0->addView(view__76); view__49->addView(view__76);
auto* const view__77 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14); auto* const view__77 = createHLine(CRect(15, 25, 240, 30), -1, "", kCenterText, 14);
subPanels_[kPanelGeneral] = view__77; view__49->addView(view__77);
view__0->addView(view__77); auto* const view__78 = createLabel(CRect(15, 5, 110, 30), -1, "Engine options", kLeftText, 12);
view__77->setVisible(false); 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);

View file

@ -259,6 +259,15 @@ connect_port_stereo(LV2_Handle instance,
case SFIZZ_NUM_SAMPLES: case SFIZZ_NUM_SAMPLES:
self->num_samples_port = (float *)data; self->num_samples_port = (float *)data;
break; 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: default:
break; break;
} }
@ -374,6 +383,15 @@ connect_port_multi(LV2_Handle instance,
case SFIZZ_MULTI_NUM_SAMPLES: case SFIZZ_MULTI_NUM_SAMPLES:
self->num_samples_port = (float *)data; self->num_samples_port = (float *)data;
break; 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: default:
break; 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_tuning_frequency(self->synth, *(self->tuning_frequency_port));
sfizz_set_sample_quality(self->synth, SFIZZ_PROCESS_LIVE, (int)(*self->sample_quality_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_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_stretch_tuning(self);
sfizz_lv2_check_preload_size(self); sfizz_lv2_check_preload_size(self);
sfizz_lv2_check_oversampling(self); sfizz_lv2_check_oversampling(self);

View file

@ -325,7 +325,7 @@ midnam:update a lv2:Feature .
lv2:name "Sample quality", lv2:name "Sample quality",
"Qualité des échantillons"@fr , "Qualité des échantillons"@fr ,
"Qualità del campione"@it ; "Qualità del campione"@it ;
pg:group <@LV2PLUGIN_URI@#tuning> ; pg:group <@LV2PLUGIN_URI@#config> ;
lv2:default 2.0 ; lv2:default 2.0 ;
lv2:minimum 0.0 ; lv2:minimum 0.0 ;
lv2:maximum 10.0 lv2:maximum 10.0
@ -336,7 +336,7 @@ midnam:update a lv2:Feature .
lv2:name "Oscillator quality", lv2:name "Oscillator quality",
"Qualité des oscillateurs"@fr , "Qualité des oscillateurs"@fr ,
"Qualità dell'oscillatore"@it ; "Qualità dell'oscillatore"@it ;
pg:group <@LV2PLUGIN_URI@#tuning> ; pg:group <@LV2PLUGIN_URI@#config> ;
lv2:default 1.0 ; lv2:default 1.0 ;
lv2:minimum 0.0 ; lv2:minimum 0.0 ;
lv2:maximum 3.0 lv2:maximum 3.0
@ -406,6 +406,36 @@ midnam:update a lv2:Feature .
lv2:default 0 ; lv2:default 0 ;
lv2:minimum 0 ; lv2:minimum 0 ;
lv2:maximum 65535 ; 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> . rdfs:seeAlso <controllers.ttl> .
@ -764,7 +794,7 @@ midnam:update a lv2:Feature .
lv2:name "Sample quality", lv2:name "Sample quality",
"Qualité des échantillons"@fr , "Qualité des échantillons"@fr ,
"Qualità del campione"@it ; "Qualità del campione"@it ;
pg:group <@LV2PLUGIN_URI@#tuning> ; pg:group <@LV2PLUGIN_URI@#config> ;
lv2:default 2.0 ; lv2:default 2.0 ;
lv2:minimum 0.0 ; lv2:minimum 0.0 ;
lv2:maximum 10.0 lv2:maximum 10.0
@ -775,7 +805,7 @@ midnam:update a lv2:Feature .
lv2:name "Oscillator quality", lv2:name "Oscillator quality",
"Qualité des oscillateurs"@fr , "Qualité des oscillateurs"@fr ,
"Qualità dell'oscillatore"@it ; "Qualità dell'oscillatore"@it ;
pg:group <@LV2PLUGIN_URI@#tuning> ; pg:group <@LV2PLUGIN_URI@#config> ;
lv2:default 1.0 ; lv2:default 1.0 ;
lv2:minimum 0.0 ; lv2:minimum 0.0 ;
lv2:maximum 3.0 lv2:maximum 3.0
@ -845,6 +875,36 @@ midnam:update a lv2:Feature .
lv2:default 0 ; lv2:default 0 ;
lv2:minimum 0 ; lv2:minimum 0 ;
lv2:maximum 65535 ; 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> . rdfs:seeAlso <controllers.ttl> .

View file

@ -73,6 +73,9 @@ enum
SFIZZ_NUM_GROUPS = 17, SFIZZ_NUM_GROUPS = 17,
SFIZZ_NUM_REGIONS = 18, SFIZZ_NUM_REGIONS = 18,
SFIZZ_NUM_SAMPLES = 19, SFIZZ_NUM_SAMPLES = 19,
SFIZZ_FREEWHEELING_SAMPLE_QUALITY = 20,
SFIZZ_FREEWHEELING_OSCILLATOR_QUALITY = 21,
SFIZZ_SUSTAIN_CANCELS_RELEASE = 22,
}; };
enum enum
@ -111,6 +114,9 @@ enum
SFIZZ_MULTI_NUM_GROUPS = 31, SFIZZ_MULTI_NUM_GROUPS = 31,
SFIZZ_MULTI_NUM_REGIONS = 32, SFIZZ_MULTI_NUM_REGIONS = 32,
SFIZZ_MULTI_NUM_SAMPLES = 33, 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 // For use with instance-access

View file

@ -47,6 +47,9 @@ struct sfizz_plugin_t
const float *stretch_tuning_port {}; const float *stretch_tuning_port {};
const float *sample_quality_port {}; const float *sample_quality_port {};
const float *oscillator_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 *active_voices_port {};
float *num_curves_port {}; float *num_curves_port {};
float *num_masters_port {}; float *num_masters_port {};

View file

@ -354,6 +354,15 @@ port_event_stereo(sfizz_ui_t *self, uint32_t port_index, const void *buffer)
case SFIZZ_NUM_SAMPLES: case SFIZZ_NUM_SAMPLES:
self->uiReceiveValue(EditId::UINumPreloadedSamples, v); self->uiReceiveValue(EditId::UINumPreloadedSamples, v);
break; 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: case SFIZZ_MULTI_NUM_SAMPLES:
self->uiReceiveValue(EditId::UINumPreloadedSamples, v); self->uiReceiveValue(EditId::UINumPreloadedSamples, v);
break; 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) { switch (id) {
case EditId::Volume: 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; break;
case EditId::Polyphony: 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; break;
case EditId::Oversampling: 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; break;
case EditId::PreloadSize: 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; break;
case EditId::ScalaRootKey: 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; break;
case EditId::TuningFrequency: 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; break;
case EditId::StretchTuning: 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; break;
case EditId::SampleQuality: 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; break;
case EditId::OscillatorQuality: 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; break;
case EditId::SfzFile: case EditId::SfzFile:
sendPath(sfizz_sfz_file_uri, v.to_string()); sendPath(sfizz_sfz_file_uri, v.to_string());

View file

@ -80,6 +80,18 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
SfizzRange::getForParameter(kPidOscillatorQuality).createParameter( SfizzRange::getForParameter(kPidOscillatorQuality).createParameter(
Steinberg::String("Oscillator quality"), pid++, nullptr, Steinberg::String("Oscillator quality"), pid++, nullptr,
0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId)); 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 // MIDI special controllers
parameters.addParameter( parameters.addParameter(
@ -267,6 +279,9 @@ tresult PLUGIN_API SfizzVstControllerNoUi::setComponentState(IBStream* stream)
setParam(kPidStretchedTuning, s.stretchedTuning); setParam(kPidStretchedTuning, s.stretchedTuning);
setParam(kPidSampleQuality, s.sampleQuality); setParam(kPidSampleQuality, s.sampleQuality);
setParam(kPidOscillatorQuality, s.oscillatorQuality); 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))); uint32 ccLimit = uint32(std::min(s.controllers.size(), size_t(sfz::config::numCCs)));
for (uint32 cc = 0; cc < ccLimit; ++cc) { for (uint32 cc = 0; cc < ccLimit; ++cc) {

View file

@ -343,6 +343,15 @@ void SfizzVstEditor::updateParameter(Vst::Parameter* parameterToUpdate)
case kPidOscillatorQuality: case kPidOscillatorQuality:
uiReceiveValue(EditId::OscillatorQuality, range.denormalize(value)); uiReceiveValue(EditId::OscillatorQuality, range.denormalize(value));
break; 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: case kPidNumOutputs:
uiReceiveValue(EditId::PluginOutputs, (int32)range.denormalize(value)); uiReceiveValue(EditId::PluginOutputs, (int32)range.denormalize(value));
break; break;
@ -406,7 +415,15 @@ void SfizzVstEditor::uiSendValue(EditId id, const EditValue& v)
case EditId::OscillatorQuality: case EditId::OscillatorQuality:
normalizeAndSet(kPidOscillatorQuality, v.to_float()); normalizeAndSet(kPidOscillatorQuality, v.to_float());
break; 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: case EditId::UserFilesDir:
SfizzPaths::setSfzConfigDefaultPath(fs::u8path(v.to_string())); SfizzPaths::setSfzConfigDefaultPath(fs::u8path(v.to_string()));
break; break;

View file

@ -22,6 +22,9 @@ enum {
kPidStretchedTuning, kPidStretchedTuning,
kPidSampleQuality, kPidSampleQuality,
kPidOscillatorQuality, kPidOscillatorQuality,
kPidFreewheelingSampleQuality,
kPidFreewheelingOscillatorQuality,
kPidSustainCancelsRelease,
kPidAftertouch, kPidAftertouch,
kPidPitchBend, kPidPitchBend,
kPidCC0, kPidCC0,
@ -78,6 +81,12 @@ struct SfizzRange {
return {2.0, 0.0, 10.0}; return {2.0, 0.0, 10.0};
case kPidOscillatorQuality: case kPidOscillatorQuality:
return {1.0, 0.0, 3.0}; 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: case kPidAftertouch:
return {0.0, 0.0, 1.0}; return {0.0, 0.0, 1.0};
case kPidPitchBend: case kPidPitchBend:

View file

@ -334,6 +334,9 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data)
} }
synth.setSampleQuality(sfz::Sfizz::ProcessLive, _state.sampleQuality); synth.setSampleQuality(sfz::Sfizz::ProcessLive, _state.sampleQuality);
synth.setOscillatorQuality(sfz::Sfizz::ProcessLive, _state.oscillatorQuality); 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); synth.renderBlock(outputs, numFrames, data.numOutputs);
@ -450,6 +453,15 @@ void SfizzVstProcessor::playOrderedParameter(int32 sampleOffset, Vst::ParamID id
case kPidOscillatorQuality: case kPidOscillatorQuality:
_state.oscillatorQuality = static_cast<int32>(range.denormalize(value)); _state.oscillatorQuality = static_cast<int32>(range.denormalize(value));
break; 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: case kPidAftertouch:
synth.hdChannelAftertouch(sampleOffset, value); synth.hdChannelAftertouch(sampleOffset, value);
break; break;

View file

@ -73,6 +73,17 @@ tresult SfizzVstState::load(IBStream* state)
oscillatorQuality = defaults.oscillatorQuality; 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 (version >= 4) {
if (!s.readInt32(lastKeyswitch)) if (!s.readInt32(lastKeyswitch))
return kResultFalse; return kResultFalse;
@ -143,6 +154,15 @@ tresult SfizzVstState::store(IBStream* state) const
if (!s.writeInt32(oscillatorQuality)) if (!s.writeInt32(oscillatorQuality))
return kResultFalse; return kResultFalse;
if (!s.writeInt32(freewheelingSampleQuality))
return kResultFalse;
if (!s.writeInt32(freewheelingOscillatorQuality))
return kResultFalse;
if (!s.writeBool(sustainCancelsRelease))
return kResultFalse;
if (!s.writeInt32(lastKeyswitch)) if (!s.writeInt32(lastKeyswitch))
return kResultFalse; return kResultFalse;

View file

@ -27,10 +27,13 @@ public:
float stretchedTuning = 0.0; float stretchedTuning = 0.0;
int32 sampleQuality = 2; int32 sampleQuality = 2;
int32 oscillatorQuality = 1; int32 oscillatorQuality = 1;
int32 freewheelingSampleQuality = 10;
int32 freewheelingOscillatorQuality = 3;
bool sustainCancelsRelease = false;
int32 lastKeyswitch = -1; int32 lastKeyswitch = -1;
std::vector<absl::optional<float>> controllers; std::vector<absl::optional<float>> controllers;
static constexpr uint64 currentStateVersion = 4; static constexpr uint64 currentStateVersion = 5;
tresult load(IBStream* state); tresult load(IBStream* state);
tresult store(IBStream* state) const; tresult store(IBStream* state) const;

View file

@ -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); 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. * @brief Set the global instrument volume.
* @since 0.2.0 * @since 0.2.0

View file

@ -360,6 +360,13 @@ public:
*/ */
void setOscillatorQuality(ProcessMode mode, int quality); 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. * @brief Return the current value for the volume, in dB.
* @since 0.2.0 * @since 0.2.0

View file

@ -40,7 +40,6 @@ FloatSpec oscillatorDetune { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds };
FloatSpec oscillatorDetuneMod { 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 oscillatorModDepth { 0.0f, {0.0f, 10000.0f}, kNormalizePercent|kPermissiveBounds };
FloatSpec oscillatorModDepthMod { 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 }; Int64Spec group { 0, {-int32_t_max, uint32_t_max}, 0 };
UInt16Spec output { 0, {0, config::maxChannels / 2 - 1}, kEnforceBounds }; UInt16Spec output { 0, {0, config::maxChannels / 2 - 1}, kEnforceBounds };
FloatSpec offTime { 6e-3f, {0.0f, 100.0f}, kPermissiveBounds }; 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 flexEGPointLevelMod { 0.0f, {-1.0f, 1.0f}, kPermissiveBounds };
FloatSpec flexEGPointShape { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds }; FloatSpec flexEGPointShape { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds };
Int32Spec sampleQuality { 2, {0, 10}, 0 }; 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 octaveOffset { 0, {-10, 10}, kPermissiveBounds };
Int32Spec noteOffset { 0, {-127, 127}, kPermissiveBounds }; Int32Spec noteOffset { 0, {-127, 127}, kPermissiveBounds };

View file

@ -274,6 +274,8 @@ namespace Default
extern const OpcodeSpec<float> flexEGPointLevelMod; extern const OpcodeSpec<float> flexEGPointLevelMod;
extern const OpcodeSpec<float> flexEGPointShape; extern const OpcodeSpec<float> flexEGPointShape;
extern const OpcodeSpec<int32_t> sampleQuality; 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> octaveOffset;
extern const OpcodeSpec<int32_t> noteOffset; extern const OpcodeSpec<int32_t> noteOffset;
extern const OpcodeSpec<float> effect; extern const OpcodeSpec<float> effect;
@ -335,8 +337,6 @@ namespace Default
// Various defaut values // Various defaut values
// e.g. "additional" or multiple defautl values // e.g. "additional" or multiple defautl values
constexpr int freewheelingSampleQuality { 10 };
constexpr int freewheelingOscillatorQuality { 3 };
constexpr float globalVolume { -7.35f }; constexpr float globalVolume { -7.35f };
constexpr float defaultEQFreq [numEQs] { 50.0f, 500.0f, 5000.0f }; constexpr float defaultEQFreq [numEQs] { 50.0f, 500.0f, 5000.0f };
} // namespace Default } // namespace Default

View file

@ -1810,6 +1810,7 @@ void Synth::setSampleQuality(ProcessMode mode, int quality)
synthConfig.liveSampleQuality = quality; synthConfig.liveSampleQuality = quality;
break; break;
case ProcessFreewheeling: case ProcessFreewheeling:
// DBG("Set freewheeling quality" << quality);
synthConfig.freeWheelingSampleQuality = quality; synthConfig.freeWheelingSampleQuality = quality;
break; break;
default: default:
@ -1845,6 +1846,7 @@ void Synth::setOscillatorQuality(ProcessMode mode, int quality)
synthConfig.liveOscillatorQuality = quality; synthConfig.liveOscillatorQuality = quality;
break; break;
case ProcessFreewheeling: case ProcessFreewheeling:
// DBG("Set freewheeling oscillator quality" << quality);
synthConfig.freeWheelingOscillatorQuality = quality; synthConfig.freeWheelingOscillatorQuality = quality;
break; break;
default: 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 float Synth::getVolume() const noexcept
{ {
Impl& impl = *impl_; Impl& impl = *impl_;

View file

@ -334,6 +334,12 @@ public:
* @param quality the quality setting * @param quality the quality setting
*/ */
void setOscillatorQuality(ProcessMode mode, int quality); 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. * @brief Get the current value for the volume, in dB.
* *

View file

@ -8,6 +8,7 @@
#include "FilePool.h" #include "FilePool.h"
#include "Curve.h" #include "Curve.h"
#include "MidiState.h" #include "MidiState.h"
#include "SynthConfig.h"
#include "utility/StringViewHelpers.h" #include "utility/StringViewHelpers.h"
#include <absl/strings/ascii.h> #include <absl/strings/ascii.h>
#include <cstring> #include <cstring>
@ -1534,6 +1535,34 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
// Setting values // Setting values
// Note: all these must be rt-safe within the parseOpcode method in region // 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) \ #define GET_REGION_OR_BREAK(idx) \
if (idx >= impl.layers_.size()) \ if (idx >= impl.layers_.size()) \
break; \ break; \

View file

@ -150,6 +150,11 @@ void sfz::Sfizz::setOscillatorQuality(ProcessMode mode, int quality)
synth->synth.setOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode), 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 float sfz::Sfizz::getVolume() const noexcept
{ {
return synth->synth.getVolume(); return synth->synth.getVolume();

View file

@ -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); 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) void sfizz_set_volume(sfizz_synth_t* synth, float volume)
{ {
synth->synth.setVolume(volume); synth->synth.setVolume(volume);