Update the VST plugin

This commit is contained in:
Jean Pierre Cimalando 2020-06-20 05:49:00 +02:00 committed by Paul Ferrand
parent ba0c68f5a1
commit 42bf66dd74
8 changed files with 541 additions and 28 deletions

View file

@ -34,10 +34,22 @@ tresult PLUGIN_API SfizzVstControllerNoUi::initialize(FUnknown* context)
kParamPreloadSizeRange.createParameter(
Steinberg::String("Preload size"), pid++, nullptr,
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
parameters.addParameter(
kParamScalaRootKey.createParameter(
Steinberg::String("Scala root key"), pid++, nullptr,
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
parameters.addParameter(
kParamTuningFrequency.createParameter(
Steinberg::String("Tuning frequency"), pid++, Steinberg::String("Hz"),
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
parameters.addParameter(
kParamStretchedTuning.createParameter(
Steinberg::String("Stretched tuning"), pid++, nullptr,
0, Vst::ParameterInfo::kCanAutomate, Vst::kRootUnitId));
// MIDI special controllers
parameters.addParameter(Steinberg::String("Aftertouch"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
parameters.addParameter(Steinberg::String("Pitch Bend"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
parameters.addParameter(Steinberg::String("Pitch bend"), nullptr, 0, 0.5, 0, pid++, Vst::kRootUnitId);
// MIDI controllers
for (unsigned i = 0; i < kNumControllerParams; ++i) {
@ -161,6 +173,21 @@ tresult PLUGIN_API SfizzVstController::setParamNormalized(Vst::ParamID tag, Vst:
value = kParamPreloadSizeRange.denormalize(normValue);
break;
}
case kPidScalaRootKey: {
slotI32 = &_state.scalaRootKey;
value = kParamScalaRootKey.denormalize(normValue);
break;
}
case kPidTuningFrequency: {
slotF32 = &_state.tuningFrequency;
value = kParamTuningFrequency.denormalize(normValue);
break;
}
case kPidStretchedTuning: {
slotF32 = &_state.stretchedTuning;
value = kParamStretchedTuning.denormalize(normValue);
break;
}
}
bool update = false;
@ -217,6 +244,9 @@ tresult PLUGIN_API SfizzVstController::setComponentState(IBStream* state)
setParamNormalized(kPidNumVoices, kParamNumVoicesRange.normalize(s.numVoices));
setParamNormalized(kPidOversampling, kParamOversamplingRange.normalize(s.oversamplingLog2));
setParamNormalized(kPidPreloadSize, kParamPreloadSizeRange.normalize(s.preloadSize));
setParamNormalized(kPidScalaRootKey, kParamScalaRootKey.normalize(s.scalaRootKey));
setParamNormalized(kPidTuningFrequency, kParamTuningFrequency.normalize(s.tuningFrequency));
setParamNormalized(kPidStretchedTuning, kParamStretchedTuning.normalize(s.stretchedTuning));
for (StateListener* listener : _stateListeners)
listener->onStateChanged();
@ -224,6 +254,34 @@ tresult PLUGIN_API SfizzVstController::setComponentState(IBStream* state)
return kResultTrue;
}
tresult SfizzVstController::notify(Vst::IMessage* message)
{
tresult result = SfizzVstControllerNoUi::notify(message);
if (result != kResultFalse)
return result;
const char* id = message->getMessageID();
Vst::IAttributeList* attr = message->getAttributes();
if (!strcmp(id, "LoadedSfz")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("File", data, size);
_state.sfzFile.assign(static_cast<const char *>(data), size);
}
else if (!strcmp(id, "LoadedScala")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("File", data, size);
_state.scalaFile.assign(static_cast<const char *>(data), size);
}
for (StateListener* listener : _stateListeners)
listener->onStateChanged();
return result;
}
void SfizzVstController::addSfizzStateListener(StateListener* listener)
{
_stateListeners.push_back(listener);

View file

@ -44,12 +44,14 @@ public:
tresult PLUGIN_API setState(IBStream* state) override;
tresult PLUGIN_API getState(IBStream* state) override;
tresult PLUGIN_API setComponentState(IBStream* state) override;
tresult PLUGIN_API notify(Vst::IMessage* message) override;
struct StateListener {
virtual void onStateChanged() = 0;
};
const SfizzVstState& getSfizzState() const { return _state; }
SfizzVstState& getSfizzState() { return _state; }
const SfizzUiState& getSfizzUiState() const { return _uiState; }
SfizzUiState& getSfizzUiState() { return _uiState; }

View file

@ -86,24 +86,53 @@ void SfizzVstEditor::valueChanged(CControl* ctl)
Call::later([this]() { chooseSfzFile(); });
break;
case kTagLoadScalaFile:
if (value != 1)
break;
Call::later([this]() { chooseScalaFile(); });
break;
case kTagSetVolume:
controller->setParamNormalized(kPidVolume, valueNorm);
controller->performEdit(kPidVolume, valueNorm);
updateVolumeLabel(value);
break;
case kTagSetNumVoices:
controller->setParamNormalized(kPidNumVoices, valueNorm);
controller->performEdit(kPidNumVoices, valueNorm);
updateNumVoicesLabel(static_cast<int>(value));
break;
case kTagSetOversampling:
controller->setParamNormalized(kPidOversampling, valueNorm);
controller->performEdit(kPidOversampling, valueNorm);
updateOversamplingLabel(static_cast<int>(value));
break;
case kTagSetPreloadSize:
controller->setParamNormalized(kPidPreloadSize, valueNorm);
controller->performEdit(kPidPreloadSize, valueNorm);
updatePreloadSizeLabel(static_cast<int>(value));
break;
case kTagSetScalaRootKey:
controller->setParamNormalized(kPidScalaRootKey, valueNorm);
controller->performEdit(kPidScalaRootKey, valueNorm);
updateScalaRootKeyLabel(value);
break;
case kTagSetTuningFrequency:
controller->setParamNormalized(kPidTuningFrequency, valueNorm);
controller->performEdit(kPidTuningFrequency, valueNorm);
updateTuningFrequencyLabel(value);
break;
case kTagSetStretchedTuning:
controller->setParamNormalized(kPidStretchedTuning, valueNorm);
controller->performEdit(kPidStretchedTuning, valueNorm);
updateStretchedTuningLabel(value);
break;
default:
@ -123,6 +152,9 @@ void SfizzVstEditor::enterOrLeaveEdit(CControl* ctl, bool enter)
case kTagSetNumVoices: id = kPidNumVoices; break;
case kTagSetOversampling: id = kPidOversampling; break;
case kTagSetPreloadSize: id = kPidPreloadSize; break;
case kTagSetScalaRootKey: id = kPidScalaRootKey; break;
case kTagSetTuningFrequency: id = kPidTuningFrequency; break;
case kTagSetStretchedTuning: id = kPidStretchedTuning; break;
default: return;
}
@ -191,7 +223,7 @@ void SfizzVstEditor::loadSfzFile(const std::string& filePath)
{
SfizzVstController* ctl = getController();
Vst::IMessage *msg = ctl->allocateMessage();
Steinberg::OPtr<Vst::IMessage> msg { ctl->allocateMessage() };
if (!msg) {
fprintf(stderr, "[Sfizz] UI could not allocate message\n");
return;
@ -201,9 +233,40 @@ void SfizzVstEditor::loadSfzFile(const std::string& filePath)
Vst::IAttributeList* attr = msg->getAttributes();
attr->setBinary("File", filePath.data(), filePath.size());
ctl->sendMessage(msg);
msg->release();
updateFileLabel(filePath);
updateSfzFileLabel(filePath);
}
void SfizzVstEditor::chooseScalaFile()
{
SharedPointer<CNewFileSelector> fs(CNewFileSelector::create(frame));
fs->setTitle("Load Scala file");
fs->setDefaultExtension(CFileExtension("SCL", "scl"));
if (fs->runModal()) {
UTF8StringPtr file = fs->getSelectedFile(0);
if (file)
loadScalaFile(file);
}
}
void SfizzVstEditor::loadScalaFile(const std::string& filePath)
{
SfizzVstController* ctl = getController();
Steinberg::OPtr<Vst::IMessage> msg { ctl->allocateMessage() };
if (!msg) {
fprintf(stderr, "[Sfizz] UI could not allocate message\n");
return;
}
msg->setMessageID("LoadScala");
Vst::IAttributeList* attr = msg->getAttributes();
attr->setBinary("File", filePath.data(), filePath.size());
ctl->sendMessage(msg);
updateScalaFileLabel(filePath);
}
void SfizzVstEditor::createFrameContents()
@ -241,7 +304,7 @@ void SfizzVstEditor::createFrameContents()
topLeftLabel->setFontColor(CColor(0x00, 0x00, 0x00));
topLeftLabel->setBackColor(CColor(0x00, 0x00, 0x00, 0x00));
panel->addView(topLeftLabel);
_fileLabel = topLeftLabel;
_sfzFileLabel = topLeftLabel;
_subPanels[kPanelGeneral] = panel;
}
@ -277,6 +340,13 @@ void SfizzVstEditor::createFrameContents()
return div;
};
auto labelArea = [&topRow, &row]() -> CRect {
CRect div = row;
div.right = topRow.right - 10.0;
div.left = div.right - 100.0 + 20.0;
return div;
};
CTextLabel* label;
SimpleSlider* slider;
@ -290,6 +360,9 @@ void SfizzVstEditor::createFrameContents()
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidVolume);
_volumeSlider = slider;
label = new CTextLabel(labelArea(), "");
_volumeLabel = label;
panel->addView(label);
row.top += interRow;
row.bottom += interRow;
@ -304,6 +377,9 @@ void SfizzVstEditor::createFrameContents()
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidNumVoices);
_numVoicesSlider = slider;
label = new CTextLabel(labelArea(), "");
_numVoicesLabel = label;
panel->addView(label);
row.top += interRow;
row.bottom += interRow;
@ -318,6 +394,9 @@ void SfizzVstEditor::createFrameContents()
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidOversampling);
_oversamplingSlider = slider;
label = new CTextLabel(labelArea(), "");
_oversamplingLabel = label;
panel->addView(label);
row.top += interRow;
row.bottom += interRow;
@ -332,6 +411,9 @@ void SfizzVstEditor::createFrameContents()
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidPreloadSize);
_preloadSizeSlider = slider;
label = new CTextLabel(labelArea(), "");
_preloadSizeLabel = label;
panel->addView(label);
// row.top += interRow;
// row.bottom += interRow;
@ -350,6 +432,114 @@ void SfizzVstEditor::createFrameContents()
_subPanels[kPanelSettings] = panel;
}
// tuning panel
{
panel = new CViewContainer(bounds);
frame->addView(panel);
panel->setTransparency(true);
CTextLabel* topLeftLabel = new CTextLabel(topLeftLabelBox, "Tuning");
topLeftLabel->setFontColor(CColor(0x00, 0x00, 0x00));
topLeftLabel->setBackColor(CColor(0x00, 0x00, 0x00, 0x00));
panel->addView(topLeftLabel);
CRect row = topRow;
row.top += 45.0;
row.bottom += 45.0;
row.left += 100.0;
row.right -= 100.0;
CCoord interRow = 35.0;
auto leftSide = [&row]() -> CRect {
CRect div = row;
div.right = 0.5 * (div.left + div.right);
return div;
};
auto rightSide = [&row]() -> CRect {
CRect div = row;
div.left = 0.5 * (div.left + div.right);
return div;
};
auto labelArea = [&topRow, &row]() -> CRect {
CRect div = row;
div.right = topRow.right - 10.0;
div.left = div.right - 100.0 + 20.0;
return div;
};
CTextLabel* label;
SimpleSlider* slider;
CTextButton* textbutton;
label = new CTextLabel(leftSide(), "Scala file");
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);
textbutton = new CTextButton(rightSide(), this, kTagLoadScalaFile, "Choose");
panel->addView(textbutton);
label = new CTextLabel(labelArea(), "");
_scalaFileLabel = label;
panel->addView(label);
row.top += interRow;
row.bottom += interRow;
label = new CTextLabel(leftSide(), "Scala root key");
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, kTagSetScalaRootKey);
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidScalaRootKey);
_scalaRootKeySlider = slider;
label = new CTextLabel(labelArea(), "");
_scalaRootKeyLabel = label;
panel->addView(label);
row.top += interRow;
row.bottom += interRow;
label = new CTextLabel(leftSide(), "Tuning frequency");
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, kTagSetTuningFrequency);
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidTuningFrequency);
_tuningFrequencySlider = slider;
label = new CTextLabel(labelArea(), "");
_tuningFrequencyLabel = label;
panel->addView(label);
row.top += interRow;
row.bottom += interRow;
label = new CTextLabel(leftSide(), "Stretched tuning");
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, kTagSetStretchedTuning);
panel->addView(slider);
adjustMinMaxToRangeParam(slider, kPidStretchedTuning);
_stretchedTuningSlider = slider;
label = new CTextLabel(labelArea(), "");
_stretchedTuningLabel = label;
panel->addView(label);
_subPanels[kPanelTuning] = panel;
}
// all panels
for (unsigned currentPanel = 0; currentPanel < kNumPanels; ++currentPanel) {
panel = _subPanels[currentPanel];
@ -369,6 +559,7 @@ void SfizzVstEditor::createFrameContents()
switch (i) {
case kPanelGeneral: text = "File"; break;
case kPanelSettings: text = "Setup"; break;
case kPanelTuning: text = "Tuning"; break;
default: text = "?"; break;
}
@ -391,38 +582,164 @@ void SfizzVstEditor::updateStateDisplay()
const SfizzVstState& state = controller->getSfizzState();
const SfizzUiState& uiState = controller->getSfizzUiState();
updateFileLabel(state.sfzFile);
updateSfzFileLabel(state.sfzFile);
if (_volumeSlider)
_volumeSlider->setValue(state.volume);
updateVolumeLabel(state.volume);
if (_numVoicesSlider)
_numVoicesSlider->setValue(state.numVoices);
updateNumVoicesLabel(state.numVoices);
if (_oversamplingSlider)
_oversamplingSlider->setValue(state.oversamplingLog2);
updateOversamplingLabel(state.oversamplingLog2);
if (_preloadSizeSlider)
_preloadSizeSlider->setValue(state.preloadSize);
updatePreloadSizeLabel(state.preloadSize);
updateScalaFileLabel(state.scalaFile);
if (_scalaRootKeySlider)
_scalaRootKeySlider->setValue(state.scalaRootKey);
updateScalaRootKeyLabel(state.scalaRootKey);
if (_tuningFrequencySlider)
_tuningFrequencySlider->setValue(state.tuningFrequency);
updateTuningFrequencyLabel(state.tuningFrequency);
if (_stretchedTuningSlider)
_stretchedTuningSlider->setValue(state.stretchedTuning);
updateStretchedTuningLabel(state.stretchedTuning);
setActivePanel(uiState.activePanel);
}
void SfizzVstEditor::updateFileLabel(const std::string& filePath)
void SfizzVstEditor::updateSfzFileLabel(const std::string& filePath)
{
if (_fileLabel) {
std::string fileName;
if (filePath.empty())
fileName = "<No file>";
else {
#if defined (_WIN32)
size_t pos = filePath.find_last_of("/\\");
#else
size_t pos = filePath.rfind('/');
#endif
fileName = (pos != filePath.npos) ?
filePath.substr(pos + 1) : filePath;
}
_fileLabel->setText(fileName.c_str());
}
updateLabelWithFileName(_sfzFileLabel, filePath);
}
void SfizzVstEditor::updateScalaFileLabel(const std::string& filePath)
{
updateLabelWithFileName(_scalaFileLabel, filePath);
}
void SfizzVstEditor::updateLabelWithFileName(CTextLabel* label, const std::string& filePath)
{
if (!label)
return;
std::string fileName;
if (filePath.empty())
fileName = "<No file>";
else {
#if defined (_WIN32)
size_t pos = filePath.find_last_of("/\\");
#else
size_t pos = filePath.rfind('/');
#endif
fileName = (pos != filePath.npos) ?
filePath.substr(pos + 1) : filePath;
}
label->setText(fileName.c_str());
}
void SfizzVstEditor::updateVolumeLabel(float volume)
{
CTextLabel* label = _volumeLabel;
if (!label)
return;
char text[64];
sprintf(text, "%.1f dB", volume);
text[sizeof(text) - 1] = '\0';
label->setText(text);
}
void SfizzVstEditor::updateNumVoicesLabel(int numVoices)
{
CTextLabel* label = _numVoicesLabel;
if (!label)
return;
char text[64];
sprintf(text, "%d", numVoices);
text[sizeof(text) - 1] = '\0';
label->setText(text);
}
void SfizzVstEditor::updateOversamplingLabel(int oversamplingLog2)
{
CTextLabel* label = _oversamplingLabel;
if (!label)
return;
char text[64];
sprintf(text, "%dx", 1 << oversamplingLog2);
text[sizeof(text) - 1] = '\0';
label->setText(text);
}
void SfizzVstEditor::updatePreloadSizeLabel(int preloadSize)
{
CTextLabel* label = _preloadSizeLabel;
if (!label)
return;
char text[64];
sprintf(text, "%.1f kB", preloadSize * (1.0 / 1024));
text[sizeof(text) - 1] = '\0';
label->setText(text);
}
void SfizzVstEditor::updateScalaRootKeyLabel(int rootKey)
{
CTextLabel* label = _scalaRootKeyLabel;
if (!label)
return;
static const char *octNoteNames[12] = {
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
};
auto noteName = [](int key) -> std::string
{
int octNum;
int octNoteNum;
if (key >= 0) {
octNum = key / 12 - 1;
octNoteNum = key % 12;
}
else {
octNum = -2 - (key + 1) / -12;
octNoteNum = (key % 12 + 12) % 12;
}
return std::string(octNoteNames[octNoteNum]) + std::to_string(octNum);
};
label->setText(noteName(rootKey));
}
void SfizzVstEditor::updateTuningFrequencyLabel(float tuningFrequency)
{
CTextLabel* label = _tuningFrequencyLabel;
if (!label)
return;
char text[64];
sprintf(text, "%.1f", tuningFrequency);
text[sizeof(text) - 1] = '\0';
label->setText(text);
}
void SfizzVstEditor::updateStretchedTuningLabel(float stretchedTuning)
{
CTextLabel* label = _stretchedTuningLabel;
if (!label)
return;
char text[64];
sprintf(text, "%.3f", stretchedTuning);
text[sizeof(text) - 1] = '\0';
label->setText(text);
}
void SfizzVstEditor::setActivePanel(unsigned panelId)
{
panelId = std::max(0, std::min(kNumPanels - 1, static_cast<int>(panelId)));

View file

@ -43,9 +43,21 @@ private:
void chooseSfzFile();
void loadSfzFile(const std::string& filePath);
void chooseScalaFile();
void loadScalaFile(const std::string& filePath);
void createFrameContents();
void updateStateDisplay();
void updateFileLabel(const std::string& filePath);
void updateSfzFileLabel(const std::string& filePath);
void updateScalaFileLabel(const std::string& filePath);
static void updateLabelWithFileName(CTextLabel* label, const std::string& filePath);
void updateVolumeLabel(float volume);
void updateNumVoicesLabel(int numVoices);
void updateOversamplingLabel(int oversamplingLog2);
void updatePreloadSizeLabel(int preloadSize);
void updateScalaRootKeyLabel(int rootKey);
void updateTuningFrequencyLabel(float tuningFrequency);
void updateStretchedTuningLabel(float stretchedTuning);
void setActivePanel(unsigned panelId);
template <class Control>
@ -60,6 +72,7 @@ private:
kPanelGeneral,
// kPanelControls,
kPanelSettings,
kPanelTuning,
kNumPanels,
};
@ -72,16 +85,31 @@ private:
kTagSetNumVoices,
kTagSetOversampling,
kTagSetPreloadSize,
kTagLoadScalaFile,
kTagSetScalaRootKey,
kTagSetTuningFrequency,
kTagSetStretchedTuning,
kTagFirstChangePanel,
kTagLastChangePanel = kTagFirstChangePanel + kNumPanels - 1,
};
CBitmap _logo;
CTextLabel* _fileLabel = nullptr;
CTextLabel* _sfzFileLabel = nullptr;
CTextLabel* _scalaFileLabel = nullptr;
CSliderBase *_volumeSlider = nullptr;
CTextLabel* _volumeLabel = nullptr;
CSliderBase *_numVoicesSlider = nullptr;
CTextLabel* _numVoicesLabel = nullptr;
CSliderBase *_oversamplingSlider = nullptr;
CTextLabel* _oversamplingLabel = nullptr;
CSliderBase *_preloadSizeSlider = nullptr;
CTextLabel* _preloadSizeLabel = nullptr;
CSliderBase *_scalaRootKeySlider = nullptr;
CTextLabel* _scalaRootKeyLabel = nullptr;
CSliderBase *_tuningFrequencySlider = nullptr;
CTextLabel* _tuningFrequencyLabel = nullptr;
CSliderBase *_stretchedTuningSlider = nullptr;
CTextLabel* _stretchedTuningLabel = nullptr;
#if !defined(__APPLE__) && !defined(_WIN32)
SharedPointer<RunLoop> _runLoop;

