Merge pull request #813 from jpcima/sample-quality-setting
Sample quality controls in UI
This commit is contained in:
commit
a49cf37930
27 changed files with 422 additions and 31 deletions
|
|
@ -3,7 +3,7 @@ version 1.0305
|
||||||
header_name {.h}
|
header_name {.h}
|
||||||
code_name {.cxx}
|
code_name {.cxx}
|
||||||
widget_class mainView {open
|
widget_class mainView {open
|
||||||
xywh {353 221 800 475} type Double
|
xywh {439 94 800 475} type Double
|
||||||
class LogicalGroup visible
|
class LogicalGroup visible
|
||||||
} {
|
} {
|
||||||
Fl_Box imageContainer_ {
|
Fl_Box imageContainer_ {
|
||||||
|
|
@ -20,7 +20,7 @@ widget_class mainView {open
|
||||||
class RoundedGroup
|
class RoundedGroup
|
||||||
} {
|
} {
|
||||||
Fl_Box {} {
|
Fl_Box {} {
|
||||||
comment {tag=kTagAbout} selected
|
comment {tag=kTagAbout}
|
||||||
image {../resources/logo_text_shaded.png} xywh {35 9 120 60}
|
image {../resources/logo_text_shaded.png} xywh {35 9 120 60}
|
||||||
class AboutButton
|
class AboutButton
|
||||||
}
|
}
|
||||||
|
|
@ -330,6 +330,32 @@ widget_class mainView {open
|
||||||
class ValueButton
|
class ValueButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Fl_Group {} {
|
||||||
|
label Quality open
|
||||||
|
xywh {530 135 195 100} box ROUNDED_BOX labelsize 12 align 17
|
||||||
|
class TitleGroup
|
||||||
|
} {
|
||||||
|
Fl_Spinner sampleQualitySlider_ {
|
||||||
|
comment {tag=kTagSetSampleQuality}
|
||||||
|
xywh {545 195 80 25} labelsize 12 textsize 12
|
||||||
|
class ValueMenu
|
||||||
|
}
|
||||||
|
Fl_Box {} {
|
||||||
|
label Sample
|
||||||
|
xywh {545 155 80 25} labelsize 12
|
||||||
|
class ValueLabel
|
||||||
|
}
|
||||||
|
Fl_Box {} {
|
||||||
|
label Oscillator
|
||||||
|
xywh {630 155 80 25} labelsize 12
|
||||||
|
class ValueLabel
|
||||||
|
}
|
||||||
|
Fl_Spinner oscillatorQualitySlider_ {
|
||||||
|
comment {tag=kTagSetOscillatorQuality} selected
|
||||||
|
xywh {630 195 80 25} labelsize 12 textsize 12
|
||||||
|
class ValueMenu
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Fl_Box piano_ {
|
Fl_Box piano_ {
|
||||||
xywh {5 400 790 70} labelsize 12
|
xywh {5 400 790 70} labelsize 12
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,10 @@ EditRange EditRange::get(EditId id)
|
||||||
return { 440, 300, 500 };
|
return { 440, 300, 500 };
|
||||||
case EditId::StretchTuning:
|
case EditId::StretchTuning:
|
||||||
return { 0, 0, 1 };
|
return { 0, 0, 1 };
|
||||||
|
case EditId::SampleQuality:
|
||||||
|
return { 1, 0, 10 };
|
||||||
|
case EditId::OscillatorQuality:
|
||||||
|
return { 1, 0, 3 };
|
||||||
case EditId::UIActivePanel:
|
case EditId::UIActivePanel:
|
||||||
return { 0, 0, 255 };
|
return { 0, 0, 255 };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ enum class EditId : int {
|
||||||
ScalaRootKey,
|
ScalaRootKey,
|
||||||
TuningFrequency,
|
TuningFrequency,
|
||||||
StretchTuning,
|
StretchTuning,
|
||||||
|
SampleQuality,
|
||||||
|
OscillatorQuality,
|
||||||
CanEditUserFilesDir,
|
CanEditUserFilesDir,
|
||||||
UserFilesDir,
|
UserFilesDir,
|
||||||
FallbackFilesDir,
|
FallbackFilesDir,
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,8 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
kTagSetScalaRootKey,
|
kTagSetScalaRootKey,
|
||||||
kTagSetTuningFrequency,
|
kTagSetTuningFrequency,
|
||||||
kTagSetStretchedTuning,
|
kTagSetStretchedTuning,
|
||||||
|
kTagSetSampleQuality,
|
||||||
|
kTagSetOscillatorQuality,
|
||||||
kTagSetCCVolume,
|
kTagSetCCVolume,
|
||||||
kTagSetCCPan,
|
kTagSetCCPan,
|
||||||
kTagChooseUserFilesDir,
|
kTagChooseUserFilesDir,
|
||||||
|
|
@ -112,6 +114,8 @@ struct Editor::Impl : EditorController::Receiver, IControlListener {
|
||||||
CTextLabel* tuningFrequencyLabel_ = nullptr;
|
CTextLabel* tuningFrequencyLabel_ = nullptr;
|
||||||
CControl *stretchedTuningSlider_ = nullptr;
|
CControl *stretchedTuningSlider_ = nullptr;
|
||||||
CTextLabel* stretchedTuningLabel_ = nullptr;
|
CTextLabel* stretchedTuningLabel_ = nullptr;
|
||||||
|
SValueMenu *sampleQualitySlider_ = nullptr;
|
||||||
|
SValueMenu *oscillatorQualitySlider_ = nullptr;
|
||||||
CTextLabel* keyswitchLabel_ = nullptr;
|
CTextLabel* keyswitchLabel_ = nullptr;
|
||||||
CTextLabel* keyswitchInactiveLabel_ = nullptr;
|
CTextLabel* keyswitchInactiveLabel_ = nullptr;
|
||||||
CTextLabel* keyswitchBadge_ = nullptr;
|
CTextLabel* keyswitchBadge_ = nullptr;
|
||||||
|
|
@ -390,6 +394,24 @@ void Editor::Impl::uiReceiveValue(EditId id, const EditValue& v)
|
||||||
updateStretchedTuningLabel(value);
|
updateStretchedTuningLabel(value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EditId::SampleQuality:
|
||||||
|
{
|
||||||
|
const int value = static_cast<int>(v.to_float());
|
||||||
|
if (CControl* slider = sampleQualitySlider_) {
|
||||||
|
slider->setValue(float(value));
|
||||||
|
slider->invalid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EditId::OscillatorQuality:
|
||||||
|
{
|
||||||
|
const int value = static_cast<int>(v.to_float());
|
||||||
|
if (CControl* slider = oscillatorQualitySlider_) {
|
||||||
|
slider->setValue(float(value));
|
||||||
|
slider->invalid();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case EditId::CanEditUserFilesDir:
|
case EditId::CanEditUserFilesDir:
|
||||||
{
|
{
|
||||||
if (STitleContainer* group = userFilesGroup_)
|
if (STitleContainer* group = userFilesGroup_)
|
||||||
|
|
@ -920,6 +942,8 @@ void Editor::Impl::createFrameContents()
|
||||||
adjustMinMaxToEditRange(tuningFrequencySlider_, EditId::TuningFrequency);
|
adjustMinMaxToEditRange(tuningFrequencySlider_, EditId::TuningFrequency);
|
||||||
tuningFrequencySlider_->setWheelInc(0.1f / EditRange::get(EditId::TuningFrequency).extent());
|
tuningFrequencySlider_->setWheelInc(0.1f / EditRange::get(EditId::TuningFrequency).extent());
|
||||||
adjustMinMaxToEditRange(stretchedTuningSlider_, EditId::StretchTuning);
|
adjustMinMaxToEditRange(stretchedTuningSlider_, EditId::StretchTuning);
|
||||||
|
adjustMinMaxToEditRange(sampleQualitySlider_, EditId::SampleQuality);
|
||||||
|
adjustMinMaxToEditRange(oscillatorQualitySlider_, EditId::OscillatorQuality);
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -1000,6 +1024,37 @@ 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> labels {{
|
||||||
|
"Nearest", "Linear", "Polynomial",
|
||||||
|
"Sinc 8", "Sinc 12", "Sinc 16", "Sinc 24",
|
||||||
|
"Sinc 36", "Sinc 48", "Sinc 60", "Sinc 72",
|
||||||
|
}};
|
||||||
|
for (size_t i = 0; i < labels.size(); ++i)
|
||||||
|
menu->addEntry(labels[i], float(i));
|
||||||
|
menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
|
||||||
|
int index = int(value);
|
||||||
|
if (index < 0 || unsigned(index) >= labels.size())
|
||||||
|
return false;
|
||||||
|
result = labels[unsigned(index)];
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (SValueMenu *menu = oscillatorQualitySlider_) {
|
||||||
|
static const std::array<const char*, 4> labels {{
|
||||||
|
"Nearest", "Linear", "High", "Dual-High",
|
||||||
|
}};
|
||||||
|
for (size_t i = 0; i < labels.size(); ++i)
|
||||||
|
menu->addEntry(labels[i], float(i));
|
||||||
|
menu->setValueToStringFunction2([](float value, std::string& result, CParamDisplay*) -> bool {
|
||||||
|
int index = int(value);
|
||||||
|
if (index < 0 || unsigned(index) >= labels.size())
|
||||||
|
return false;
|
||||||
|
result = labels[unsigned(index)];
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (SPiano* piano = piano_) {
|
if (SPiano* piano = piano_) {
|
||||||
piano->onKeyPressed = [this](unsigned key, float vel) {
|
piano->onKeyPressed = [this](unsigned key, float vel) {
|
||||||
uint8_t msg[3];
|
uint8_t msg[3];
|
||||||
|
|
@ -1765,6 +1820,14 @@ void Editor::Impl::valueChanged(CControl* ctl)
|
||||||
updateTuningFrequencyLabel(value);
|
updateTuningFrequencyLabel(value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case kTagSetSampleQuality:
|
||||||
|
ctrl.uiSendValue(EditId::SampleQuality, value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kTagSetOscillatorQuality:
|
||||||
|
ctrl.uiSendValue(EditId::OscillatorQuality, value);
|
||||||
|
break;
|
||||||
|
|
||||||
case kTagSetStretchedTuning:
|
case kTagSetStretchedTuning:
|
||||||
ctrl.uiSendValue(EditId::StretchTuning, value);
|
ctrl.uiSendValue(EditId::StretchTuning, value);
|
||||||
updateStretchedTuningLabel(value);
|
updateStretchedTuningLabel(value);
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,18 @@ view__63->addView(view__64);
|
||||||
auto* const view__65 = createValueButton(CRect(20, 60, 120, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12);
|
auto* const view__65 = createValueButton(CRect(20, 60, 120, 85), kTagChooseUserFilesDir, "DefaultPath", kCenterText, 12);
|
||||||
userFilesDirButton_ = view__65;
|
userFilesDirButton_ = view__65;
|
||||||
view__63->addView(view__65);
|
view__63->addView(view__65);
|
||||||
auto* const view__66 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
|
auto* const view__66 = createTitleGroup(CRect(525, 26, 720, 126), -1, "Quality", kCenterText, 12);
|
||||||
piano_ = view__66;
|
view__46->addView(view__66);
|
||||||
view__0->addView(view__66);
|
auto* const view__67 = createValueMenu(CRect(15, 60, 95, 85), kTagSetSampleQuality, "", kCenterText, 12);
|
||||||
|
sampleQualitySlider_ = view__67;
|
||||||
|
view__66->addView(view__67);
|
||||||
|
auto* const view__68 = createValueLabel(CRect(15, 20, 95, 45), -1, "Sample", kCenterText, 12);
|
||||||
|
view__66->addView(view__68);
|
||||||
|
auto* const view__69 = createValueLabel(CRect(100, 20, 180, 45), -1, "Oscillator", kCenterText, 12);
|
||||||
|
view__66->addView(view__69);
|
||||||
|
auto* const view__70 = createValueMenu(CRect(100, 60, 180, 85), kTagSetOscillatorQuality, "", kCenterText, 12);
|
||||||
|
oscillatorQualitySlider_ = view__70;
|
||||||
|
view__66->addView(view__70);
|
||||||
|
auto* const view__71 = createPiano(CRect(5, 400, 795, 470), -1, "", kCenterText, 12);
|
||||||
|
piano_ = view__71;
|
||||||
|
view__0->addView(view__71);
|
||||||
|
|
|
||||||
|
|
@ -236,6 +236,12 @@ connect_port(LV2_Handle instance,
|
||||||
case SFIZZ_STRETCH_TUNING:
|
case SFIZZ_STRETCH_TUNING:
|
||||||
self->stretch_tuning_port = (const float *)data;
|
self->stretch_tuning_port = (const float *)data;
|
||||||
break;
|
break;
|
||||||
|
case SFIZZ_SAMPLE_QUALITY:
|
||||||
|
self->sample_quality_port = (const float *)data;
|
||||||
|
break;
|
||||||
|
case SFIZZ_OSCILLATOR_QUALITY:
|
||||||
|
self->oscillator_quality_port = (const float *)data;
|
||||||
|
break;
|
||||||
case SFIZZ_ACTIVE_VOICES:
|
case SFIZZ_ACTIVE_VOICES:
|
||||||
self->active_voices_port = (float *)data;
|
self->active_voices_port = (float *)data;
|
||||||
break;
|
break;
|
||||||
|
|
@ -976,6 +982,8 @@ run(LV2_Handle instance, uint32_t sample_count)
|
||||||
sfizz_set_volume(self->synth, *(self->volume_port));
|
sfizz_set_volume(self->synth, *(self->volume_port));
|
||||||
sfizz_set_scala_root_key(self->synth, *(self->scala_root_key_port));
|
sfizz_set_scala_root_key(self->synth, *(self->scala_root_key_port));
|
||||||
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_oscillator_quality(self->synth, SFIZZ_PROCESS_LIVE, (int)(*self->oscillator_quality_port));
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -315,8 +315,30 @@ midnam:update a lv2:Feature .
|
||||||
lv2:maximum 1.0 ;
|
lv2:maximum 1.0 ;
|
||||||
units:unit units:coef
|
units:unit units:coef
|
||||||
] , [
|
] , [
|
||||||
a lv2:OutputPort, lv2:ControlPort ;
|
a lv2:InputPort, lv2:ControlPort ;
|
||||||
lv2:index 13 ;
|
lv2:index 13 ;
|
||||||
|
lv2:symbol "sample_quality" ;
|
||||||
|
lv2:name "Sample quality",
|
||||||
|
"Qualité des échantillons"@fr ,
|
||||||
|
"Qualità del campione"@it ;
|
||||||
|
pg:group <@LV2PLUGIN_URI@#tuning> ;
|
||||||
|
lv2:default 1.0 ;
|
||||||
|
lv2:minimum 0.0 ;
|
||||||
|
lv2:maximum 10.0
|
||||||
|
] , [
|
||||||
|
a lv2:InputPort, lv2:ControlPort ;
|
||||||
|
lv2:index 14 ;
|
||||||
|
lv2:symbol "oscillator_quality" ;
|
||||||
|
lv2:name "Oscillator quality",
|
||||||
|
"Qualité des oscillateurs"@fr ,
|
||||||
|
"Qualità dell'oscillatore"@it ;
|
||||||
|
pg:group <@LV2PLUGIN_URI@#tuning> ;
|
||||||
|
lv2:default 1.0 ;
|
||||||
|
lv2:minimum 0.0 ;
|
||||||
|
lv2:maximum 3.0
|
||||||
|
] , [
|
||||||
|
a lv2:OutputPort, lv2:ControlPort ;
|
||||||
|
lv2:index 15 ;
|
||||||
lv2:symbol "active_voices" ;
|
lv2:symbol "active_voices" ;
|
||||||
lv2:name "Active voices",
|
lv2:name "Active voices",
|
||||||
"Voix utilisées"@fr ;
|
"Voix utilisées"@fr ;
|
||||||
|
|
@ -327,7 +349,7 @@ midnam:update a lv2:Feature .
|
||||||
lv2:maximum 256 ;
|
lv2:maximum 256 ;
|
||||||
] , [
|
] , [
|
||||||
a lv2:OutputPort, lv2:ControlPort ;
|
a lv2:OutputPort, lv2:ControlPort ;
|
||||||
lv2:index 14 ;
|
lv2:index 16 ;
|
||||||
lv2:symbol "num_curves" ;
|
lv2:symbol "num_curves" ;
|
||||||
lv2:name "Number of curves",
|
lv2:name "Number of curves",
|
||||||
"Nombre de courbes"@fr ;
|
"Nombre de courbes"@fr ;
|
||||||
|
|
@ -338,7 +360,7 @@ midnam:update a lv2:Feature .
|
||||||
lv2:maximum 65535 ;
|
lv2:maximum 65535 ;
|
||||||
] , [
|
] , [
|
||||||
a lv2:OutputPort, lv2:ControlPort ;
|
a lv2:OutputPort, lv2:ControlPort ;
|
||||||
lv2:index 15 ;
|
lv2:index 17 ;
|
||||||
lv2:symbol "num_masters" ;
|
lv2:symbol "num_masters" ;
|
||||||
lv2:name "Number of masters",
|
lv2:name "Number of masters",
|
||||||
"Nombre de maîtres"@fr ;
|
"Nombre de maîtres"@fr ;
|
||||||
|
|
@ -349,7 +371,7 @@ midnam:update a lv2:Feature .
|
||||||
lv2:maximum 65535 ;
|
lv2:maximum 65535 ;
|
||||||
] , [
|
] , [
|
||||||
a lv2:OutputPort, lv2:ControlPort ;
|
a lv2:OutputPort, lv2:ControlPort ;
|
||||||
lv2:index 16 ;
|
lv2:index 18 ;
|
||||||
lv2:symbol "num_groups" ;
|
lv2:symbol "num_groups" ;
|
||||||
lv2:name "Number of groups",
|
lv2:name "Number of groups",
|
||||||
"Nombre de groupes"@fr ;
|
"Nombre de groupes"@fr ;
|
||||||
|
|
@ -360,7 +382,7 @@ midnam:update a lv2:Feature .
|
||||||
lv2:maximum 65535 ;
|
lv2:maximum 65535 ;
|
||||||
] , [
|
] , [
|
||||||
a lv2:OutputPort, lv2:ControlPort ;
|
a lv2:OutputPort, lv2:ControlPort ;
|
||||||
lv2:index 17 ;
|
lv2:index 19 ;
|
||||||
lv2:symbol "num_regions" ;
|
lv2:symbol "num_regions" ;
|
||||||
lv2:name "Number of regions",
|
lv2:name "Number of regions",
|
||||||
"Nombre de régions"@fr ;
|
"Nombre de régions"@fr ;
|
||||||
|
|
@ -371,7 +393,7 @@ midnam:update a lv2:Feature .
|
||||||
lv2:maximum 65535 ;
|
lv2:maximum 65535 ;
|
||||||
] , [
|
] , [
|
||||||
a lv2:OutputPort, lv2:ControlPort ;
|
a lv2:OutputPort, lv2:ControlPort ;
|
||||||
lv2:index 18 ;
|
lv2:index 20 ;
|
||||||
lv2:symbol "num_samples" ;
|
lv2:symbol "num_samples" ;
|
||||||
lv2:name "Number of samples",
|
lv2:name "Number of samples",
|
||||||
"Nombre d'échantillons"@fr ;
|
"Nombre d'échantillons"@fr ;
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,14 @@ enum
|
||||||
SFIZZ_SCALA_ROOT_KEY = 10,
|
SFIZZ_SCALA_ROOT_KEY = 10,
|
||||||
SFIZZ_TUNING_FREQUENCY = 11,
|
SFIZZ_TUNING_FREQUENCY = 11,
|
||||||
SFIZZ_STRETCH_TUNING = 12,
|
SFIZZ_STRETCH_TUNING = 12,
|
||||||
SFIZZ_ACTIVE_VOICES = 13,
|
SFIZZ_SAMPLE_QUALITY = 13,
|
||||||
SFIZZ_NUM_CURVES = 14,
|
SFIZZ_OSCILLATOR_QUALITY = 14,
|
||||||
SFIZZ_NUM_MASTERS = 15,
|
SFIZZ_ACTIVE_VOICES = 15,
|
||||||
SFIZZ_NUM_GROUPS = 16,
|
SFIZZ_NUM_CURVES = 16,
|
||||||
SFIZZ_NUM_REGIONS = 17,
|
SFIZZ_NUM_MASTERS = 17,
|
||||||
SFIZZ_NUM_SAMPLES = 18,
|
SFIZZ_NUM_GROUPS = 18,
|
||||||
|
SFIZZ_NUM_REGIONS = 19,
|
||||||
|
SFIZZ_NUM_SAMPLES = 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
// For use with instance-access
|
// For use with instance-access
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ struct sfizz_plugin_t
|
||||||
const float *scala_root_key_port {};
|
const float *scala_root_key_port {};
|
||||||
const float *tuning_frequency_port {};
|
const float *tuning_frequency_port {};
|
||||||
const float *stretch_tuning_port {};
|
const float *stretch_tuning_port {};
|
||||||
|
const float *sample_quality_port {};
|
||||||
|
const float *oscillator_quality_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 {};
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,12 @@ port_event(LV2UI_Handle ui,
|
||||||
case SFIZZ_STRETCH_TUNING:
|
case SFIZZ_STRETCH_TUNING:
|
||||||
self->uiReceiveValue(EditId::StretchTuning, v);
|
self->uiReceiveValue(EditId::StretchTuning, v);
|
||||||
break;
|
break;
|
||||||
|
case SFIZZ_SAMPLE_QUALITY:
|
||||||
|
self->uiReceiveValue(EditId::SampleQuality, v);
|
||||||
|
break;
|
||||||
|
case SFIZZ_OSCILLATOR_QUALITY:
|
||||||
|
self->uiReceiveValue(EditId::OscillatorQuality, v);
|
||||||
|
break;
|
||||||
case SFIZZ_ACTIVE_VOICES:
|
case SFIZZ_ACTIVE_VOICES:
|
||||||
self->uiReceiveValue(EditId::UINumActiveVoices, v);
|
self->uiReceiveValue(EditId::UINumActiveVoices, v);
|
||||||
break;
|
break;
|
||||||
|
|
@ -582,6 +588,12 @@ void sfizz_ui_t::uiSendValue(EditId id, const EditValue& v)
|
||||||
case EditId::StretchTuning:
|
case EditId::StretchTuning:
|
||||||
sendFloat(SFIZZ_STRETCH_TUNING, v.to_float());
|
sendFloat(SFIZZ_STRETCH_TUNING, v.to_float());
|
||||||
break;
|
break;
|
||||||
|
case EditId::SampleQuality:
|
||||||
|
sendFloat(SFIZZ_SAMPLE_QUALITY, v.to_float());
|
||||||
|
break;
|
||||||
|
case EditId::OscillatorQuality:
|
||||||
|
sendFloat(SFIZZ_OSCILLATOR_QUALITY, v.to_float());
|
||||||
|
break;
|
||||||
case EditId::SfzFile:
|
case EditId::SfzFile:
|
||||||
sendPath(sfizz_sfz_file_uri, v.to_string());
|
sendPath(sfizz_sfz_file_uri, v.to_string());
|
||||||
break;
|
break;
|
||||||
|
|
@ -635,6 +647,12 @@ void sfizz_ui_t::uiTouch(EditId id, bool t)
|
||||||
case EditId::StretchTuning:
|
case EditId::StretchTuning:
|
||||||
touch->touch(touch->handle, SFIZZ_STRETCH_TUNING, t);
|
touch->touch(touch->handle, SFIZZ_STRETCH_TUNING, t);
|
||||||
break;
|
break;
|
||||||
|
case EditId::SampleQuality:
|
||||||
|
touch->touch(touch->handle, SFIZZ_SAMPLE_QUALITY, t);
|
||||||
|
break;
|
||||||
|
case EditId::OscillatorQuality:
|
||||||
|
touch->touch(touch->handle, SFIZZ_OSCILLATOR_QUALITY, t);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,14 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
|
||||||
SfizzRange::getForParameter(kPidStretchedTuning).createParameter(
|
SfizzRange::getForParameter(kPidStretchedTuning).createParameter(
|
||||||
Steinberg::String("Stretched tuning"), pid++, nullptr,
|
Steinberg::String("Stretched tuning"), pid++, nullptr,
|
||||||
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
|
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
|
||||||
|
parameters.addParameter(
|
||||||
|
SfizzRange::getForParameter(kPidSampleQuality).createParameter(
|
||||||
|
Steinberg::String("Sample quality"), pid++, nullptr,
|
||||||
|
0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId));
|
||||||
|
parameters.addParameter(
|
||||||
|
SfizzRange::getForParameter(kPidOscillatorQuality).createParameter(
|
||||||
|
Steinberg::String("Oscillator quality"), pid++, nullptr,
|
||||||
|
0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId));
|
||||||
|
|
||||||
// MIDI special controllers
|
// MIDI special controllers
|
||||||
parameters.addParameter(Steinberg::String("Aftertouch"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
|
parameters.addParameter(Steinberg::String("Aftertouch"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
|
||||||
|
|
@ -73,7 +81,7 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
|
||||||
shortTitle.printf("CC%u", i);
|
shortTitle.printf("CC%u", i);
|
||||||
|
|
||||||
parameters.addParameter(
|
parameters.addParameter(
|
||||||
SfizzRange::getForParameter(kPidStretchedTuning).createParameter(
|
SfizzRange::getForParameter(kPidCC0 + i).createParameter(
|
||||||
title, pid++, nullptr, 0, Vst::ParameterInfo::kCanAutomate,
|
title, pid++, nullptr, 0, Vst::ParameterInfo::kCanAutomate,
|
||||||
Vst::kRootUnitId, shortTitle));
|
Vst::kRootUnitId, shortTitle));
|
||||||
}
|
}
|
||||||
|
|
@ -174,6 +182,8 @@ tresult PLUGIN_API SfizzVstControllerNoUi::setComponentState(IBStream* stream)
|
||||||
setParam(kPidScalaRootKey, s.scalaRootKey);
|
setParam(kPidScalaRootKey, s.scalaRootKey);
|
||||||
setParam(kPidTuningFrequency, s.tuningFrequency);
|
setParam(kPidTuningFrequency, s.tuningFrequency);
|
||||||
setParam(kPidStretchedTuning, s.stretchedTuning);
|
setParam(kPidStretchedTuning, s.stretchedTuning);
|
||||||
|
setParam(kPidSampleQuality, s.sampleQuality);
|
||||||
|
setParam(kPidOscillatorQuality, s.oscillatorQuality);
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,12 @@ void PLUGIN_API SfizzVstEditor::update(FUnknown* changedUnknown, int32 message)
|
||||||
case kPidStretchedTuning:
|
case kPidStretchedTuning:
|
||||||
uiReceiveValue(EditId::StretchTuning, range.denormalize(value));
|
uiReceiveValue(EditId::StretchTuning, range.denormalize(value));
|
||||||
break;
|
break;
|
||||||
|
case kPidSampleQuality:
|
||||||
|
uiReceiveValue(EditId::SampleQuality, range.denormalize(value));
|
||||||
|
break;
|
||||||
|
case kPidOscillatorQuality:
|
||||||
|
uiReceiveValue(EditId::OscillatorQuality, range.denormalize(value));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (id >= kPidCC0 && id <= kPidCCLast) {
|
if (id >= kPidCC0 && id <= kPidCCLast) {
|
||||||
int cc = int(id - kPidCC0);
|
int cc = int(id - kPidCC0);
|
||||||
|
|
@ -373,6 +379,12 @@ void SfizzVstEditor::uiSendValue(EditId id, const EditValue& v)
|
||||||
case EditId::StretchTuning:
|
case EditId::StretchTuning:
|
||||||
normalizeAndSet(kPidStretchedTuning, v.to_float());
|
normalizeAndSet(kPidStretchedTuning, v.to_float());
|
||||||
break;
|
break;
|
||||||
|
case EditId::SampleQuality:
|
||||||
|
normalizeAndSet(kPidSampleQuality, v.to_float());
|
||||||
|
break;
|
||||||
|
case EditId::OscillatorQuality:
|
||||||
|
normalizeAndSet(kPidOscillatorQuality, v.to_float());
|
||||||
|
break;
|
||||||
|
|
||||||
case EditId::UserFilesDir:
|
case EditId::UserFilesDir:
|
||||||
SfizzPaths::setSfzConfigDefaultPath(fs::u8path(v.to_string()));
|
SfizzPaths::setSfzConfigDefaultPath(fs::u8path(v.to_string()));
|
||||||
|
|
@ -479,6 +491,8 @@ Vst::ParamID SfizzVstEditor::parameterOfEditId(EditId id)
|
||||||
case EditId::ScalaRootKey: return kPidScalaRootKey;
|
case EditId::ScalaRootKey: return kPidScalaRootKey;
|
||||||
case EditId::TuningFrequency: return kPidTuningFrequency;
|
case EditId::TuningFrequency: return kPidTuningFrequency;
|
||||||
case EditId::StretchTuning: return kPidStretchedTuning;
|
case EditId::StretchTuning: return kPidStretchedTuning;
|
||||||
|
case EditId::SampleQuality: return kPidSampleQuality;
|
||||||
|
case EditId::OscillatorQuality: return kPidOscillatorQuality;
|
||||||
default:
|
default:
|
||||||
if (editIdIsCC(id))
|
if (editIdIsCC(id))
|
||||||
return kPidCC0 + ccForEditId(id);
|
return kPidCC0 + ccForEditId(id);
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ enum {
|
||||||
kPidScalaRootKey,
|
kPidScalaRootKey,
|
||||||
kPidTuningFrequency,
|
kPidTuningFrequency,
|
||||||
kPidStretchedTuning,
|
kPidStretchedTuning,
|
||||||
|
kPidSampleQuality,
|
||||||
|
kPidOscillatorQuality,
|
||||||
kPidAftertouch,
|
kPidAftertouch,
|
||||||
kPidPitchBend,
|
kPidPitchBend,
|
||||||
kPidCC0,
|
kPidCC0,
|
||||||
|
|
@ -68,6 +70,10 @@ struct SfizzRange {
|
||||||
return {440.0, 300.0, 500.0};
|
return {440.0, 300.0, 500.0};
|
||||||
case kPidStretchedTuning:
|
case kPidStretchedTuning:
|
||||||
return {0.0, 0.0, 1.0};
|
return {0.0, 0.0, 1.0};
|
||||||
|
case kPidSampleQuality:
|
||||||
|
return {1.0, 0.0, 10.0};
|
||||||
|
case kPidOscillatorQuality:
|
||||||
|
return {1.0, 0.0, 3.0};
|
||||||
case kPidAftertouch:
|
case kPidAftertouch:
|
||||||
return {0.0, 0.0, 1.0};
|
return {0.0, 0.0, 1.0};
|
||||||
case kPidPitchBend:
|
case kPidPitchBend:
|
||||||
|
|
|
||||||
|
|
@ -287,6 +287,8 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data)
|
||||||
synth.loadStretchTuningByRatio(_state.stretchedTuning);
|
synth.loadStretchTuningByRatio(_state.stretchedTuning);
|
||||||
_currentStretchedTuning = _state.stretchedTuning;
|
_currentStretchedTuning = _state.stretchedTuning;
|
||||||
}
|
}
|
||||||
|
synth.setSampleQuality(sfz::Sfizz::ProcessLive, _state.sampleQuality);
|
||||||
|
synth.setOscillatorQuality(sfz::Sfizz::ProcessLive, _state.oscillatorQuality);
|
||||||
|
|
||||||
synth.renderBlock(outputs, numFrames, numChannels);
|
synth.renderBlock(outputs, numFrames, numChannels);
|
||||||
|
|
||||||
|
|
@ -380,6 +382,12 @@ void SfizzVstProcessor::playOrderedParameter(int32 sampleOffset, Vst::ParamID id
|
||||||
case kPidStretchedTuning:
|
case kPidStretchedTuning:
|
||||||
_state.stretchedTuning = range.denormalize(value);
|
_state.stretchedTuning = range.denormalize(value);
|
||||||
break;
|
break;
|
||||||
|
case kPidSampleQuality:
|
||||||
|
_state.sampleQuality = static_cast<int32>(range.denormalize(value));
|
||||||
|
break;
|
||||||
|
case kPidOscillatorQuality:
|
||||||
|
_state.oscillatorQuality = static_cast<int32>(range.denormalize(value));
|
||||||
|
break;
|
||||||
case kPidAftertouch:
|
case kPidAftertouch:
|
||||||
synth.aftertouch(sampleOffset, fastRound(value * 127.0));
|
synth.aftertouch(sampleOffset, fastRound(value * 127.0));
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,9 @@ tresult SfizzVstState::load(IBStream* state)
|
||||||
if (!s.readInt64u(version))
|
if (!s.readInt64u(version))
|
||||||
return kResultFalse;
|
return kResultFalse;
|
||||||
|
|
||||||
|
if (version > currentStateVersion)
|
||||||
|
return kResultFalse;
|
||||||
|
|
||||||
if (const char* str = s.readStr8())
|
if (const char* str = s.readStr8())
|
||||||
sfzFile = str;
|
sfzFile = str;
|
||||||
else
|
else
|
||||||
|
|
@ -58,6 +61,18 @@ tresult SfizzVstState::load(IBStream* state)
|
||||||
stretchedTuning = defaults.stretchedTuning;
|
stretchedTuning = defaults.stretchedTuning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version >= 3) {
|
||||||
|
if (!s.readInt32(sampleQuality))
|
||||||
|
return kResultFalse;
|
||||||
|
|
||||||
|
if (!s.readInt32(oscillatorQuality))
|
||||||
|
return kResultFalse;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sampleQuality = defaults.sampleQuality;
|
||||||
|
oscillatorQuality = defaults.oscillatorQuality;
|
||||||
|
}
|
||||||
|
|
||||||
controllers.clear();
|
controllers.clear();
|
||||||
if (version >= 2) {
|
if (version >= 2) {
|
||||||
uint32 count;
|
uint32 count;
|
||||||
|
|
@ -77,9 +92,6 @@ tresult SfizzVstState::load(IBStream* state)
|
||||||
controllers.shrink_to_fit();
|
controllers.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version > 2)
|
|
||||||
return kResultFalse;
|
|
||||||
|
|
||||||
return kResultTrue;
|
return kResultTrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,6 +129,12 @@ tresult SfizzVstState::store(IBStream* state) const
|
||||||
if (!s.writeFloat(stretchedTuning))
|
if (!s.writeFloat(stretchedTuning))
|
||||||
return kResultFalse;
|
return kResultFalse;
|
||||||
|
|
||||||
|
if (!s.writeInt32(sampleQuality))
|
||||||
|
return kResultFalse;
|
||||||
|
|
||||||
|
if (!s.writeInt32(oscillatorQuality))
|
||||||
|
return kResultFalse;
|
||||||
|
|
||||||
{
|
{
|
||||||
uint32 ccCount = 0;
|
uint32 ccCount = 0;
|
||||||
uint32 ccLimit = uint32(std::min(controllers.size(), size_t(0x10000)));
|
uint32 ccLimit = uint32(std::min(controllers.size(), size_t(0x10000)));
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,11 @@ public:
|
||||||
int32 scalaRootKey = 60;
|
int32 scalaRootKey = 60;
|
||||||
float tuningFrequency = 440.0;
|
float tuningFrequency = 440.0;
|
||||||
float stretchedTuning = 0.0;
|
float stretchedTuning = 0.0;
|
||||||
|
int32 sampleQuality = 1;
|
||||||
|
int32 oscillatorQuality = 1;
|
||||||
std::vector<absl::optional<float>> controllers;
|
std::vector<absl::optional<float>> controllers;
|
||||||
|
|
||||||
static constexpr uint64 currentStateVersion = 2;
|
static constexpr uint64 currentStateVersion = 3;
|
||||||
|
|
||||||
tresult load(IBStream* state);
|
tresult load(IBStream* state);
|
||||||
tresult store(IBStream* state) const;
|
tresult store(IBStream* state) const;
|
||||||
|
|
|
||||||
38
src/sfizz.h
38
src/sfizz.h
|
|
@ -648,7 +648,7 @@ SFIZZ_EXPORTED_API bool sfizz_set_oversampling_factor(sfizz_synth_t* synth, sfiz
|
||||||
* @param synth The synth.
|
* @param synth The synth.
|
||||||
* @param[in] mode The processing mode.
|
* @param[in] mode The processing mode.
|
||||||
*
|
*
|
||||||
* @return The sample quality for the given mode, in the range 1 to 10.
|
* @return The sample quality for the given mode, in the range 0 to 10.
|
||||||
*/
|
*/
|
||||||
SFIZZ_EXPORTED_API int sfizz_get_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode);
|
SFIZZ_EXPORTED_API int sfizz_get_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode);
|
||||||
|
|
||||||
|
|
@ -663,13 +663,47 @@ SFIZZ_EXPORTED_API int sfizz_get_sample_quality(sfizz_synth_t* synth, sfizz_proc
|
||||||
*
|
*
|
||||||
* @param synth The synth.
|
* @param synth The synth.
|
||||||
* @param[in] mode The processing mode.
|
* @param[in] mode The processing mode.
|
||||||
* @param[in] quality The desired sample quality, in the range 1 to 10.
|
* @param[in] quality The desired sample quality, in the range 0 to 10.
|
||||||
*
|
*
|
||||||
* @par Thread-safety constraints
|
* @par Thread-safety constraints
|
||||||
* - @b RT: the function must be invoked from the Real-time thread
|
* - @b RT: the function must be invoked from the Real-time thread
|
||||||
*/
|
*/
|
||||||
SFIZZ_EXPORTED_API void sfizz_set_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality);
|
SFIZZ_EXPORTED_API void sfizz_set_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the default oscillator quality.
|
||||||
|
*
|
||||||
|
* This is the quality setting which the engine uses when the instrument
|
||||||
|
* does not use the opcode `oscillator_quality`. The engine uses distinct
|
||||||
|
* default quality settings for live mode and freewheeling mode,
|
||||||
|
* which both can be accessed by the means of this function.
|
||||||
|
* @since 0.6.0
|
||||||
|
*
|
||||||
|
* @param synth The synth.
|
||||||
|
* @param[in] mode The processing mode.
|
||||||
|
*
|
||||||
|
* @return The oscillator quality for the given mode, in the range 0 to 10.
|
||||||
|
*/
|
||||||
|
SFIZZ_EXPORTED_API int sfizz_get_oscillator_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the default oscillator quality.
|
||||||
|
*
|
||||||
|
* This is the quality setting which the engine uses when the instrument
|
||||||
|
* does not use the opcode `oscillator_quality`. The engine uses distinct
|
||||||
|
* default quality settings for live mode and freewheeling mode,
|
||||||
|
* which both can be accessed by the means of this function.
|
||||||
|
* @since 0.6.0
|
||||||
|
*
|
||||||
|
* @param synth The synth.
|
||||||
|
* @param[in] mode The processing mode.
|
||||||
|
* @param[in] quality The desired oscillator quality, in the range 0 to 10.
|
||||||
|
*
|
||||||
|
* @par Thread-safety constraints
|
||||||
|
* - @b RT: the function must be invoked from the Real-time thread
|
||||||
|
*/
|
||||||
|
SFIZZ_EXPORTED_API void sfizz_set_oscillator_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the global instrument volume.
|
* @brief Set the global instrument volume.
|
||||||
* @since 0.2.0
|
* @since 0.2.0
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ public:
|
||||||
*
|
*
|
||||||
* @param[in] mode The processing mode.
|
* @param[in] mode The processing mode.
|
||||||
*
|
*
|
||||||
* @return The sample quality for the given mode, in the range 1 to 10.
|
* @return The sample quality for the given mode, in the range 0 to 10.
|
||||||
*/
|
*/
|
||||||
int getSampleQuality(ProcessMode mode);
|
int getSampleQuality(ProcessMode mode);
|
||||||
|
|
||||||
|
|
@ -305,13 +305,46 @@ public:
|
||||||
* @since 0.4.0
|
* @since 0.4.0
|
||||||
*
|
*
|
||||||
* @param[in] mode The processing mode.
|
* @param[in] mode The processing mode.
|
||||||
* @param[in] quality The desired sample quality, in the range 1 to 10.
|
* @param[in] quality The desired sample quality, in the range 0 to 10.
|
||||||
*
|
*
|
||||||
* @par Thread-safety constraints
|
* @par Thread-safety constraints
|
||||||
* - @b RT: the function must be invoked from the Real-time thread
|
* - @b RT: the function must be invoked from the Real-time thread
|
||||||
*/
|
*/
|
||||||
void setSampleQuality(ProcessMode mode, int quality);
|
void setSampleQuality(ProcessMode mode, int quality);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the default oscillator quality.
|
||||||
|
*
|
||||||
|
* This is the quality setting which the engine uses when the instrument
|
||||||
|
* does not use the opcode `oscillator_quality`. The engine uses distinct
|
||||||
|
* default quality settings for live mode and freewheeling mode,
|
||||||
|
* which both can be accessed by the means of this function.
|
||||||
|
* @since 0.6.0
|
||||||
|
*
|
||||||
|
* @param[in] mode The processing mode.
|
||||||
|
*
|
||||||
|
* @return The oscillator quality for the given mode, in the range 0 to 3.
|
||||||
|
*/
|
||||||
|
int getOscillatorQuality(ProcessMode mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the default oscillator quality.
|
||||||
|
*
|
||||||
|
* This is the quality setting which the engine uses when the instrument
|
||||||
|
* does not use the opcode `oscillator_quality`. The engine uses distinct
|
||||||
|
* default quality settings for live mode and freewheeling mode,
|
||||||
|
* which both can be accessed by the means of this function.
|
||||||
|
*
|
||||||
|
* @since 0.6.0
|
||||||
|
*
|
||||||
|
* @param[in] mode The processing mode.
|
||||||
|
* @param[in] quality The desired oscillator quality, in the range 0 to 3.
|
||||||
|
*
|
||||||
|
* @par Thread-safety constraints
|
||||||
|
* - @b RT: the function must be invoked from the Real-time thread
|
||||||
|
*/
|
||||||
|
void setOscillatorQuality(ProcessMode mode, int quality);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,8 @@ namespace Default
|
||||||
|
|
||||||
// Various defaut values
|
// Various defaut values
|
||||||
// e.g. "additional" or multiple defautl values
|
// e.g. "additional" or multiple defautl values
|
||||||
constexpr int freewheelingQuality { 10 };
|
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
|
||||||
|
|
|
||||||
|
|
@ -1645,9 +1645,9 @@ int Synth::getSampleQuality(ProcessMode mode)
|
||||||
|
|
||||||
void Synth::setSampleQuality(ProcessMode mode, int quality)
|
void Synth::setSampleQuality(ProcessMode mode, int quality)
|
||||||
{
|
{
|
||||||
SFIZZ_CHECK(quality >= 1 && quality <= 10);
|
SFIZZ_CHECK(quality >= 0 && quality <= 10);
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
quality = clamp(quality, 1, 10);
|
quality = clamp(quality, 0, 10);
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case ProcessLive:
|
case ProcessLive:
|
||||||
|
|
@ -1662,6 +1662,39 @@ void Synth::setSampleQuality(ProcessMode mode, int quality)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Synth::getOscillatorQuality(ProcessMode mode)
|
||||||
|
{
|
||||||
|
Impl& impl = *impl_;
|
||||||
|
switch (mode) {
|
||||||
|
case ProcessLive:
|
||||||
|
return impl.resources_.synthConfig.liveOscillatorQuality;
|
||||||
|
case ProcessFreewheeling:
|
||||||
|
return impl.resources_.synthConfig.freeWheelingOscillatorQuality;
|
||||||
|
default:
|
||||||
|
SFIZZ_CHECK(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Synth::setOscillatorQuality(ProcessMode mode, int quality)
|
||||||
|
{
|
||||||
|
SFIZZ_CHECK(quality >= 0 && quality <= 3);
|
||||||
|
Impl& impl = *impl_;
|
||||||
|
quality = clamp(quality, 0, 3);
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case ProcessLive:
|
||||||
|
impl.resources_.synthConfig.liveOscillatorQuality = quality;
|
||||||
|
break;
|
||||||
|
case ProcessFreewheeling:
|
||||||
|
impl.resources_.synthConfig.freeWheelingOscillatorQuality = quality;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SFIZZ_CHECK(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float Synth::getVolume() const noexcept
|
float Synth::getVolume() const noexcept
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,21 @@ public:
|
||||||
* @param quality the quality setting
|
* @param quality the quality setting
|
||||||
*/
|
*/
|
||||||
void setSampleQuality(ProcessMode mode, int quality);
|
void setSampleQuality(ProcessMode mode, int quality);
|
||||||
|
/**
|
||||||
|
* @brief Get the default oscillator quality for the given mode.
|
||||||
|
*
|
||||||
|
* @param mode the processing mode
|
||||||
|
*
|
||||||
|
* @return the quality setting
|
||||||
|
*/
|
||||||
|
int getOscillatorQuality(ProcessMode mode);
|
||||||
|
/**
|
||||||
|
* @brief Set the default oscillator quality for the given mode.
|
||||||
|
*
|
||||||
|
* @param mode the processing mode
|
||||||
|
* @param quality the quality setting
|
||||||
|
*/
|
||||||
|
void setOscillatorQuality(ProcessMode mode, int quality);
|
||||||
/**
|
/**
|
||||||
* @brief Get the current value for the volume, in dB.
|
* @brief Get the current value for the volume, in dB.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,19 @@ struct SynthConfig
|
||||||
bool freeWheeling { false };
|
bool freeWheeling { false };
|
||||||
|
|
||||||
int liveSampleQuality { Default::sampleQuality };
|
int liveSampleQuality { Default::sampleQuality };
|
||||||
int freeWheelingSampleQuality { Default::freewheelingQuality };
|
int freeWheelingSampleQuality { Default::freewheelingSampleQuality };
|
||||||
|
|
||||||
|
int liveOscillatorQuality { Default::oscillatorQuality };
|
||||||
|
int freeWheelingOscillatorQuality { Default::freewheelingOscillatorQuality };
|
||||||
|
|
||||||
int currentSampleQuality() const noexcept
|
int currentSampleQuality() const noexcept
|
||||||
{
|
{
|
||||||
return freeWheeling ? freeWheelingSampleQuality : liveSampleQuality;
|
return freeWheeling ? freeWheelingSampleQuality : liveSampleQuality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int currentOscillatorQuality() const noexcept
|
||||||
|
{
|
||||||
|
return freeWheeling ? freeWheelingOscillatorQuality : liveOscillatorQuality;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,12 @@ struct Voice::Impl
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
int getCurrentSampleQuality() const noexcept;
|
int getCurrentSampleQuality() const noexcept;
|
||||||
|
/**
|
||||||
|
* @brief Get the oscillator quality determined by the active region.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int getCurrentOscillatorQuality() const noexcept;
|
||||||
/**
|
/**
|
||||||
* @brief Reset the loop information
|
* @brief Reset the loop information
|
||||||
*
|
*
|
||||||
|
|
@ -531,6 +537,18 @@ int Voice::getCurrentSampleQuality() const noexcept
|
||||||
return impl.getCurrentSampleQuality();
|
return impl.getCurrentSampleQuality();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Voice::Impl::getCurrentOscillatorQuality() const noexcept
|
||||||
|
{
|
||||||
|
return (region_ && region_->oscillatorQuality) ?
|
||||||
|
*region_->oscillatorQuality : resources_.synthConfig.currentOscillatorQuality();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Voice::getCurrentOscillatorQuality() const noexcept
|
||||||
|
{
|
||||||
|
Impl& impl = *impl_;
|
||||||
|
return impl.getCurrentOscillatorQuality();
|
||||||
|
}
|
||||||
|
|
||||||
bool Voice::isFree() const noexcept
|
bool Voice::isFree() const noexcept
|
||||||
{
|
{
|
||||||
Impl& impl = *impl_;
|
Impl& impl = *impl_;
|
||||||
|
|
@ -1459,6 +1477,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
||||||
|
|
||||||
const int oscillatorMode = region_->oscillatorMode;
|
const int oscillatorMode = region_->oscillatorMode;
|
||||||
const int oscillatorMulti = region_->oscillatorMulti;
|
const int oscillatorMulti = region_->oscillatorMulti;
|
||||||
|
const int quality = getCurrentOscillatorQuality();
|
||||||
|
|
||||||
if (oscillatorMode <= 0 && oscillatorMulti < 2) {
|
if (oscillatorMode <= 0 && oscillatorMulti < 2) {
|
||||||
// single oscillator
|
// single oscillator
|
||||||
|
|
@ -1467,6 +1486,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
||||||
return;
|
return;
|
||||||
|
|
||||||
WavetableOscillator& osc = waveOscillators_[0];
|
WavetableOscillator& osc = waveOscillators_[0];
|
||||||
|
osc.setQuality(quality);
|
||||||
fill(*detuneSpan, 1.0f);
|
fill(*detuneSpan, 1.0f);
|
||||||
osc.processModulated(frequencies->data(), detuneSpan->data(), tempSpan->data(), buffer.getNumFrames());
|
osc.processModulated(frequencies->data(), detuneSpan->data(), tempSpan->data(), buffer.getNumFrames());
|
||||||
copy<float>(*tempSpan, leftSpan);
|
copy<float>(*tempSpan, leftSpan);
|
||||||
|
|
@ -1483,6 +1503,7 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
||||||
const float* detuneMod = resources_.modMatrix.getModulation(oscillatorDetuneTarget_);
|
const float* detuneMod = resources_.modMatrix.getModulation(oscillatorDetuneTarget_);
|
||||||
for (unsigned u = 0, uSize = waveUnisonSize_; u < uSize; ++u) {
|
for (unsigned u = 0, uSize = waveUnisonSize_; u < uSize; ++u) {
|
||||||
WavetableOscillator& osc = waveOscillators_[u];
|
WavetableOscillator& osc = waveOscillators_[u];
|
||||||
|
osc.setQuality(quality);
|
||||||
if (!detuneMod)
|
if (!detuneMod)
|
||||||
fill(*detuneSpan, waveDetuneRatio_[u]);
|
fill(*detuneSpan, waveDetuneRatio_[u]);
|
||||||
else {
|
else {
|
||||||
|
|
@ -1512,6 +1533,8 @@ void Voice::Impl::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
||||||
|
|
||||||
WavetableOscillator& oscCar = waveOscillators_[0];
|
WavetableOscillator& oscCar = waveOscillators_[0];
|
||||||
WavetableOscillator& oscMod = waveOscillators_[1];
|
WavetableOscillator& oscMod = waveOscillators_[1];
|
||||||
|
oscCar.setQuality(quality);
|
||||||
|
oscMod.setQuality(quality);
|
||||||
|
|
||||||
// compute the modulator
|
// compute the modulator
|
||||||
auto modulatorSpan = resources_.bufferPool.getBuffer(numFrames);
|
auto modulatorSpan = resources_.bufferPool.getBuffer(numFrames);
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,13 @@ public:
|
||||||
*/
|
*/
|
||||||
int getCurrentSampleQuality() const noexcept;
|
int getCurrentSampleQuality() const noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the oscillator quality determined by the active region.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int getCurrentOscillatorQuality() const noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Register a note-off event; this may trigger a release.
|
* @brief Register a note-off event; this may trigger a release.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -140,6 +140,16 @@ void sfz::Sfizz::setSampleQuality(ProcessMode mode, int quality)
|
||||||
synth->synth.setSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
synth->synth.setSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sfz::Sfizz::getOscillatorQuality(ProcessMode mode)
|
||||||
|
{
|
||||||
|
return synth->synth.getOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfz::Sfizz::setOscillatorQuality(ProcessMode mode, int quality)
|
||||||
|
{
|
||||||
|
synth->synth.setOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
||||||
|
}
|
||||||
|
|
||||||
float sfz::Sfizz::getVolume() const noexcept
|
float sfz::Sfizz::getVolume() const noexcept
|
||||||
{
|
{
|
||||||
return synth->synth.getVolume();
|
return synth->synth.getVolume();
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,16 @@ void sfizz_set_sample_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, i
|
||||||
return synth->synth.setSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
return synth->synth.setSampleQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sfizz_get_oscillator_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode)
|
||||||
|
{
|
||||||
|
return synth->synth.getOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void sfizz_set_oscillator_quality(sfizz_synth_t* synth, sfizz_process_mode_t mode, int quality)
|
||||||
|
{
|
||||||
|
return synth->synth.setOscillatorQuality(static_cast<sfz::Synth::ProcessMode>(mode), quality);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
|
|
@ -584,7 +584,7 @@ TEST_CASE("[Synth] sample quality")
|
||||||
synth.noteOn(0, 60, 100);
|
synth.noteOn(0, 60, 100);
|
||||||
synth.renderBlock(buffer);
|
synth.renderBlock(buffer);
|
||||||
REQUIRE(synth.getNumActiveVoices() == 1);
|
REQUIRE(synth.getNumActiveVoices() == 1);
|
||||||
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == sfz::Default::freewheelingQuality);
|
REQUIRE(synth.getVoiceView(0)->getCurrentSampleQuality() == sfz::Default::freewheelingSampleQuality);
|
||||||
synth.allSoundOff();
|
synth.allSoundOff();
|
||||||
synth.disableFreeWheeling();
|
synth.disableFreeWheeling();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue