MIDI plugins -- partial implemetnation, temporarily disabled.
This commit is contained in:
+3
-2
@@ -1862,8 +1862,9 @@ public:
|
||||
VuUpdate v;
|
||||
v.instanceId_ = instanceId;
|
||||
// Display mono VUs if a stereo device is being fed identical L/R inputs.
|
||||
v.isStereoInput_ = effect->GetNumberOfInputAudioPorts() != 1 && effect->GetAudioInputBuffer(0) != effect->GetAudioInputBuffer(1);
|
||||
v.isStereoOutput_ = effect->GetNumberOfOutputAudioPorts() != 1;
|
||||
v.isStereoInput_ = effect->GetNumberOfInputAudioBuffers() >= 2
|
||||
&& effect->GetAudioInputBuffer(0) != effect->GetAudioInputBuffer(1);
|
||||
v.isStereoOutput_ = effect->GetNumberOfOutputAudioBuffers() >= 2;
|
||||
|
||||
vuConfig->vuUpdateWorkingData.push_back(v);
|
||||
vuConfig->vuUpdateResponseData.push_back(v);
|
||||
|
||||
+4
-1
@@ -41,7 +41,7 @@ namespace macaron
|
||||
public:
|
||||
static std::string Encode(const std::vector<uint8_t> &data)
|
||||
{
|
||||
return Encode(data.size(),&(data[0]));
|
||||
return Encode(data.size(),data.data());
|
||||
}
|
||||
static std::string Encode(size_t size, const uint8_t *data)
|
||||
{
|
||||
@@ -112,6 +112,9 @@ namespace macaron
|
||||
if (in_len % 4 != 0)
|
||||
throw std::invalid_argument("Input data size is not a multiple of 4");
|
||||
|
||||
if (in_len < 4) {
|
||||
return std::vector<uint8_t>();
|
||||
}
|
||||
size_t out_len = in_len / 4 * 3;
|
||||
if (input[in_len - 1] == '=')
|
||||
out_len--;
|
||||
|
||||
+5
-2
@@ -49,8 +49,11 @@ namespace pipedal {
|
||||
virtual void SetBypass(bool enable) = 0;
|
||||
virtual float GetOutputControlValue(int controlIndex) const = 0;
|
||||
|
||||
virtual int GetNumberOfInputAudioPorts() const = 0;
|
||||
virtual int GetNumberOfOutputAudioPorts() const = 0;
|
||||
virtual int GetNumberOfInputAudioPorts() const = 0; // as declared
|
||||
virtual int GetNumberOfOutputAudioPorts() const = 0; // as declared.
|
||||
|
||||
virtual int GetNumberOfInputAudioBuffers() const = 0; // may be different if plugin has zero inputs.
|
||||
virtual int GetNumberOfOutputAudioBuffers() const = 0; // may be different if plugin has zero inputs.
|
||||
virtual float *GetAudioInputBuffer(int index) const = 0;
|
||||
virtual float *GetAudioOutputBuffer(int index) const = 0;
|
||||
virtual void ResetAtomBuffers() = 0;
|
||||
|
||||
+4
-4
@@ -414,12 +414,12 @@ void Lv2Effect::SetAudioInputBuffer(int index, float *buffer)
|
||||
|
||||
void Lv2Effect::SetAudioInputBuffer(float *left)
|
||||
{
|
||||
if (GetNumberOfInputAudioPorts() > 1)
|
||||
if (GetNumberOfInputAudioBuffers() > 1)
|
||||
{
|
||||
SetAudioInputBuffer(0, left);
|
||||
SetAudioInputBuffer(1, left);
|
||||
}
|
||||
else if (GetNumberOfInputAudioPorts() != 0) /// yyx MIXING!
|
||||
else if (GetNumberOfInputAudioBuffers() != 0)
|
||||
{
|
||||
SetAudioInputBuffer(0, left);
|
||||
}
|
||||
@@ -427,11 +427,11 @@ void Lv2Effect::SetAudioInputBuffer(float *left)
|
||||
|
||||
void Lv2Effect::SetAudioInputBuffers(float *left, float *right)
|
||||
{
|
||||
if (GetNumberOfInputAudioPorts() == 1)
|
||||
if (GetNumberOfInputAudioBuffers() == 1)
|
||||
{
|
||||
SetAudioInputBuffer(0, left);
|
||||
}
|
||||
else if (GetNumberOfInputAudioPorts() > 1)
|
||||
else if (GetNumberOfInputAudioBuffers() > 1)
|
||||
{
|
||||
SetAudioInputBuffer(0, left);
|
||||
SetAudioInputBuffer(1, right);
|
||||
|
||||
@@ -252,16 +252,22 @@ namespace pipedal
|
||||
virtual uint64_t GetInstanceId() const { return instanceId; }
|
||||
virtual int GetNumberOfInputAudioPorts() const { return inputAudioPortIndices.size(); }
|
||||
virtual int GetNumberOfOutputAudioPorts() const { return outputAudioPortIndices.size(); }
|
||||
|
||||
virtual int GetNumberOfInputAtomPorts() const { return inputAtomPortIndices.size(); }
|
||||
|
||||
virtual int GetNumberOfOutputAtomPorts() const { return outputAtomPortIndices.size(); }
|
||||
virtual int GetNumberOfMidiInputPorts() const { return inputMidiPortIndices.size(); }
|
||||
virtual int GetNumberOfMidiOutputPorts() const { return outputMidiPortIndices.size(); }
|
||||
|
||||
|
||||
|
||||
virtual int GetNumberOfInputAudioBuffers() const { return this->inputAudioBuffers.size(); }
|
||||
virtual int GetNumberOfOutputAudioBuffers() const {return this->outputAudioBuffers.size(); }
|
||||
|
||||
virtual void SetAudioInputBuffer(int index, float *buffer);
|
||||
virtual float *GetAudioInputBuffer(int index) const { return this->inputAudioBuffers[index]; }
|
||||
|
||||
|
||||
virtual void SetAudioInputBuffer(float *buffer);
|
||||
virtual void SetAudioInputBuffers(float *left, float *right);
|
||||
|
||||
|
||||
+10
-32
@@ -136,11 +136,11 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
|
||||
if (inputBuffers.size() == 1)
|
||||
{
|
||||
if (pLv2Effect->GetNumberOfInputAudioPorts() == 1)
|
||||
if (pLv2Effect->GetNumberOfInputAudioBuffers() == 1)
|
||||
{
|
||||
pLv2Effect->SetAudioInputBuffer(0, inputBuffers[0]);
|
||||
}
|
||||
else
|
||||
else if (pLv2Effect->GetNumberOfInputAudioBuffers() >= 2)
|
||||
{
|
||||
pLv2Effect->SetAudioInputBuffer(0, inputBuffers[0]);
|
||||
pLv2Effect->SetAudioInputBuffer(1, inputBuffers[0]);
|
||||
@@ -148,13 +148,13 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pLv2Effect->GetNumberOfInputAudioPorts() == 1)
|
||||
if (pLv2Effect->GetNumberOfInputAudioBuffers() == 1)
|
||||
{
|
||||
pLv2Effect->SetAudioInputBuffer(0, inputBuffers[0]);
|
||||
|
||||
auto inputBuffer = inputBuffers[0];
|
||||
}
|
||||
else
|
||||
else if (pLv2Effect->GetNumberOfInputAudioBuffers() >= 2)
|
||||
{
|
||||
pLv2Effect->SetAudioInputBuffer(0, inputBuffers[0]);
|
||||
pLv2Effect->SetAudioInputBuffer(1, inputBuffers[1]);
|
||||
@@ -178,37 +178,15 @@ std::vector<float *> Lv2Pedalboard::PrepareItems(
|
||||
|
||||
std::vector<float *> effectOutput;
|
||||
|
||||
#ifdef RECYCLE_AUDIO_BUFFERS
|
||||
// can't do this anymore if we're going to do pop-less bypbass.
|
||||
if (pEffect->GetNumberOfOutputAudioPorts() == 1)
|
||||
{
|
||||
float *pLeft = inputBuffers[0];
|
||||
effectOutput.push_back(pLeft);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (inputBuffers.size() == 1)
|
||||
{
|
||||
effectOutput.push_back(inputBuffers[0]);
|
||||
effectOutput.push_back(CreateNewAudioBuffer());
|
||||
}
|
||||
else
|
||||
{
|
||||
effectOutput.push_back(inputBuffers[0]);
|
||||
effectOutput.push_back(inputBuffers[1]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (pEffect->GetNumberOfOutputAudioPorts() == 1)
|
||||
if (pEffect->GetNumberOfOutputAudioBuffers() == 1)
|
||||
{
|
||||
effectOutput.push_back(CreateNewAudioBuffer());
|
||||
}
|
||||
else
|
||||
else if (pEffect->GetNumberOfOutputAudioBuffers() >= 2)
|
||||
{
|
||||
effectOutput.push_back(CreateNewAudioBuffer());
|
||||
effectOutput.push_back(CreateNewAudioBuffer());
|
||||
}
|
||||
#endif
|
||||
for (size_t i = 0; i < effectOutput.size(); ++i)
|
||||
{
|
||||
pEffect->SetAudioOutputBuffer(i, effectOutput[i]);
|
||||
@@ -475,21 +453,21 @@ void Lv2Pedalboard::ComputeVus(RealtimeVuBuffers *vuConfiguration, uint32_t samp
|
||||
{
|
||||
auto effect = this->realtimeEffects[index];
|
||||
|
||||
if (effect->GetNumberOfInputAudioPorts() == 1)
|
||||
if (effect->GetNumberOfInputAudioBuffers() == 1)
|
||||
{
|
||||
pUpdate->AccumulateInputs(effect->GetAudioInputBuffer(0), samples);
|
||||
}
|
||||
else
|
||||
else if (effect->GetNumberOfInputAudioBuffers() >= 2)
|
||||
{
|
||||
pUpdate->AccumulateInputs(
|
||||
effect->GetAudioInputBuffer(0),
|
||||
effect->GetAudioInputBuffer(1), samples);
|
||||
}
|
||||
if (effect->GetNumberOfOutputAudioPorts() == 1)
|
||||
if (effect->GetNumberOfOutputAudioBuffers() == 1)
|
||||
{
|
||||
pUpdate->AccumulateOutputs(effect->GetAudioOutputBuffer(0), samples);
|
||||
}
|
||||
else
|
||||
else if (effect->GetNumberOfOutputAudioBuffers() >= 2)
|
||||
{
|
||||
pUpdate->AccumulateOutputs(
|
||||
effect->GetAudioOutputBuffer(0),
|
||||
|
||||
+30
-1
@@ -17,12 +17,41 @@
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "pch.h"
|
||||
#include "MidiBinding.hpp"
|
||||
#include "MapFeature.hpp"
|
||||
|
||||
|
||||
using namespace pipedal;
|
||||
|
||||
MidiChannelBinding MidiChannelBinding::DefaultForMissingValue()
|
||||
{
|
||||
MidiChannelBinding result {};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void MidiChannelBinding::Prepare(MapFeature &mapFeature)
|
||||
{
|
||||
midiDeviceUrids.resize(0);
|
||||
midiDeviceUrids.reserve(midiDevices_.size());
|
||||
|
||||
for (const auto&midiDevice: midiDevices_)
|
||||
{
|
||||
midiDeviceUrids.push_back(mapFeature.GetUrid(midiDevice.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(MidiChannelBinding)
|
||||
JSON_MAP_REFERENCE(MidiChannelBinding,deviceSelection)
|
||||
JSON_MAP_REFERENCE(MidiChannelBinding,midiDevices)
|
||||
JSON_MAP_REFERENCE(MidiChannelBinding,channel)
|
||||
JSON_MAP_REFERENCE(MidiChannelBinding,acceptProgramChanges)
|
||||
JSON_MAP_REFERENCE(MidiChannelBinding,acceptCommonMessages)
|
||||
JSON_MAP_END()
|
||||
|
||||
|
||||
JSON_MAP_BEGIN(MidiBinding)
|
||||
JSON_MAP_REFERENCE(MidiBinding,channel)
|
||||
JSON_MAP_REFERENCE(MidiBinding,symbol)
|
||||
|
||||
@@ -20,10 +20,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "json.hpp"
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <lv2/urid/urid.h>
|
||||
|
||||
|
||||
|
||||
namespace pipedal {
|
||||
|
||||
class MapFeature;
|
||||
|
||||
#define GETTER_SETTER_REF(name) \
|
||||
const decltype(name##_)& name() const { return name##_;} \
|
||||
@@ -33,6 +39,9 @@ namespace pipedal {
|
||||
decltype(name##_)& name() { return name##_;} \
|
||||
const decltype(name##_)& name() const { return name##_;}
|
||||
|
||||
//void name(decltype(const name##_) &value) { name##_ = value; }
|
||||
//void name(decltype(const name##_) &&value) { name##_ = std::move(value); }
|
||||
|
||||
|
||||
|
||||
#define GETTER_SETTER(name) \
|
||||
@@ -102,6 +111,85 @@ public:
|
||||
|
||||
};
|
||||
|
||||
|
||||
enum class MidiDeviceSelection {
|
||||
DeviceAny = 0,
|
||||
DeviceNone = 1,
|
||||
DeviceList = 2
|
||||
};
|
||||
|
||||
class MidiChannelBinding {
|
||||
public:
|
||||
static constexpr std::int32_t CHANNEL_OMNI = -1;
|
||||
private:
|
||||
int32_t deviceSelection_ = (int32_t)(MidiDeviceSelection::DeviceAny);
|
||||
|
||||
std::vector<std::string> midiDevices_;
|
||||
|
||||
std::vector<LV2_URID> midiDeviceUrids;
|
||||
|
||||
std::int32_t channel_ = CHANNEL_OMNI;
|
||||
bool acceptProgramChanges_ = true;
|
||||
bool acceptCommonMessages_ = true;
|
||||
public:
|
||||
MidiDeviceSelection deviceSelection() const { return (MidiDeviceSelection)deviceSelection_; }
|
||||
void deviceSelection(MidiDeviceSelection value) { deviceSelection_ = (int32_t)value; }
|
||||
GETTER_SETTER_VEC(midiDevices);
|
||||
GETTER_SETTER(channel);
|
||||
GETTER_SETTER(acceptProgramChanges);
|
||||
GETTER_SETTER(acceptCommonMessages);
|
||||
|
||||
void Prepare(MapFeature &mapFeature);
|
||||
|
||||
static MidiChannelBinding DefaultForMissingValue();
|
||||
|
||||
bool WantsMidiMessage(uint8_t midi_cc0,uint8_t midi_cc1, uint8_t midi_cc2);
|
||||
bool WantProgramChange(uint8_t midi_cc0,uint8_t midi_cc1);
|
||||
|
||||
// must call Prepare first.
|
||||
bool WantsDevice(LV2_URID deviceUrid);
|
||||
|
||||
|
||||
DECLARE_JSON_MAP(MidiChannelBinding);
|
||||
|
||||
};
|
||||
///////////////////////////////////////
|
||||
|
||||
inline bool MidiChannelBinding::WantsMidiMessage(uint8_t midi_cc0,uint8_t midi_cc1, uint8_t midi_cc2)
|
||||
{
|
||||
if (midi_cc0 < 0xF0)
|
||||
{
|
||||
if (channel_ < 0) return true;
|
||||
|
||||
return midi_cc0 & 0x0F == channel_;
|
||||
} else {
|
||||
return acceptCommonMessages_;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool MidiChannelBinding::WantProgramChange(uint8_t midi_cc0,uint8_t midi_cc1)
|
||||
{
|
||||
if (!acceptProgramChanges_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (channel_ < 0) return true;
|
||||
return midi_cc0 & 0x0F == channel_;
|
||||
}
|
||||
|
||||
inline bool MidiChannelBinding::WantsDevice(LV2_URID deviceUrid)
|
||||
{
|
||||
if (this->midiDeviceUrids.size() == 0) return true;
|
||||
for (LV2_URID urid: midiDeviceUrids)
|
||||
{
|
||||
if (urid == deviceUrid) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
|
||||
|
||||
#undef GETTER_SETTER_REF
|
||||
#undef GETTER_SETTER_VEC
|
||||
#undef GETTER_SETTER
|
||||
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
std::vector<PedalboardItem> topChain_;
|
||||
std::vector<PedalboardItem> bottomChain_;
|
||||
std::vector<MidiBinding> midiBindings_;
|
||||
std::optional<MidiChannelBinding> midiChannelBinding_;
|
||||
std::string vstState_;
|
||||
uint32_t stateUpdateCount_ = 0;
|
||||
Lv2PluginState lv2State_;
|
||||
@@ -122,6 +123,7 @@ public:
|
||||
GETTER_SETTER_VEC(topChain)
|
||||
GETTER_SETTER_VEC(bottomChain)
|
||||
GETTER_SETTER_VEC(midiBindings)
|
||||
GETTER_SETTER_REF(midiChannelBinding)
|
||||
GETTER_SETTER(stateUpdateCount)
|
||||
GETTER_SETTER_REF(lv2State)
|
||||
Lv2PluginState&lv2State() { return lv2State_; } // non-const version.
|
||||
|
||||
@@ -1876,6 +1876,18 @@ void PiPedalModel::UpdateDefaults(PedalboardItem *pedalboardItem, std::unordered
|
||||
}
|
||||
if (pPlugin)
|
||||
{
|
||||
if (pPlugin->hasMidiInput())
|
||||
{
|
||||
if (!pedalboardItem->midiChannelBinding())
|
||||
{
|
||||
pedalboardItem->midiChannelBinding(MidiChannelBinding::DefaultForMissingValue());
|
||||
}
|
||||
} else {
|
||||
if (pedalboardItem->midiChannelBinding())
|
||||
{
|
||||
pedalboardItem->midiChannelBinding(std::optional<MidiChannelBinding>()); // clear it.
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < pPlugin->ports().size(); ++i)
|
||||
{
|
||||
auto port = pPlugin->ports()[i];
|
||||
|
||||
+4
-3
@@ -495,6 +495,10 @@ void PluginHost::Load(const char *lv2Path)
|
||||
{
|
||||
Lv2Log::debug("Plugin %s (%s) skipped. No audio i/o.", plugin->name().c_str(), plugin->uri().c_str());
|
||||
|
||||
} else if (info.audio_inputs() == 0)
|
||||
{
|
||||
// temporarily disable this feature.
|
||||
Lv2Log::debug("Plugin %s (%s) skipped. No inputs.", plugin->name().c_str(), plugin->uri().c_str());
|
||||
}
|
||||
#elif SUPPORT_MIDI
|
||||
if (info.audio_inputs() == 0 && !info.has_midi_input())
|
||||
@@ -520,9 +524,6 @@ void PluginHost::Load(const char *lv2Path)
|
||||
if (info.audio_inputs() == 0) {
|
||||
Lv2Log::debug("************* ZERO INPUTS: %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
|
||||
}
|
||||
if (info.audio_outputs() == 0) {
|
||||
Lv2Log::debug("************* ZERO OUTPUTS: %s (%s) skipped. No audio outputs.", plugin->name().c_str(), plugin->uri().c_str());
|
||||
}
|
||||
ui_plugins_.push_back(std::move(info));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,6 +432,7 @@ namespace pipedal
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool hasMidiOutput() const
|
||||
{
|
||||
|
||||
@@ -381,10 +381,15 @@ namespace pipedal
|
||||
{
|
||||
return (int)this->inputs.size();
|
||||
}
|
||||
virtual int GetNumberOfInputAudioBuffers() const { return this->inputs.size(); }
|
||||
|
||||
virtual float *GetAudioInputBuffer(int index) const
|
||||
{
|
||||
return inputs[index];
|
||||
}
|
||||
|
||||
virtual int GetNumberOfOutputAudioBuffers() const {return this->outputBuffers.size(); }
|
||||
|
||||
virtual float *GetAudioOutputBuffer(int index) const
|
||||
{
|
||||
return this->outputBuffers[index];
|
||||
|
||||
@@ -199,7 +199,7 @@ const void *StateInterface::StateRetrieveFunction(
|
||||
*size = entry.value_.size();
|
||||
*type = map.GetUrid(entry.atomType_.c_str());
|
||||
*flags = entry.flags_;
|
||||
return (void*)&entry.value_[0];
|
||||
return entry.value_.data();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -126,8 +126,21 @@ namespace pipedal
|
||||
{
|
||||
return info.pluginInfo_.audio_outputs();
|
||||
}
|
||||
|
||||
virtual int GetNumberOfInputAudioBuffers() const { return buffers.inputs.size(); }
|
||||
virtual int GetNumberOfOutputAudioPorts() const {return buffers.outputs.size(); }
|
||||
|
||||
virtual float *GetAudioInputBuffer(int index) const { return buffers.inputs[index]; }
|
||||
virtual float *GetAudioOutputBuffer(int index) const { return buffers.outputs[index]; }
|
||||
|
||||
virtual int GetNumberOfInputAudioBuffers() const {
|
||||
return buffers.inputs.size();
|
||||
}
|
||||
virtual int GetNumberOfInputAudioBuffers() const {
|
||||
return buffers.outputs.size();
|
||||
}
|
||||
|
||||
|
||||
virtual void ResetAtomBuffers() {}
|
||||
virtual void RequestParameter(LV2_URID uridUri) {} // no vst equivalent.
|
||||
virtual void GatherPatchProperties(RealtimePatchPropertyRequest *pRequest) {} // no vst equivalent.
|
||||
|
||||
Reference in New Issue
Block a user