View file

@ -52,6 +52,7 @@ tresult PLUGIN_API SfizzVstProcessor::initialize(FUnknown* context)
fprintf(stderr, "[sfizz] new synth\n");
_synth.reset(new sfz::Sfizz);
_currentStretchedTuning = 0.0;
loadSfzFileOrDefault(*_synth, {});
return result;
@ -101,6 +102,10 @@ void SfizzVstProcessor::syncStateToSynth()
synth->setNumVoices(_state.numVoices);
synth->setOversamplingFactor(1 << _state.oversamplingLog2);
synth->setPreloadSize(_state.preloadSize);
synth->loadScalaFile(_state.scalaFile);
synth->setScalaRootKey(_state.scalaRootKey);
synth->setTuningFrequency(_state.tuningFrequency);
synth->loadStretchTuningByRatio(_state.stretchedTuning);
}
tresult PLUGIN_API SfizzVstProcessor::canProcessSampleSize(int32 symbolicSampleSize)
@ -174,6 +179,12 @@ tresult PLUGIN_API SfizzVstProcessor::process(Vst::ProcessData& data)
processEvents(*events);
synth.setVolume(_state.volume);
synth.setScalaRootKey(_state.scalaRootKey);
synth.setTuningFrequency(_state.tuningFrequency);
if (_currentStretchedTuning != _state.stretchedTuning) {
synth.loadStretchTuningByRatio(_state.stretchedTuning);
_currentStretchedTuning = _state.stretchedTuning;
}
synth.renderBlock(outputs, numFrames, numChannels);
@ -230,6 +241,18 @@ void SfizzVstProcessor::processParameterChanges(Vst::IParameterChanges& pc)
_semaToWorker.post();
}
break;
case kPidScalaRootKey:
if (pointCount > 0 && vq->getPoint(pointCount - 1, sampleOffset, value) == kResultTrue)
_state.scalaRootKey = static_cast<int32>(kParamScalaRootKey.denormalize(value));
break;
case kPidTuningFrequency:
if (pointCount > 0 && vq->getPoint(pointCount - 1, sampleOffset, value) == kResultTrue)
_state.tuningFrequency = kParamTuningFrequency.denormalize(value);
break;
case kPidStretchedTuning:
if (pointCount > 0 && vq->getPoint(pointCount - 1, sampleOffset, value) == kResultTrue)
_state.stretchedTuning = kParamStretchedTuning.denormalize(value);
break;
}
}
}
@ -328,9 +351,33 @@ tresult PLUGIN_API SfizzVstProcessor::notify(Vst::IMessage* message)
if (result != kResultTrue)
return result;
std::lock_guard<std::mutex> lock(_processMutex);
std::unique_lock<std::mutex> lock(_processMutex);
_state.sfzFile.assign(static_cast<const char *>(data), size);
loadSfzFileOrDefault(*_synth, _state.sfzFile);
lock.unlock();
Steinberg::OPtr<Vst::IMessage> reply { allocateMessage() };
reply->setMessageID("LoadedSfz");
reply->getAttributes()->setBinary("File", _state.sfzFile.data(), _state.sfzFile.size());
sendMessage(reply);
}
else if (!std::strcmp(id, "LoadScala")) {
const void* data = nullptr;
uint32 size = 0;
result = attr->getBinary("File", data, size);
if (result != kResultTrue)
return result;
std::unique_lock<std::mutex> lock(_processMutex);
_state.scalaFile.assign(static_cast<const char *>(data), size);
_synth->loadScalaFile(_state.scalaFile);
lock.unlock();
Steinberg::OPtr<Vst::IMessage> reply { allocateMessage() };
reply->setMessageID("LoadedScala");
reply->getAttributes()->setBinary("File", _state.scalaFile.data(), _state.scalaFile.size());
sendMessage(reply);
}
return result;
@ -379,9 +426,13 @@ void SfizzVstProcessor::doBackgroundWork()
}
else if (!std::strcmp(id, "CheckShouldReload")) {
if (_synth->shouldReloadFile()) {
fprintf(stderr, "[Sfizz] file has changed, reloading\n");
fprintf(stderr, "[Sfizz] sfz file has changed, reloading\n");
loadSfzFileOrDefault(*_synth, _state.sfzFile);
}
else if (_synth->shouldReloadScala()) {
fprintf(stderr, "[Sfizz] scala file has changed, reloading\n");
_synth->loadScalaFile(_state.scalaFile);
}
}
}
}

