Browse Source

Update DPF and Nekobi

tags/v1.1
falkTX 8 years ago
parent
commit
fe9e89e260
10 changed files with 231 additions and 51 deletions
  1. +4
    -4
      dpf/dgl/NanoVG.hpp
  2. +1
    -1
      dpf/dgl/Widget.hpp
  3. +56
    -2
      dpf/distrho/DistrhoPlugin.hpp
  4. +7
    -0
      dpf/distrho/src/DistrhoPluginInternal.hpp
  5. +97
    -28
      dpf/distrho/src/DistrhoPluginJack.cpp
  6. +11
    -10
      dpf/distrho/src/DistrhoPluginLV2.cpp
  7. +33
    -4
      dpf/distrho/src/DistrhoPluginLV2export.cpp
  8. +1
    -1
      dpf/distrho/src/DistrhoUILV2.cpp
  9. +18
    -0
      plugins/Nekobi/DistrhoPluginNekobi.cpp
  10. +3
    -1
      plugins/Nekobi/DistrhoPluginNekobi.hpp

+ 4
- 4
dpf/dgl/NanoVG.hpp View File

@@ -192,10 +192,10 @@ private:

@code
const char* txt = "Text me up.";
textBounds(vg, x,y, txt, NULL, bounds);
beginPath(vg);
roundedRect(vg, bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
fill(vg);
vg.textBounds(x,y, txt, NULL, bounds);
vg.beginPath();
vg.roundedRect(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]);
vg.fill();
@endcode

Note: currently only solid color fill is supported for text.


+ 1
- 1
dpf/dgl/Widget.hpp View File

@@ -111,7 +111,7 @@ public:
/**
Mouse event.
@a button The button number (1 = left, 2 = middle, 3 = right).
@a press True if the key was pressed, false if released.
@a press True if the button was pressed, false if released.
@a pos The widget-relative coordinates of the pointer.
@see onMouse
*/


+ 56
- 2
dpf/distrho/DistrhoPlugin.hpp View File

@@ -133,6 +133,29 @@ struct AudioPort {
symbol() {}
};

/**
Parameter designation.@n
Allows a parameter to be specially designated for a task, like bypass.

Each designation is unique, there must be only one parameter that uses it.@n
The use of designated parameters is completely optional.

@note Designated parameters have strict ranges.
@see ParameterRanges::adjustForDesignation()
*/
enum ParameterDesignation {
/**
Null or unset designation.
*/
kParameterDesignationNull = 0,

/**
Bypass designation.@n
When on (> 0.5f), it means the plugin must run in a bypassed state.
*/
kParameterDesignationBypass = 1
};

/**
Parameter ranges.@n
This is used to set the default, minimum and maximum values of a parameter.
@@ -289,6 +312,11 @@ struct Parameter {
*/
ParameterRanges ranges;

/**
Designation for this parameter.
*/
ParameterDesignation designation;

/**
MIDI CC to use by default on this parameter.@n
A value of 0 or 32 (bank change) is considered invalid.@n
@@ -306,6 +334,7 @@ struct Parameter {
symbol(),
unit(),
ranges(),
designation(kParameterDesignationNull),
midiCC(0) {}

/**
@@ -317,7 +346,32 @@ struct Parameter {
symbol(s),
unit(u),
ranges(def, min, max),
designation(kParameterDesignationNull),
midiCC(0) {}

/**
Initialize a parameter for a specific designation.
*/
void initDesignation(ParameterDesignation d) noexcept
{
designation = d;

switch (d)
{
case kParameterDesignationNull:
break;
case kParameterDesignationBypass:
hints = kParameterIsAutomable|kParameterIsBoolean|kParameterIsInteger;
name = "Bypass";
symbol = "dpf_bypass";
unit = "";
midiCC = 0;
ranges.def = 0.0f;
ranges.min = 0.0f;
ranges.max = 1.0f;
break;
}
}
};

