Browse Source

Zyn plugin tweaks, expose 6 basic parameters

tags/1.9.6
falkTX 10 years ago
parent
commit
0baf7c5529
3 changed files with 271 additions and 99 deletions
  1. +11
    -7
      source/backend/plugin/CarlaPlugin.cpp
  2. +1
    -1
      source/carla_skin.py
  3. +259
    -91
      source/native-plugins/zynaddsubfx-synth.cpp

+ 11
- 7
source/backend/plugin/CarlaPlugin.cpp View File

@@ -528,8 +528,10 @@ const CarlaStateSave& CarlaPlugin::getStateSave(const bool callPrepareForSave)

if (data != nullptr && dataSize > 0)
{
usingChunk = true;
pData->stateSave.chunk = CarlaString::asBase64(data, dataSize).dup();

if (pluginType != PLUGIN_INTERNAL)
usingChunk = true;
}
}

@@ -621,6 +623,8 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
char strBuf[STR_MAX+1];
const bool usesMultiProgs(pData->extraHints & PLUGIN_EXTRA_HINT_USES_MULTI_PROGS);

const PluginType pluginType(getType());

// ---------------------------------------------------------------
// Part 1 - PRE-set custom data (only those which reload programs)

@@ -633,7 +637,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
const char* const type(stateCustomData->type);
const char* const key(stateCustomData->key);

if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
if (pluginType == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
continue;
if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
continue;
@@ -685,7 +689,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)

LinkedList<ParamSymbol*> paramSymbols;