View file

@ -48,6 +48,7 @@ private:
// synth state. acquire processMutex before accessing
std::unique_ptr<sfz::Sfizz> _synth;
SfizzVstState _state;
float _currentStretchedTuning = 0;
// misc
static void loadSfzFileOrDefault(sfz::Sfizz& synth, const std::string& filePath);

View file

@ -34,6 +34,33 @@ tresult SfizzVstState::load(IBStream* state)
if (!s.readInt32(preloadSize))
return kResultFalse;
const SfizzVstState defaults;
if (version >= 1) {
if (const char* str = s.readStr8())
scalaFile = str;
else
return kResultFalse;
if (!s.readInt32(scalaRootKey))
return kResultFalse;
if (!s.readFloat(tuningFrequency))
return kResultFalse;
if (!s.readFloat(stretchedTuning))
return kResultFalse;
}
else {
scalaFile = defaults.scalaFile;
scalaRootKey = defaults.scalaRootKey;
tuningFrequency = defaults.tuningFrequency;
stretchedTuning = defaults.stretchedTuning;
}
if (version > 1)
return kResultFalse;
return kResultTrue;
}
@ -59,9 +86,23 @@ tresult SfizzVstState::store(IBStream* state) const
if (!s.writeInt32(preloadSize))
return kResultFalse;
if (!s.writeStr8(scalaFile.c_str()))
return kResultFalse;
if (!s.writeInt32(scalaRootKey))
return kResultFalse;
if (!s.writeFloat(tuningFrequency))
return kResultFalse;
if (!s.writeFloat(stretchedTuning))
return kResultFalse;
return kResultTrue;
}
constexpr uint64 SfizzVstState::currentStateVersion;
tresult SfizzUiState::load(IBStream* state)
{
IBStreamer s(state, kLittleEndian);
@ -73,6 +114,9 @@ tresult SfizzUiState::load(IBStream* state)
if (!s.readInt32u(activePanel))
return kResultFalse;
if (version > 0)
return kResultFalse;
return kResultTrue;
}
@ -88,3 +132,5 @@ tresult SfizzUiState::store(IBStream* state) const
return kResultTrue;
}
constexpr uint64 SfizzUiState::currentStateVersion;