/**
@@ -541,7 +595,7 @@ public:
Returns false when the host buffer is full, in which case do not call this again until the next run().
@note This function is not implemented yet!@n
It's here so that developers can prepare MIDI plugins in advance.@n
If you plan to use this, please report to DPF authos so it can be implemented.
If you plan to use this, please report to DPF authors so it can be implemented.
*/
bool writeMidiEvent(const MidiEvent& midiEvent) noexcept;
#endif
@@ -661,7 +715,7 @@ protected:
/**
Get the value of an internal state.@n
The host may call this function from any non-realtime context.@n
Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_PROGRAMS or DISTRHO_PLUGIN_WANT_FULL_STATE is enabled.
Must be implemented by your plugin class if DISTRHO_PLUGIN_WANT_FULL_STATE is enabled.
@note The use of this function breaks compatibility with the DSSI format.
*/
virtual String getState(const char* key) const = 0;


+ 7
- 0
dpf/distrho/src/DistrhoPluginInternal.hpp View File

@@ -290,6 +290,13 @@ public:
return fData->parameters[index].hints;
}

ParameterDesignation getParameterDesignation(const uint32_t index) const noexcept
{
DISTRHO_SAFE_ASSERT_RETURN(fData != nullptr && index < fData->parameterCount, kParameterDesignationNull);

return fData->parameters[index].designation;
}

