diff --git a/vst/SfizzVstController.cpp b/vst/SfizzVstController.cpp index eba85ca2..065c41fa 100644 --- a/vst/SfizzVstController.cpp +++ b/vst/SfizzVstController.cpp @@ -26,6 +26,10 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context) kParamNumVoicesRange.createParameter( Steinberg::String("Polyphony"), pid++, nullptr, 0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId)); + parameters.addParameter( + kParamOversamplingRange.createParameter( + Steinberg::String("Oversampling"), pid++, nullptr, + 0, Vst::ParameterInfo::kNoFlags, Vst::kRootUnitId)); // MIDI controllers for (unsigned i = 0; i < kNumControllerParams; ++i) { @@ -71,6 +75,40 @@ tresult PLUGIN_API SfizzVstControllerNoUi::getMidiControllerAssignment(int32 bus } } +tresult PLUGIN_API SfizzVstControllerNoUi::getParamStringByValue(Vst::ParamID tag, Vst::ParamValue valueNormalized, Vst::String128 string) +{ + switch (tag) { + case kPidOversampling: + { + int factor = SfizzMisc::adaptOversamplingFactor( + kParamOversamplingRange.denormalize(valueNormalized)); + Steinberg::String buf; + buf.printf("%dX", factor); + buf.copyTo(string); + return kResultTrue; + } + } + + return EditController::getParamStringByValue(tag, valueNormalized, string); +} + +tresult PLUGIN_API SfizzVstControllerNoUi::getParamValueByString(Vst::ParamID tag, Vst::TChar* string, Vst::ParamValue& valueNormalized) +{ + switch (tag) { + case kPidOversampling: + { + int factor; + if (!Steinberg::String::scanInt32(string, factor, false)) + factor = 1; + valueNormalized = kParamOversamplingRange.normalize( + SfizzMisc::adaptOversamplingFactor(factor)); + return kResultTrue; + } + } + + return EditController::getParamValueByString(tag, string, valueNormalized); +} + // --- Controller with UI --- // IPlugView* PLUGIN_API SfizzVstController::createView(FIDString _name) @@ -104,6 +142,11 @@ tresult PLUGIN_API SfizzVstController::setParamNormalized(Vst::ParamID tag, Vst: value = kParamNumVoicesRange.denormalize(normValue); break; } + case kPidOversampling: { + slotI32 = &_state.oversampling; + value = kParamOversamplingRange.denormalize(normValue); + break; + } } bool update = false; @@ -158,6 +201,7 @@ tresult PLUGIN_API SfizzVstController::setComponentState(IBStream* state) setParamNormalized(kPidVolume, kParamVolumeRange.normalize(s.volume)); setParamNormalized(kPidNumVoices, kParamNumVoicesRange.normalize(s.numVoices)); + setParamNormalized(kPidOversampling, kParamOversamplingRange.normalize(s.oversampling)); for (StateListener* listener : _stateListeners) listener->onStateChanged(); diff --git a/vst/SfizzVstController.h b/vst/SfizzVstController.h index e8ca3037..b8455ecd 100644 --- a/vst/SfizzVstController.h +++ b/vst/SfizzVstController.h @@ -24,6 +24,10 @@ public: tresult PLUGIN_API getMidiControllerAssignment(int32 busIndex, int16 channel, Vst::CtrlNumber midiControllerNumber, Vst::ParamID& id) override; + tresult PLUGIN_API getParamStringByValue(Vst::ParamID tag, Vst::ParamValue valueNormalized, Vst::String128 string) override; + tresult PLUGIN_API getParamValueByString(Vst::ParamID tag, Vst::TChar* string, Vst::ParamValue& valueNormalized) override; + + // interfaces OBJ_METHODS(SfizzVstControllerNoUi, Vst::EditController) DEFINE_INTERFACES diff --git a/vst/SfizzVstEditor.cpp b/vst/SfizzVstEditor.cpp index d3079626..65da051a 100644 --- a/vst/SfizzVstEditor.cpp +++ b/vst/SfizzVstEditor.cpp @@ -81,6 +81,11 @@ void SfizzVstEditor::valueChanged(CControl* ctl) controller->performEdit(kPidNumVoices, valueNorm); break; + case kTagSetOversampling: + controller->setParamNormalized(kPidOversampling, valueNorm); + controller->performEdit(kPidOversampling, valueNorm); + break; + default: if (tag >= kTagFirstChangePanel && tag <= kTagLastChangePanel) setActivePanel(tag - kTagFirstChangePanel); @@ -96,6 +101,7 @@ void SfizzVstEditor::enterOrLeaveEdit(CControl* ctl, bool enter) switch (tag) { case kTagSetVolume: id = kPidVolume; break; case kTagSetNumVoices: id = kPidNumVoices; break; + case kTagSetOversampling: id = kPidOversampling; break; default: return; } @@ -255,17 +261,19 @@ void SfizzVstEditor::createFrameContents() adjustMinMaxToRangeParam(slider, kPidNumVoices); _numVoicesSlider = slider; - // row.top += interRow; - // row.bottom += interRow; + row.top += interRow; + row.bottom += interRow; - // label = new CTextLabel(leftSide(), "Oversampling"); - // label->setFontColor(CColor(0x00, 0x00, 0x00)); - // label->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00)); - // label->setBackColor(CColor(0x00, 0x00, 0x00, 0x00)); - // label->setHoriAlign(kLeftText); - // panel->addView(label); - // slider = new SimpleSlider(rightSide(), this, -1); - // panel->addView(slider); + label = new CTextLabel(leftSide(), "Oversampling"); + label->setFontColor(CColor(0x00, 0x00, 0x00)); + label->setFrameColor(CColor(0x00, 0x00, 0x00, 0x00)); + label->setBackColor(CColor(0x00, 0x00, 0x00, 0x00)); + label->setHoriAlign(kLeftText); + panel->addView(label); + slider = new SimpleSlider(rightSide(), this, kTagSetOversampling); + panel->addView(slider); + adjustMinMaxToRangeParam(slider, kPidOversampling); + _oversamplingSlider = slider; // row.top += interRow; // row.bottom += interRow; @@ -276,8 +284,10 @@ void SfizzVstEditor::createFrameContents() // label->setBackColor(CColor(0x00, 0x00, 0x00, 0x00)); // label->setHoriAlign(kLeftText); // panel->addView(label); - // slider = new SimpleSlider(rightSide(), this, -1); + // slider = new SimpleSlider(rightSide(), this, kTag); // panel->addView(slider); + // adjustMinMaxToRangeParam(slider, kPid); + // _aSlider = slider; // row.top += interRow; // row.bottom += interRow; @@ -288,8 +298,10 @@ void SfizzVstEditor::createFrameContents() // label->setBackColor(CColor(0x00, 0x00, 0x00, 0x00)); // label->setHoriAlign(kLeftText); // panel->addView(label); - // slider = new SimpleSlider(rightSide(), this, -1); + // slider = new SimpleSlider(rightSide(), this, kTag); // panel->addView(slider); + // adjustMinMaxToRangeParam(slider, kPid); + // _aSlider = slider; _subPanels[kPanelSettings] = panel; } @@ -341,6 +353,8 @@ void SfizzVstEditor::updateStateDisplay() _volumeSlider->setValue(state.volume); if (_numVoicesSlider) _numVoicesSlider->setValue(state.numVoices); + if (_oversamplingSlider) + _oversamplingSlider->setValue(state.oversampling); setActivePanel(uiState.activePanel); } diff --git a/vst/SfizzVstEditor.h b/vst/SfizzVstEditor.h index e71bd284..353db127 100644 --- a/vst/SfizzVstEditor.h +++ b/vst/SfizzVstEditor.h @@ -63,6 +63,7 @@ private: kTagLoadSfzFile, kTagSetVolume, kTagSetNumVoices, + kTagSetOversampling, kTagFirstChangePanel, kTagLastChangePanel = kTagFirstChangePanel + kNumPanels - 1, }; @@ -71,4 +72,5 @@ private: CTextLabel* _fileLabel = nullptr; CSliderBase *_volumeSlider = nullptr; CSliderBase *_numVoicesSlider = nullptr; + CSliderBase *_oversamplingSlider = nullptr; }; diff --git a/vst/SfizzVstProcessor.cpp b/vst/SfizzVstProcessor.cpp index 5cdafaf9..b7111dce 100644 --- a/vst/SfizzVstProcessor.cpp +++ b/vst/SfizzVstProcessor.cpp @@ -81,6 +81,8 @@ void SfizzVstProcessor::syncStateToSynth() synth->loadSfzFile(_state.sfzFile); synth->setVolume(_state.volume); synth->setNumVoices(_state.numVoices); + synth->setOversamplingFactor( + SfizzMisc::adaptOversamplingFactor(_state.oversampling)); } tresult PLUGIN_API SfizzVstProcessor::canProcessSampleSize(int32 symbolicSampleSize) @@ -189,6 +191,21 @@ void SfizzVstProcessor::processParameterChanges(Vst::IParameterChanges& pc) _semaToWorker.post(); } break; + case kPidOversampling: + if (pointCount > 0 && vq->getPoint(pointCount - 1, sampleOffset, value) == kResultTrue) { + Vst::IMessage* msg = allocateMessage(); + if (!msg) + break; + msg->setMessageID("SetOversampling"); + Vst::IAttributeList* attr = msg->getAttributes(); + attr->setInt("Oversampling", kParamOversamplingRange.denormalize(value)); + if (!_fifoToWorker.push(msg)) { + msg->release(); + break; + } + _semaToWorker.post(); + } + break; } } } @@ -319,6 +336,14 @@ void SfizzVstProcessor::doBackgroundWork() _synth->setNumVoices(value); } } + else if (!std::strcmp(id, "SetOversampling")) { + int64 value; + if (attr->getInt("Oversampling", value) == kResultTrue) { + _state.oversampling = value; + _synth->setOversamplingFactor( + SfizzMisc::adaptOversamplingFactor(value)); + } + } msg->release(); } diff --git a/vst/SfizzVstState.cpp b/vst/SfizzVstState.cpp index 6c951314..0b416c3d 100644 --- a/vst/SfizzVstState.cpp +++ b/vst/SfizzVstState.cpp @@ -5,6 +5,7 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "SfizzVstState.h" +#include #include #include @@ -27,6 +28,9 @@ tresult SfizzVstState::load(IBStream* state) if (!s.readInt32(numVoices)) return kResultFalse; + if (!s.readInt32(oversampling)) + return kResultFalse; + return kResultTrue; } @@ -46,6 +50,9 @@ tresult SfizzVstState::store(IBStream* state) const if (!s.writeInt32(numVoices)) return kResultFalse; + if (!s.writeInt32(oversampling)) + return kResultFalse; + return kResultTrue; } @@ -75,3 +82,16 @@ tresult SfizzUiState::store(IBStream* state) const return kResultTrue; } + +/// +int SfizzMisc::adaptOversamplingFactor(int valueDenorm) +{ + if (valueDenorm >= 8) + return SFIZZ_OVERSAMPLING_X8; + else if (valueDenorm >= 4) + return SFIZZ_OVERSAMPLING_X4; + else if (valueDenorm >= 2) + return SFIZZ_OVERSAMPLING_X2; + else + return SFIZZ_OVERSAMPLING_X1; +} diff --git a/vst/SfizzVstState.h b/vst/SfizzVstState.h index f68412f6..6bc6dbe5 100644 --- a/vst/SfizzVstState.h +++ b/vst/SfizzVstState.h @@ -20,6 +20,7 @@ enum { enum { kPidVolume, kPidNumVoices, + kPidOversampling, kPidMidiCC0, kPidMidiCCLast = kPidMidiCC0 + kNumControllerParams - 1, kPidMidiAftertouch, @@ -32,6 +33,7 @@ public: std::string sfzFile; float volume = 0; int numVoices = 64; + int oversampling = 1; static constexpr uint64 currentStateVersion = 0; @@ -75,3 +77,9 @@ struct SfizzParameterRange { static constexpr SfizzParameterRange kParamVolumeRange(0.0, -60.0, +6.0); static constexpr SfizzParameterRange kParamNumVoicesRange(64.0, 1.0, 256.0); +static constexpr SfizzParameterRange kParamOversamplingRange(1.0, 1.0, 8.0); + +class SfizzMisc { +public: + static int adaptOversamplingFactor(int factor); +};