View file

@ -22,6 +22,9 @@ enum {
kPidNumVoices,
kPidOversampling,
kPidPreloadSize,
kPidScalaRootKey,
kPidTuningFrequency,
kPidStretchedTuning,
kPidMidiAftertouch,
kPidMidiPitchBend,
kPidMidiCC0,
@ -31,15 +34,19 @@ enum {
class SfizzVstState {
public:
SfizzVstState() { sfzFile.reserve(8192); }
SfizzVstState() { sfzFile.reserve(8192); scalaFile.reserve(8192); }
std::string sfzFile;
float volume = 0;
int32 numVoices = 64;
int32 oversamplingLog2 = 0;
int32 preloadSize = 8192;
std::string scalaFile;
int32 scalaRootKey = 60;
float tuningFrequency = 440.0;
float stretchedTuning = 0.0;
static constexpr uint64 currentStateVersion = 0;
static constexpr uint64 currentStateVersion = 1;
tresult load(IBStream* state);
tresult store(IBStream* state) const;
@ -83,3 +90,6 @@ static constexpr SfizzParameterRange kParamVolumeRange(0.0, -60.0, +6.0);
static constexpr SfizzParameterRange kParamNumVoicesRange(256.0, 1.0, 512.0);
static constexpr SfizzParameterRange kParamOversamplingRange(0.0, 0.0, 3.0);
static constexpr SfizzParameterRange kParamPreloadSizeRange(8192.0, 1024.0, 65536.0);
static constexpr SfizzParameterRange kParamScalaRootKey(60.0, 0.0, 127.0);
static constexpr SfizzParameterRange kParamTuningFrequency(440.0, 300.0, 500.0);
static constexpr SfizzParameterRange kParamStretchedTuning(0.0, 0.0, 1.0);