bool isParameterOutput(const uint32_t index) const noexcept
{
return (getParameterHints(index) & kParameterIsOutput);


+ 97
- 28
dpf/distrho/src/DistrhoPluginJack.cpp View File

@@ -97,28 +97,27 @@ public:
#endif
fClient(client)
{
#if DISTRHO_PLUGIN_NUM_INPUTS > 0 || DISTRHO_PLUGIN_NUM_OUTPUTS > 0
char strBuf[0xff+1];
strBuf[0xff] = '\0';

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
# if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "in%i", i+1);
fPortAudioIns[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
}
#endif

#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
# endif
# if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i)
{
std::snprintf(strBuf, 0xff, "out%i", i+1);
fPortAudioOuts[i] = jack_port_register(fClient, strBuf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
}
# endif
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
fPortMidiIn = jack_port_register(fClient, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
#endif
fPortEventsIn = jack_port_register(fClient, "events-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);

#if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fPlugin.getProgramCount() > 0)
@@ -128,11 +127,18 @@ public:
fUI.programLoaded(0);
# endif
}
# if DISTRHO_PLUGIN_HAS_UI
fProgramChanged = -1;
# endif
#endif

if (const uint32_t count = fPlugin.getParameterCount())
{
fLastOutputValues = new float[count];
#if DISTRHO_PLUGIN_HAS_UI
fParametersChanged = new bool[count];
std::memset(fParametersChanged, 0, sizeof(bool)*count);
#endif

for (uint32_t i=0; i < count; ++i)
{
@@ -143,15 +149,18 @@ public:
else
{
fLastOutputValues[i] = 0.0f;
# if DISTRHO_PLUGIN_HAS_UI
#if DISTRHO_PLUGIN_HAS_UI
fUI.parameterChanged(i, fPlugin.getParameterValue(i));
# endif
#endif
}
}
}
else
{
fLastOutputValues = nullptr;
#if DISTRHO_PLUGIN_HAS_UI
fParametersChanged = nullptr;
#endif
}

jack_set_buffer_size_callback(fClient, jackBufferSizeCallback, this);
@@ -192,10 +201,8 @@ public:
if (fClient == nullptr)
return;

#if DISTRHO_PLUGIN_IS_SYNTH
jack_port_unregister(fClient, fPortMidiIn);
fPortMidiIn = nullptr;
#endif
jack_port_unregister(fClient, fPortEventsIn);
fPortEventsIn = nullptr;

#if DISTRHO_PLUGIN_NUM_INPUTS > 0
for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i)
@@ -225,20 +232,31 @@ protected:
if (gCloseSignalReceived)
return fUI.quit();

float value;
# if DISTRHO_PLUGIN_WANT_PROGRAMS
if (fProgramChanged >= 0)
{
fUI.programLoaded(fProgramChanged);
fProgramChanged = -1;
}
# endif

for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i)
{
if (! fPlugin.isParameterOutput(i))
continue;

value = fPlugin.getParameterValue(i);
if (fPlugin.isParameterOutput(i))
{
const float value = fPlugin.getParameterValue(i);

if (fLastOutputValues[i] == value)
continue;
if (d_isEqual(fLastOutputValues[i], value))
continue;

fLastOutputValues[i] = value;
fUI.parameterChanged(i, value);
fLastOutputValues[i] = value;
fUI.parameterChanged(i, value);
}
else if (fParametersChanged[i])
{
fParametersChanged[i] = false;
fUI.parameterChanged(i, fPlugin.getParameterValue(i));
}
}

fUI.exec_idle();
@@ -310,14 +328,14 @@ protected:
fPlugin.setTimePosition(fTimePosition);
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
void* const midiBuf = jack_port_get_buffer(fPortMidiIn, nframes);
void* const midiBuf = jack_port_get_buffer(fPortEventsIn, nframes);

if (const uint32_t eventCount = jack_midi_get_event_count(midiBuf))
{
#if DISTRHO_PLUGIN_IS_SYNTH
uint32_t midiEventCount = 0;
MidiEvent midiEvents[eventCount];
#endif
jack_midi_event_t jevent;

for (uint32_t i=0; i < eventCount; ++i)
@@ -325,6 +343,47 @@ protected:
if (jack_midi_event_get(&jevent, midiBuf, i) != 0)
break;

// Check if message is control change on channel 1
if (jevent.buffer[0] == 0xB0 && jevent.size == 3)
{
const uint8_t control = jevent.buffer[1];
const uint8_t value = jevent.buffer[2];

/* NOTE: This is not optimal, we're iterating all parameters on every CC message.
Since the JACK standalone is more of a test tool, this will do for now. */
for (uint32_t j=0, paramCount=fPlugin.getParameterCount(); j < paramCount; ++j)
{
if (fPlugin.isParameterOutput(j))
continue;
if (fPlugin.getParameterMidiCC(j) != control)
continue;

const float scaled = static_cast<float>(value)/127.0f;
const float fvalue = fPlugin.getParameterRanges(j).getUnnormalizedValue(scaled);
fPlugin.setParameterValue(j, fvalue);
#if DISTRHO_PLUGIN_HAS_UI
fParametersChanged[j] = true;
#endif
break;
}
}
#if DISTRHO_PLUGIN_WANT_PROGRAMS
// Check if message is program change on channel 1
else if (jevent.buffer[0] == 0xC0 && jevent.size == 2)
{
const uint8_t program = jevent.buffer[1];

if (program < fPlugin.getProgramCount())
{
fPlugin.loadProgram(program);
# if DISTRHO_PLUGIN_HAS_UI
fProgramChanged = program;
# endif
}
}
#endif

#if DISTRHO_PLUGIN_IS_SYNTH
MidiEvent& midiEvent(midiEvents[midiEventCount++]);

midiEvent.frame = jevent.time;
@@ -334,10 +393,14 @@ protected:
midiEvent.dataExt = jevent.buffer;
else
std::memcpy(midiEvent.data, jevent.buffer, midiEvent.size);
#endif
}

#if DISTRHO_PLUGIN_IS_SYNTH
fPlugin.run(audioIns, audioOuts, nframes, midiEvents, midiEventCount);
#endif
}
#if DISTRHO_PLUGIN_IS_SYNTH
else
{
fPlugin.run(audioIns, audioOuts, nframes, nullptr, 0);
@@ -393,9 +456,7 @@ private:
#if DISTRHO_PLUGIN_NUM_OUTPUTS > 0
jack_port_t* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS];
#endif
#if DISTRHO_PLUGIN_IS_SYNTH
jack_port_t* fPortMidiIn;
#endif
jack_port_t* fPortEventsIn;
#if DISTRHO_PLUGIN_WANT_TIMEPOS
TimePosition fTimePosition;
#endif
@@ -403,6 +464,14 @@ private:
// Temporary data
float* fLastOutputValues;

#if DISTRHO_PLUGIN_HAS_UI
// Store DSP changes to send to UI
bool* fParametersChanged;
# if DISTRHO_PLUGIN_WANT_PROGRAMS
int fProgramChanged;
# endif
#endif

// -------------------------------------------------------------------
// Callbacks



+ 11
- 10
dpf/distrho/src/DistrhoPluginLV2.cpp View File

@@ -512,6 +512,12 @@ public:
if (fLastControlValues[i] != curValue && ! fPlugin.isParameterOutput(i))
{
fLastControlValues[i] = curValue;

if (fPlugin.getParameterDesignation(i) == kParameterDesignationBypass)
{
curValue = 1.0f - curValue;
}

fPlugin.setParameterValue(i, curValue);
}
}
@@ -589,10 +595,14 @@ public:
#if DISTRHO_PLUGIN_WANT_STATE && DISTRHO_PLUGIN_HAS_UI
const uint32_t capacity = fPortEventsOut->atom.size;