if (getType() == PLUGIN_LADSPA || getType() == PLUGIN_LV2)
if (pluginType == PLUGIN_LADSPA || pluginType == PLUGIN_LV2)
{
for (uint32_t i=0; i < pData->param.count; ++i)
{
@@ -712,7 +716,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)

int32_t index = -1;

if (getType() == PLUGIN_LADSPA)
if (pluginType == PLUGIN_LADSPA)
{
// Try to set by symbol, otherwise use index
if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
@@ -735,7 +739,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
else
index = stateParameter->index;
}
else if (getType() == PLUGIN_LV2)
else if (pluginType == PLUGIN_LV2)
{
// Symbol only
if (stateParameter->symbol != nullptr && stateParameter->symbol[0] != '\0')
@@ -809,7 +813,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
const char* const type(stateCustomData->type);
const char* const key(stateCustomData->key);

if (getType() == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
if (pluginType == PLUGIN_DSSI && (std::strcmp(key, "reloadprograms") == 0 || std::strcmp(key, "load") == 0 || std::strncmp(key, "patches", 7) == 0))
continue;
if (usesMultiProgs && std::strcmp(key, "midiPrograms") == 0)
continue;
@@ -820,7 +824,7 @@ void CarlaPlugin::loadStateSave(const CarlaStateSave& stateSave)
// ---------------------------------------------------------------
// Part 5x - set lv2 state

if (getType() == PLUGIN_LV2 && pData->custom.count() > 0)
if (pluginType == PLUGIN_LV2 && pData->custom.count() > 0)
setCustomData(CUSTOM_DATA_TYPE_STRING, "CarlaLoadLv2StateNow", "true", true);

// ---------------------------------------------------------------


+ 1
- 1
source/carla_skin.py View File

@@ -553,7 +553,7 @@ class AbstractPluginSlot(QFrame, PluginEditParentMeta):
continue
if paramData['hints'] & PARAMETER_IS_BOOLEAN:
continue
if paramData['hints'] & PARAMETER_IS_INTEGER:
if (paramData['hints'] & PARAMETER_IS_INTEGER) != 0 and paramRanges['max']-paramRanges['min'] <= 10.0:
continue
if (paramData['hints'] & PARAMETER_IS_ENABLED) == 0:
continue


+ 259
- 91
source/native-plugins/zynaddsubfx-synth.cpp View File

@@ -65,9 +65,7 @@ void set_module_parameters(Fl_Widget* o)
o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP);
o->color(FL_BLACK);
o->labeltype(FL_SHADOW_LABEL);

if (gModuleBackdrop != nullptr)
o->image(gModuleBackdrop);
o->image(gModuleBackdrop);
}
#endif

@@ -76,41 +74,39 @@ void set_module_parameters(Fl_Widget* o)
class ZynAddSubFxPrograms
{
public:
ZynAddSubFxPrograms()
ZynAddSubFxPrograms() noexcept
: fInitiated(false),
#ifdef CARLA_PROPER_CPP11_SUPPORT
fRetProgram({0, 0, nullptr}),
#endif
fPrograms() {}

~ZynAddSubFxPrograms()
~ZynAddSubFxPrograms() noexcept
{
if (! fInitiated)
return;

for (LinkedList<const ProgramInfo*>::Itenerator it = fPrograms.begin(); it.valid(); it.next())
{
const ProgramInfo* const& pInfo(it.getValue());
const ProgramInfo* const& pInfo(it.getValue(nullptr));
delete pInfo;
}

fPrograms.clear();

FFT_cleanup();
}

void init()
void initIfNeeded()
{
if (fInitiated)
return;
fInitiated = true;

fPrograms.append(new ProgramInfo(0, 0, "default"));

Master& master(Master::getInstance());

pthread_mutex_lock(&master.mutex);

fPrograms.append(new ProgramInfo(0, 0, "default"));

// refresh banks
master.bank.rescanforbanks();

@@ -121,7 +117,7 @@ public:

master.bank.loadbank(master.bank.banks[i].dir);

for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument)
for (uint instrument = 0; instrument < BANK_SIZE; ++instrument)
{
const std::string insName(master.bank.getname(instrument));

@@ -193,10 +189,10 @@ private:
uint32_t prog;
const char* name;

ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_) noexcept
: bank(bank_),
prog(prog_),
name(carla_strdup_safe(name_)) {}
ProgramInfo(uint32_t b, uint32_t p, const char* n) noexcept
: bank(b),
prog(p),
name(carla_strdup_safe(n)) {}

~ProgramInfo() noexcept
{
@@ -232,9 +228,7 @@ class ZynAddSubFxInstanceCount
{
public:
ZynAddSubFxInstanceCount()
: fCount(0)
{
}
: fCount(0) {}

~ZynAddSubFxInstanceCount()
{
@@ -243,39 +237,39 @@ public:

void addOne(const NativeHostDescriptor* const host)
{
if (fCount++ == 0)
{
CARLA_ASSERT(synth == nullptr);
CARLA_ASSERT(denormalkillbuf == nullptr);
if (fCount++ != 0)
return;

reinit(host);
CARLA_SAFE_ASSERT(synth == nullptr);
CARLA_SAFE_ASSERT(denormalkillbuf == nullptr);

reinit(host);

#ifdef WANT_ZYNADDSUBFX_UI
if (gPixmapPath.isEmpty())
{
gPixmapPath = host->resourceDir;
gPixmapPath += "/zynaddsubfx/";
gUiPixmapPath = gPixmapPath;
}
#endif
if (gPixmapPath.isEmpty())
{
gPixmapPath = host->resourceDir;
gPixmapPath += "/zynaddsubfx/";
gUiPixmapPath = gPixmapPath;
}
#endif
}

void removeOne()
{
if (--fCount == 0)
{
CARLA_ASSERT(synth != nullptr);
CARLA_ASSERT(denormalkillbuf != nullptr);
if (--fCount != 0)
return;

Master::deleteInstance();
CARLA_SAFE_ASSERT(synth != nullptr);
CARLA_SAFE_ASSERT(denormalkillbuf != nullptr);

delete[] denormalkillbuf;
denormalkillbuf = nullptr;
Master::deleteInstance();

delete synth;
synth = nullptr;
}
delete[] denormalkillbuf;
denormalkillbuf = nullptr;

delete synth;
synth = nullptr;
}

void reinit(const NativeHostDescriptor* const host)
@@ -319,8 +313,8 @@ public:

void maybeReinit(const NativeHostDescriptor* const host)
{
if (host->get_buffer_size(host->handle) == static_cast<uint32_t>(synth->buffersize) &&
carla_compareFloats(host->get_sample_rate(host->handle), static_cast<double>(synth->samplerate)))
if (static_cast< int>(host->get_buffer_size(host->handle)) == synth->buffersize &&
static_cast<uint>(host->get_sample_rate(host->handle)) == synth->samplerate)
return;

reinit(host);
@@ -352,32 +346,30 @@ public:
fChangeProgram(false),
fNextChannel(0),
fNextBank(0),
fNextProgram(0)
{
}
fNextProgram(0) {}

~ZynAddSubFxThread()
{
#ifdef WANT_ZYNADDSUBFX_UI
// must be closed by now
CARLA_ASSERT(fUi == nullptr);
CARLA_SAFE_ASSERT(fUi == nullptr);
#endif
}

void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program)
{
fNextChannel = channel;
fNextBank = bank;
fNextProgram = program;
fNextChannel = channel;
fNextBank = bank;
fNextProgram = program;
fChangeProgram = true;
}

void stopLoadProgramLater()
{
fChangeProgram = false;
fNextChannel = 0;
fNextBank = 0;
fNextProgram = 0;
fNextChannel = 0;
fNextBank = 0;
fNextProgram = 0;
}

void setMaster(Master* const master)
@@ -515,7 +507,7 @@ protected:
}

#ifdef WANT_ZYNADDSUBFX_UI
if (shouldThreadExit() || fUi != nullptr)
if (fUi != nullptr)
{
Fl::lock();
delete fUi;
@@ -550,28 +542,104 @@ private:
class ZynAddSubFxPlugin : public NativePluginClass
{
public:
enum Parameters {
kParamFilterCutoff = 0, // Filter Frequency
kParamFilterQ, // Filter Resonance
kParamBandwidth, // Bandwidth
kParamModAmp, // FM Gain
kParamResCenter, // Resonance center frequency
kParamResBandwidth, // Resonance bandwidth
kParamCount
};

ZynAddSubFxPlugin(const NativeHostDescriptor* const host)
: NativePluginClass(host),
fMaster(new Master()),
fMaster(nullptr),
fSampleRate(static_cast<uint>(getSampleRate())),
fIsActive(false),
fThread(fMaster, host),
fThread(nullptr, host),
leakDetector_ZynAddSubFxPlugin()
{
fThread.startThread();
// init parameters to default
fParameters[kParamFilterCutoff] = 64.0f;
fParameters[kParamFilterQ] = 64.0f;
fParameters[kParamBandwidth] = 64.0f;
fParameters[kParamModAmp] = 127.0f;
fParameters[kParamResCenter] = 64.0f;
fParameters[kParamResBandwidth] = 64.0f;

for (int i = 0; i < NUM_MIDI_PARTS; ++i)
fMaster->partonoff(i, 1);

sPrograms.init();
_initMaster();
sPrograms.initIfNeeded();
}

~ZynAddSubFxPlugin() override
{
deleteMaster();
_deleteMaster();
}

protected:
// -------------------------------------------------------------------
// Plugin parameter calls

uint32_t getParameterCount() const final
{
return kParamCount;
}

const NativeParameter* getParameterInfo(const uint32_t index) const override
{
CARLA_SAFE_ASSERT_RETURN(index < kParamCount, nullptr);

static NativeParameter param;

int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_INTEGER|NATIVE_PARAMETER_IS_AUTOMABLE;

param.name = nullptr;
param.unit = nullptr;
param.ranges.def = 64.0f;
param.ranges.min = 0.0f;
param.ranges.max = 127.0f;
param.ranges.step = 1.0f;
param.ranges.stepSmall = 1.0f;
param.ranges.stepLarge = 20.0f;
param.scalePointCount = 0;
param.scalePoints = nullptr;

switch (index)
{
case kParamFilterCutoff:
param.name = "Filter Cutoff";
break;
case kParamFilterQ:
param.name = "Filter Q";
break;
case kParamBandwidth:
param.name = "Bandwidth";
break;
case kParamModAmp:
param.name = "FM Gain";
param.ranges.def = 127.0f;
break;
case kParamResCenter:
param.name = "Res Center Freq";
break;
case kParamResBandwidth:
param.name = "Res Bandwidth";
break;
}

param.hints = static_cast<NativeParameterHints>(hints);

return &param;
}

float getParameterValue(const uint32_t index) const final
{
CARLA_SAFE_ASSERT_RETURN(index < kParamCount, 0.0f);

return fParameters[index];
}

// -------------------------------------------------------------------
// Plugin midi-program calls

@@ -588,6 +656,22 @@ protected:
// -------------------------------------------------------------------
// Plugin state calls

void setParameterValue(const uint32_t index, const float value) final
{
CARLA_SAFE_ASSERT_RETURN(index < kParamCount,);

const uint zynIndex(getZynParameterFromIndex(index));
CARLA_SAFE_ASSERT_RETURN(zynIndex != C_NULL,);

fParameters[index] = value;

for (int npart=0; npart<NUM_MIDI_PARTS; ++npart)
{
if (fMaster->part[npart] != nullptr && fMaster->part[npart]->Penabled != 0)
fMaster->part[npart]->SetController(zynIndex, static_cast<int>(value));
}
}

void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
{
if (bank >= fMaster->bank.banks.size())
@@ -601,9 +685,10 @@ protected:
#ifdef WANT_ZYNADDSUBFX_UI
fThread.uiRepaint();
#endif
return;
}
else
fThread.loadProgramLater(channel, bank, program);
fThread.loadProgramLater(channel, bank, program);
}

void setCustomData(const char* const key, const char* const value) override
@@ -613,7 +698,7 @@ protected:

pthread_mutex_lock(&fMaster->mutex);

if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
/**/ if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
{
fMaster->defaults();
fMaster->loadXML(value);
@@ -680,6 +765,10 @@ protected:
}
else if (MIDI_IS_STATUS_CONTROL_CHANGE(status))
{
// skip controls which we map to parameters
if (getZynParameterFromIndex(midiEvent->data[1]) == C_NULL)
continue;

const int control = midiEvent->data[1];
const int value = midiEvent->data[2];

@@ -735,42 +824,38 @@ protected:
// -------------------------------------------------------------------
// Plugin dispatcher

// TODO - save&load current state

void bufferSizeChanged(const uint32_t) final
{
deleteMaster();
char* const state(getState());

_deleteMaster();
sInstanceCount.maybeReinit(getHostHandle());
initMaster();
_initMaster();

if (state != nullptr)
{
fMaster->putalldata(state, 0);
fMaster->applyparameters(true);
std::free(state);
}
}

void sampleRateChanged(const double sampleRate) final
{
fSampleRate = static_cast<uint>(sampleRate);
deleteMaster();
sInstanceCount.maybeReinit(getHostHandle());
initMaster();
}

void initMaster()
{
fMaster = new Master();
fThread.setMaster(fMaster);
fThread.startThread();

for (int i = 0; i < NUM_MIDI_PARTS; ++i)
fMaster->partonoff(i, 1);
}
char* const state(getState());

void deleteMaster()
{
//ensure that everything has stopped
pthread_mutex_lock(&fMaster->mutex);
pthread_mutex_unlock(&fMaster->mutex);
fThread.stopThread(-1);
_deleteMaster();
sInstanceCount.maybeReinit(getHostHandle());
_initMaster();

delete fMaster;
fMaster = nullptr;
if (state != nullptr)
{
fMaster->putalldata(state, 0);
fMaster->applyparameters(true);
std::free(state);
}
}

#ifdef WANT_ZYNADDSUBFX_UI
@@ -786,9 +871,91 @@ private:
Master* fMaster;
uint fSampleRate;
bool fIsActive;
float fParameters[kParamCount];

ZynAddSubFxThread fThread;

/*
static Parameters getParameterFromZynIndex(const MidiControllers index)
{
switch (index)
{
case C_filtercutoff:
return kParamFilterCutoff;
case C_filterq:
return kParamFilterQ;
case C_bandwidth:
return kParamBandwidth;
case C_fmamp:
return kParamModAmp;
case C_resonance_center:
return kParamResCenter;
case C_resonance_bandwidth:
return kParamResBandwidth;
default:
return kParamCount;
}
}
*/

static uint getZynParameterFromIndex(const uint index)
{
switch (index)
{
case kParamFilterCutoff:
return C_filtercutoff;
case kParamFilterQ:
return C_filterq;
case kParamBandwidth:
return C_bandwidth;
case kParamModAmp:
return C_fmamp;
case kParamResCenter:
return C_resonance_center;
case kParamResBandwidth:
return C_resonance_bandwidth;
case kParamCount:
return C_NULL;
}

return C_NULL;
}

// -------------------------------------------------------------------

void _initMaster()
{
fMaster = new Master();
fThread.setMaster(fMaster);
fThread.startThread();

for (int i=0; i<NUM_MIDI_PARTS; ++i)
{
fMaster->partonoff(i, 1);

for (int npart=0; npart<NUM_MIDI_PARTS; ++npart)
{
fMaster->part[npart]->SetController(C_filtercutoff, static_cast<int>(fParameters[kParamFilterCutoff]));
fMaster->part[npart]->SetController(C_filterq, static_cast<int>(fParameters[kParamFilterQ]));
fMaster->part[npart]->SetController(C_bandwidth, static_cast<int>(fParameters[kParamBandwidth]));
fMaster->part[npart]->SetController(C_fmamp, static_cast<int>(fParameters[kParamModAmp]));
fMaster->part[npart]->SetController(C_resonance_center, static_cast<int>(fParameters[kParamResCenter]));
fMaster->part[npart]->SetController(C_resonance_bandwidth, static_cast<int>(fParameters[kParamResBandwidth]));
}
}
}

void _deleteMaster()
{
//ensure that everything has stopped
pthread_mutex_lock(&fMaster->mutex);
pthread_mutex_unlock(&fMaster->mutex);
fThread.stopThread(-1);

delete fMaster;
fMaster = nullptr;
}

// -------------------------------------------------------------------

public:
@@ -797,6 +964,7 @@ public:
sInstanceCount.addOne(host);
return new ZynAddSubFxPlugin(host);
}

static void _cleanup(NativePluginHandle handle)
{
delete (ZynAddSubFxPlugin*)handle;
@@ -824,7 +992,7 @@ static const NativePluginDescriptor zynaddsubfxDesc = {
/* audioOuts */ 2,
/* midiIns */ 1,
/* midiOuts */ 0,
/* paramIns */ 0,
/* paramIns */ ZynAddSubFxPlugin::kParamCount,
/* paramOuts */ 0,
/* name */ "ZynAddSubFX",
/* label */ "zynaddsubfx",


Loading…
Cancel
Save