Add new config options and bind them to the UI

This commit is contained in:
Paul Fd 2021-11-12 11:40:48 +01:00
parent 3a882b98d7
commit aab807a7b5
25 changed files with 496 additions and 114 deletions

View file

@ -245,22 +245,22 @@ widget_class mainView {open
} { } {
Fl_Spinner oversamplingSlider_ { Fl_Spinner oversamplingSlider_ {
comment {tag=kTagSetOversampling} comment {tag=kTagSetOversampling}
xywh {175 185 70 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 {20 185 85 25} labelsize 12 align 20 xywh {20 195 85 25} labelsize 12 align 20
class Label class Label
} }
Fl_Box {} { Fl_Box {} {
label {Preload size} label {Preload size}
xywh {20 160 75 25} labelsize 12 align 20 xywh {20 170 75 25} labelsize 12 align 20
class Label class Label
} }
Fl_Spinner preloadSizeSlider_ { Fl_Spinner preloadSizeSlider_ {
comment {tag=kTagSetPreloadSize} comment {tag=kTagSetPreloadSize}
xywh {175 160 70 25} labelsize 12 textsize 12 xywh {175 170 70 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Spinner sampleQualitySlider_ { Fl_Spinner sampleQualitySlider_ {
@ -275,12 +275,12 @@ widget_class mainView {open
} }
Fl_Box {} { Fl_Box {} {
label Oscillator label Oscillator
xywh {290 170 60 25} labelsize 12 align 20 xywh {290 195 60 25} labelsize 12 align 20
class Label class Label
} }
Fl_Spinner oscillatorQualitySlider_ { Fl_Spinner oscillatorQualitySlider_ {
comment {tag=kTagSetOscillatorQuality} comment {tag=kTagSetOscillatorQuality}
xywh {435 170 80 25} labelsize 12 textsize 12 xywh {435 195 80 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Spinner themeMenu_ { Fl_Spinner themeMenu_ {
@ -306,72 +306,73 @@ widget_class mainView {open
} }
Fl_Box {} { Fl_Box {} {
label {Root key} label {Root key}
xywh {290 285 60 25} labelsize 12 align 20 xywh {555 285 60 25} labelsize 12 align 20
class Label class Label
} }
Fl_Box {} { Fl_Box {} {
label Frequency label Frequency
xywh {290 310 70 25} labelsize 12 align 20 xywh {555 310 70 25} labelsize 12 align 20
class Label class Label
} }
Fl_Dial stretchedTuningSlider_ { Fl_Dial stretchedTuningSlider_ {
comment {tag=kTagSetStretchedTuning} comment {tag=kTagSetStretchedTuning}
xywh {455 337 48 48} value 0.5 xywh {720 337 48 48} value 0.5
class StyledKnob class StyledKnob
} }
Fl_Box {} { Fl_Box {} {
label Stretch label Stretch
xywh {290 345 50 25} labelsize 12 align 20 xywh {555 345 50 25} labelsize 12 align 20
class Label class Label
} }
Fl_Box {} { Fl_Box {} {
label {Scala file} label {Scala file}
xywh {290 260 60 25} labelsize 12 align 20 xywh {555 260 60 25} labelsize 12 align 20
class Label class Label
} }
Fl_Button scalaFileButton_ { Fl_Button scalaFileButton_ {
label DefaultScale label DefaultScale
comment {tag=kTagLoadScalaFile} comment {tag=kTagLoadScalaFile}
xywh {390 260 100 25} labelsize 12 xywh {655 260 100 25} labelsize 12
class ValueButton class ValueButton
} }
Fl_Spinner scalaRootKeySlider_ { Fl_Spinner scalaRootKeySlider_ {
comment {tag=kTagSetScalaRootKey} comment {tag=kTagSetScalaRootKey}
xywh {450 285 35 25} labelsize 12 textsize 12 xywh {715 285 35 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Spinner scalaRootOctaveSlider_ { Fl_Spinner scalaRootOctaveSlider_ {
comment {tag=kTagSetScalaRootKey} comment {tag=kTagSetScalaRootKey}
xywh {485 285 30 25} labelsize 12 textsize 12 xywh {750 285 30 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Button scalaResetButton_ { Fl_Button scalaResetButton_ {
comment {tag=kTagResetScalaFile} comment {tag=kTagResetScalaFile}
xywh {490 260 25 25} labelsize 12 xywh {755 260 25 25} labelsize 12
class ResetSomethingButton class ResetSomethingButton
} }
Fl_Box {} { Fl_Box {} {
label Freewheeling label {... when freewheeling}
xywh {290 195 85 25} labelsize 12 align 20 xywh {290 170 145 25} labelsize 12 align 20
class Label class Label
} }
Fl_Spinner freewheelingQualitySlider_ { Fl_Spinner freewheelingSampleQualitySlider_ {
comment {tag=kTagSetOscillatorQuality} comment {tag=kTagSetFreewheelingSampleQuality}
xywh {435 195 80 25} labelsize 12 textsize 12 xywh {435 170 80 25} labelsize 12 textsize 12
class ValueMenu class ValueMenu
} }
Fl_Box {} { Fl_Box {} {
label {Release cancels sustain} label {Sustain cancels release}
xywh {20 210 145 25} labelsize 12 align 20 xywh {20 220 145 25} labelsize 12 align 20
class Label class Label
} }
Fl_Check_Button {} { Fl_Check_Button sustainCancelsReleaseCheckbox_ {
xywh {205 210 25 25} down_box DOWN_BOX comment {tag=kTagSetSustainCancelsRelease} selected
xywh {200 220 25 25} down_box DOWN_BOX
class Checkbox class Checkbox
} }
Fl_Box sfizzVersionLabel_ { Fl_Box sfizzVersionLabel_ {
label SFIZZ_VERSION label SFIZZ_VERSION
xywh {20 140 225 20} labelsize 10 xywh {20 145 225 20} labelsize 10
class Label class Label
} }
Fl_Box {} { Fl_Box {} {
@ -401,7 +402,7 @@ widget_class mainView {open
} }
Fl_Box {} { Fl_Box {} {
label Tuning label Tuning
xywh {290 230 225 25} labelsize 12 align 20 xywh {555 230 225 25} labelsize 12 align 20
class Label class Label
} }
Fl_Box {} { Fl_Box {} {
@ -416,25 +417,35 @@ widget_class mainView {open
} }
Fl_Box {} { Fl_Box {} {
label {Separator 2} label {Separator 2}
xywh {290 250 225 5} box BORDER_BOX labeltype NO_LABEL xywh {555 250 225 5} box BORDER_BOX labeltype NO_LABEL
class HLine class HLine
} }
Fl_Button tuningFrequencyDropdown_ { Fl_Button tuningFrequencyDropdown_ {
comment {tag=kTagSetTuningFrequency} comment {tag=kTagSetTuningFrequency}
xywh {490 310 25 25} labelsize 24 xywh {755 310 25 25} labelsize 24
class ChevronValueDropDown class ChevronValueDropDown
} }
Fl_Text_Editor tuningFrequencyEdit_ { Fl_Text_Editor tuningFrequencyEdit_ {
comment {tag=kTagSetTuningFrequency} comment {tag=kTagSetTuningFrequency}
xywh {430 310 60 25} labelsize 12 xywh {695 310 60 25} labelsize 12
class TextEdit class TextEdit
} }
Fl_Button settingsAboutButton_ { Fl_Button settingsAboutButton_ {
label {About sfizz} label {About sfizz}
comment {tag=kTagAbout} selected comment {tag=kTagAbout}
xywh {610 205 115 25} labelsize 12 xywh {610 205 115 25} labelsize 12
class ValueButton 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
}
} }
} }
Fl_Box piano_ { Fl_Box piano_ {

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

@ -98,8 +98,9 @@ struct Editor::Impl : EditorController::Receiver,
kTagSetStretchedTuning, kTagSetStretchedTuning,
kTagSetSampleQuality, kTagSetSampleQuality,
kTagSetOscillatorQuality, kTagSetOscillatorQuality,
kTagSetFreewheelingQuality, kTagSetFreewheelingSampleQuality,
kTagSetReleaseCancelsSustain, kTagSetFreewheelingOscillatorQuality,
kTagSetSustainCancelsRelease,
kTagSetCCVolume, kTagSetCCVolume,
kTagSetCCPan, kTagSetCCPan,
kTagChooseUserFilesDir, kTagChooseUserFilesDir,
@ -132,7 +133,9 @@ struct Editor::Impl : EditorController::Receiver,
CTextLabel* stretchedTuningLabel_ = nullptr; CTextLabel* stretchedTuningLabel_ = nullptr;
SValueMenu *sampleQualitySlider_ = nullptr; SValueMenu *sampleQualitySlider_ = nullptr;
SValueMenu *oscillatorQualitySlider_ = nullptr; SValueMenu *oscillatorQualitySlider_ = nullptr;
SValueMenu *freewheelingQualitySlider_ = 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;
@ -448,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_)
@ -1095,6 +1125,9 @@ void Editor::Impl::createFrameContents()
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);
@ -1186,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) {
@ -2002,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

@ -133,14 +133,14 @@ subPanels_[kPanelSettings] = view__48;
view__0->addView(view__48); view__0->addView(view__48);
auto* const view__49 = createRoundedGroup(CRect(5, 0, 795, 285), -1, "", kCenterText, 14); 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(170, 75, 240, 100), 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 = createLabel(CRect(15, 75, 100, 100), -1, "Oversampling", kLeftText, 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 = createLabel(CRect(15, 50, 90, 75), -1, "Preload size", kLeftText, 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(170, 50, 240, 75), 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 = createValueMenu(CRect(430, 35, 510, 60), kTagSetSampleQuality, "", kCenterText, 12); auto* const view__54 = createValueMenu(CRect(430, 35, 510, 60), kTagSetSampleQuality, "", kCenterText, 12);
@ -148,9 +148,9 @@ sampleQualitySlider_ = view__54;
view__49->addView(view__54); view__49->addView(view__54);
auto* const view__55 = createLabel(CRect(285, 35, 335, 60), -1, "Sample", kLeftText, 12); auto* const view__55 = createLabel(CRect(285, 35, 335, 60), -1, "Sample", kLeftText, 12);
view__49->addView(view__55); view__49->addView(view__55);
auto* const view__56 = createLabel(CRect(285, 60, 345, 85), -1, "Oscillator", kLeftText, 12); auto* const view__56 = createLabel(CRect(285, 85, 345, 110), -1, "Oscillator", kLeftText, 12);
view__49->addView(view__56); view__49->addView(view__56);
auto* const view__57 = createValueMenu(CRect(430, 60, 510, 85), kTagSetOscillatorQuality, "", kCenterText, 12); auto* const view__57 = createValueMenu(CRect(430, 85, 510, 110), kTagSetOscillatorQuality, "", kCenterText, 12);
oscillatorQualitySlider_ = view__57; oscillatorQualitySlider_ = view__57;
view__49->addView(view__57); view__49->addView(view__57);
auto* const view__58 = createOptionMenu(CRect(675, 35, 775, 60), kTagThemeMenu, "", kCenterText, 12); auto* const view__58 = createOptionMenu(CRect(675, 35, 775, 60), kTagThemeMenu, "", kCenterText, 12);
@ -163,39 +163,40 @@ view__49->addView(view__60);
auto* const view__61 = createValueButton(CRect(675, 60, 775, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12); auto* const view__61 = createValueButton(CRect(675, 60, 775, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12);
userFilesDirButton_ = view__61; userFilesDirButton_ = view__61;
view__49->addView(view__61); view__49->addView(view__61);
auto* const view__62 = createLabel(CRect(285, 175, 345, 200), -1, "Root key", kLeftText, 12); auto* const view__62 = createLabel(CRect(550, 175, 610, 200), -1, "Root key", kLeftText, 12);
view__49->addView(view__62); view__49->addView(view__62);
auto* const view__63 = createLabel(CRect(285, 200, 355, 225), -1, "Frequency", kLeftText, 12); auto* const view__63 = createLabel(CRect(550, 200, 620, 225), -1, "Frequency", kLeftText, 12);
view__49->addView(view__63); view__49->addView(view__63);
auto* const view__64 = createStyledKnob(CRect(450, 227, 498, 275), kTagSetStretchedTuning, "", kCenterText, 14); auto* const view__64 = createStyledKnob(CRect(715, 227, 763, 275), kTagSetStretchedTuning, "", kCenterText, 14);
stretchedTuningSlider_ = view__64; stretchedTuningSlider_ = view__64;
view__49->addView(view__64); view__49->addView(view__64);
auto* const view__65 = createLabel(CRect(285, 235, 335, 260), -1, "Stretch", kLeftText, 12); auto* const view__65 = createLabel(CRect(550, 235, 600, 260), -1, "Stretch", kLeftText, 12);
view__49->addView(view__65); view__49->addView(view__65);
auto* const view__66 = createLabel(CRect(285, 150, 345, 175), -1, "Scala file", kLeftText, 12); auto* const view__66 = createLabel(CRect(550, 150, 610, 175), -1, "Scala file", kLeftText, 12);
view__49->addView(view__66); view__49->addView(view__66);
auto* const view__67 = createValueButton(CRect(385, 150, 485, 175), kTagLoadScalaFile, "DefaultScale", kCenterText, 12); auto* const view__67 = createValueButton(CRect(650, 150, 750, 175), kTagLoadScalaFile, "DefaultScale", kCenterText, 12);
scalaFileButton_ = view__67; scalaFileButton_ = view__67;
view__49->addView(view__67); view__49->addView(view__67);
auto* const view__68 = createValueMenu(CRect(445, 175, 480, 200), kTagSetScalaRootKey, "", kCenterText, 12); auto* const view__68 = createValueMenu(CRect(710, 175, 745, 200), kTagSetScalaRootKey, "", kCenterText, 12);
scalaRootKeySlider_ = view__68; scalaRootKeySlider_ = view__68;
view__49->addView(view__68); view__49->addView(view__68);
auto* const view__69 = createValueMenu(CRect(480, 175, 510, 200), kTagSetScalaRootKey, "", kCenterText, 12); auto* const view__69 = createValueMenu(CRect(745, 175, 775, 200), kTagSetScalaRootKey, "", kCenterText, 12);
scalaRootOctaveSlider_ = view__69; scalaRootOctaveSlider_ = view__69;
view__49->addView(view__69); view__49->addView(view__69);
auto* const view__70 = createResetSomethingButton(CRect(485, 150, 510, 175), kTagResetScalaFile, "", kCenterText, 12); auto* const view__70 = createResetSomethingButton(CRect(750, 150, 775, 175), kTagResetScalaFile, "", kCenterText, 12);
scalaResetButton_ = view__70; scalaResetButton_ = view__70;
view__49->addView(view__70); view__49->addView(view__70);
auto* const view__71 = createLabel(CRect(285, 85, 370, 110), -1, "Freewheeling", kLeftText, 12); auto* const view__71 = createLabel(CRect(285, 60, 430, 85), -1, "... when freewheeling", kLeftText, 12);
view__49->addView(view__71); view__49->addView(view__71);
auto* const view__72 = createValueMenu(CRect(430, 85, 510, 110), kTagSetOscillatorQuality, "", kCenterText, 12); auto* const view__72 = createValueMenu(CRect(430, 60, 510, 85), kTagSetFreewheelingSampleQuality, "", kCenterText, 12);
freewheelingQualitySlider_ = view__72; freewheelingSampleQualitySlider_ = view__72;
view__49->addView(view__72); view__49->addView(view__72);
auto* const view__73 = createLabel(CRect(15, 100, 160, 125), -1, "Release cancels sustain", kLeftText, 12); auto* const view__73 = createLabel(CRect(15, 110, 160, 135), -1, "Sustain cancels release", kLeftText, 12);
view__49->addView(view__73); view__49->addView(view__73);
auto* const view__74 = createCheckbox(CRect(200, 100, 225, 125), -1, "", kCenterText, 14); auto* const view__74 = createCheckbox(CRect(195, 110, 220, 135), kTagSetSustainCancelsRelease, "", kCenterText, 14);
sustainCancelsReleaseCheckbox_ = view__74;
view__49->addView(view__74); view__49->addView(view__74);
auto* const view__75 = createLabel(CRect(15, 30, 240, 50), -1, "SFIZZ_VERSION", kCenterText, 10); auto* const view__75 = createLabel(CRect(15, 35, 240, 55), -1, "SFIZZ_VERSION", kCenterText, 10);
sfizzVersionLabel_ = view__75; sfizzVersionLabel_ = view__75;
view__49->addView(view__75); view__49->addView(view__75);
auto* const view__76 = createLabel(CRect(285, 5, 395, 30), -1, "Rendering quality", kLeftText, 12); auto* const view__76 = createLabel(CRect(285, 5, 395, 30), -1, "Rendering quality", kLeftText, 12);
@ -208,27 +209,32 @@ auto* const view__79 = createHLine(CRect(575, 25, 760, 30), -1, "", kCenterText,
view__49->addView(view__79); view__49->addView(view__79);
auto* const view__80 = createLabel(CRect(550, 5, 590, 30), -1, "Other", kLeftText, 12); auto* const view__80 = createLabel(CRect(550, 5, 590, 30), -1, "Other", kLeftText, 12);
view__49->addView(view__80); view__49->addView(view__80);
auto* const view__81 = createLabel(CRect(285, 120, 510, 145), -1, "Tuning", kLeftText, 12); auto* const view__81 = createLabel(CRect(550, 120, 775, 145), -1, "Tuning", kLeftText, 12);
view__49->addView(view__81); view__49->addView(view__81);
auto* const view__82 = createHLine(CRect(285, 25, 510, 30), -1, "", kCenterText, 14); auto* const view__82 = createHLine(CRect(285, 25, 510, 30), -1, "", kCenterText, 14);
view__49->addView(view__82); view__49->addView(view__82);
auto* const view__83 = createHLine(CRect(550, 25, 775, 30), -1, "", kCenterText, 14); auto* const view__83 = createHLine(CRect(550, 25, 775, 30), -1, "", kCenterText, 14);
view__49->addView(view__83); view__49->addView(view__83);
auto* const view__84 = createHLine(CRect(285, 140, 510, 145), -1, "", kCenterText, 14); auto* const view__84 = createHLine(CRect(550, 140, 775, 145), -1, "", kCenterText, 14);
view__49->addView(view__84); view__49->addView(view__84);
auto* const view__85 = createChevronValueDropDown(CRect(485, 200, 510, 225), kTagSetTuningFrequency, "", kCenterText, 24); auto* const view__85 = createChevronValueDropDown(CRect(750, 200, 775, 225), kTagSetTuningFrequency, "", kCenterText, 24);
tuningFrequencyDropdown_ = view__85; tuningFrequencyDropdown_ = view__85;
view__49->addView(view__85); view__49->addView(view__85);
auto* const view__86 = createTextEdit(CRect(425, 200, 485, 225), kTagSetTuningFrequency, "", kCenterText, 12); auto* const view__86 = createTextEdit(CRect(690, 200, 750, 225), kTagSetTuningFrequency, "", kCenterText, 12);
tuningFrequencyEdit_ = view__86; tuningFrequencyEdit_ = view__86;
view__49->addView(view__86); view__49->addView(view__86);
auto* const view__87 = createValueButton(CRect(605, 95, 720, 120), kTagAbout, "About sfizz", kCenterText, 12); auto* const view__87 = createValueButton(CRect(605, 95, 720, 120), kTagAbout, "About sfizz", kCenterText, 12);
settingsAboutButton_ = view__87; settingsAboutButton_ = view__87;
view__49->addView(view__87); view__49->addView(view__87);
auto* const view__88 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12); auto* const view__88 = createLabel(CRect(285, 110, 430, 135), -1, "... when freewheeling", kLeftText, 12);
piano_ = view__88; view__49->addView(view__88);
view__0->addView(view__88); auto* const view__89 = createValueMenu(CRect(430, 110, 510, 135), kTagSetFreewheelingOscillatorQuality, "", kCenterText, 12);
auto* const view__89 = createLogicalGroup(CRect(5, 110, 795, 395), -1, "", kCenterText, 14); freewheelingOscillatorQualitySlider_ = view__89;
subPanels_[kPanelGeneral] = view__89; view__49->addView(view__89);
view__0->addView(view__89); auto* const view__90 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
view__89->setVisible(false); 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);