bool needsInit = true;
uint32_t size, offset = 0;
LV2_Atom_Event* aev;

fPortEventsOut->atom.size = sizeof(LV2_Atom_Sequence_Body);
fPortEventsOut->atom.type = fURIDs.atomSequence;
fPortEventsOut->body.unit = 0;
fPortEventsOut->body.pad = 0;

// TODO - MIDI Output

for (uint32_t i=0, count=fPlugin.getStateCount(); i < count; ++i)
@@ -617,15 +627,6 @@ public:
if (sizeof(LV2_Atom_Event) + msgSize > capacity - offset)
break;

if (needsInit)
{
fPortEventsOut->atom.size = 0;
fPortEventsOut->atom.type = fURIDs.atomSequence;
fPortEventsOut->body.unit = 0;
fPortEventsOut->body.pad = 0;
needsInit = false;
}

// reserve msg space
char msgBuf[msgSize];
std::memset(msgBuf, 0, msgSize);


+ 33
- 4
dpf/distrho/src/DistrhoPluginLV2export.cpp View File

@@ -377,10 +377,34 @@ void lv2_generate_ttl(const char* const basename)
pluginString += " a lv2:InputPort, lv2:ControlPort ;\n";

pluginString += " lv2:index " + String(portIndex) + " ;\n";
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";

// symbol
bool designated = false;

// designation
if (! plugin.isParameterOutput(i))
{
switch (plugin.getParameterDesignation(i))
{
case kParameterDesignationNull:
break;
case kParameterDesignationBypass:
designated = true;
pluginString += " lv2:name \"Enabled\" ;\n";
pluginString += " lv2:symbol \"lv2_enabled\" ;\n";
pluginString += " lv2:default 1 ;\n";
pluginString += " lv2:minimum 0 ;\n";
pluginString += " lv2:maximum 1 ;\n";
pluginString += " lv2:portProperty lv2:toggled , lv2:integer ;\n";
pluginString += " lv2:designation lv2:enabled ;\n";
break;
}
}

// name and symbol
if (! designated)
{
pluginString += " lv2:name \"" + plugin.getParameterName(i) + "\" ;\n";

String symbol(plugin.getParameterSymbol(i));

if (symbol.isEmpty())
@@ -390,24 +414,28 @@ void lv2_generate_ttl(const char* const basename)
}

// ranges
if (! designated)
{
const ParameterRanges& ranges(plugin.getParameterRanges(i));

if (plugin.getParameterHints(i) & kParameterIsInteger)
{
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
if (! plugin.isParameterOutput(i))
pluginString += " lv2:default " + String(int(plugin.getParameterValue(i))) + " ;\n";
pluginString += " lv2:minimum " + String(int(ranges.min)) + " ;\n";
pluginString += " lv2:maximum " + String(int(ranges.max)) + " ;\n";
}
else
{
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
if (! plugin.isParameterOutput(i))
pluginString += " lv2:default " + String(plugin.getParameterValue(i)) + " ;\n";
pluginString += " lv2:minimum " + String(ranges.min) + " ;\n";
pluginString += " lv2:maximum " + String(ranges.max) + " ;\n";
}
}

// unit
if (! designated)
{
const String& unit(plugin.getParameterUnit(i));

@@ -453,6 +481,7 @@ void lv2_generate_ttl(const char* const basename)
}

// hints
if (! designated)
{
const uint32_t hints(plugin.getParameterHints(i));



+ 1
- 1
dpf/distrho/src/DistrhoUILV2.cpp View File

@@ -239,7 +239,7 @@ protected:
const size_t msgSize(tmpStr.length()+1);

// reserve atom space
const size_t atomSize(lv2_atom_pad_size(sizeof(LV2_Atom) + msgSize));
const size_t atomSize(sizeof(LV2_Atom) + msgSize);
char atomBuf[atomSize];
std::memset(atomBuf, 0, atomSize);



+ 18
- 0
plugins/Nekobi/DistrhoPluginNekobi.cpp View File

@@ -135,6 +135,7 @@ DistrhoPluginNekobi::DistrhoPluginNekobi()
fParams.decay = 75.0f;
fParams.accent = 25.0f;
fParams.volume = 75.0f;
fParams.bypass = false;
// Internal stuff
fSynth.waveform = 0.0f;
@@ -232,6 +233,9 @@ void DistrhoPluginNekobi::initParameter(uint32_t index, Parameter& parameter)
parameter.ranges.min = 0.0f;
parameter.ranges.max = 100.0f;
break;
case paramBypass:
parameter.initDesignation(kParameterDesignationBypass);
break;
}
}
@@ -258,6 +262,8 @@ float DistrhoPluginNekobi::getParameterValue(uint32_t index) const
return fParams.accent;
case paramVolume:
return fParams.volume;
case paramBypass:
return fParams.bypass ? 1.0f : 0.0f;
}
return 0.0f;
@@ -307,6 +313,14 @@ void DistrhoPluginNekobi::setParameterValue(uint32_t index, float value)
fSynth.volume = value/100.0f;
DISTRHO_SAFE_ASSERT(fSynth.volume >= 0.0f && fSynth.volume <= 1.0f);
break;
case paramBypass: {
const bool bypass = (value > 0.5f);
if (fParams.bypass != bypass)
{
fParams.bypass = bypass;
nekobee_synth_all_voices_off(&fSynth);
}
} break;
}
}
@@ -342,6 +356,10 @@ void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, c
return;
}
// ignore midi input if bypassed
if (fParams.bypass)
midiEventCount = 0;
while (framesDone < frames)
{
if (fSynth.nugget_remains == 0)


+ 3
- 1
plugins/Nekobi/DistrhoPluginNekobi.hpp View File

@@ -42,6 +42,7 @@ public:
paramDecay,
paramAccent,
paramVolume,
paramBypass,
paramCount
};
@@ -79,7 +80,7 @@ protected:
uint32_t getVersion() const noexcept override
{
return d_version(1, 0, 0);
return d_version(1, 1, 0);
}
int64_t getUniqueId() const noexcept override
@@ -117,6 +118,7 @@ private:
float decay;
float accent;
float volume;
bool bypass;
} fParams;
nekobee_synth_t fSynth;


Loading…
Cancel
Save