Browse Source

Implement VST3 parameter outputs

Signed-off-by: falkTX <falktx@falktx.com>
pull/1775/head
falkTX 1 year ago
parent
commit
c96d08746b
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
3 changed files with 172 additions and 15 deletions
  1. +169
    -12
      source/backend/plugin/CarlaPluginVST3.cpp
  2. +1
    -1
      source/discovery/carla-discovery.cpp
  3. +2
    -2
      source/includes/travesty/audio_processor.h

+ 169
- 12
source/backend/plugin/CarlaPluginVST3.cpp View File

@@ -570,7 +570,6 @@ private:
}

CARLA_DECLARE_NON_COPYABLE(carla_v3_input_param_value_queue)
// CARLA_PREVENT_HEAP_ALLOCATION
};

struct carla_v3_input_param_changes : v3_param_changes_cpp {
@@ -606,10 +605,7 @@ struct carla_v3_input_param_changes : v3_param_changes_cpp {
carla_zeroStructs(updatedParams, paramCount);

for (uint32_t i=0; i<paramCount; ++i)
{
carla_zeroStruct(updatedParams[i]);
queue[i] = new carla_v3_input_param_value_queue(static_cast<v3_param_id>(paramData.data[i].rindex));
}
}

~carla_v3_input_param_changes()
@@ -674,7 +670,7 @@ private:
return me->pluginExposedQueue[index];
}

static v3_param_value_queue** V3_API add_param_data(void*, v3_param_id*, int32_t*)
static v3_param_value_queue** V3_API add_param_data(void*, const v3_param_id*, int32_t*)
{
// there is nothing here for input parameters, plugins are not meant to call this!
return nullptr;
@@ -685,8 +681,88 @@ private:

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

struct carla_v3_output_param_value_queue : v3_param_value_queue_cpp {
const v3_param_id paramId;
bool used;
int32_t offset;
double value;

carla_v3_output_param_value_queue(const v3_param_id pId)
: paramId(pId),
used(false),
offset(0),
value(0.0)
{
query_interface = v3_query_interface_static<v3_param_value_queue_iid>;
ref = v3_ref_static;
unref = v3_unref_static;
queue.get_param_id = get_param_id;
queue.get_point_count = get_point_count;
queue.get_point = get_point;
queue.add_point = add_point;
}

void init()
{
used = false;
offset = 0;
value = 0.0;
}

private:
static v3_param_id V3_API get_param_id(void* self)
{
carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
return me->paramId;
}

static int32_t V3_API get_point_count(void* self)
{
carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
return me->used ? 1 : 0;
}

static v3_result V3_API get_point(void* const self,
const int32_t index, int32_t* const sample_offset, double* const value)
{
carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
CARLA_SAFE_ASSERT_RETURN(me->used, V3_INVALID_ARG);
CARLA_SAFE_ASSERT_INT_RETURN(index == 0, index, V3_INVALID_ARG);

*sample_offset = me->offset;
*value = me->value;
return V3_OK;
}

static v3_result V3_API add_point(void* const self,
const int32_t sample_offset, const double value, int32_t* const index)
{
carla_v3_output_param_value_queue* const me = *static_cast<carla_v3_output_param_value_queue**>(self);
CARLA_SAFE_ASSERT_INT_RETURN(sample_offset >= 0, sample_offset, V3_INVALID_ARG);
CARLA_SAFE_ASSERT_RETURN(value >= 0 && value <= 1, V3_INVALID_ARG);
CARLA_SAFE_ASSERT_RETURN(index != nullptr, V3_INVALID_ARG);

me->offset = sample_offset;
me->value = value;
*index = 0;
return V3_OK;
}

CARLA_DECLARE_NON_COPYABLE(carla_v3_output_param_value_queue)
};

struct carla_v3_output_param_changes : v3_param_changes_cpp {
carla_v3_output_param_changes()
const uint32_t numParameters;
int32_t numParametersUsed;
bool* const parametersUsed;
carla_v3_output_param_value_queue** const queue;
std::unordered_map<v3_param_id, int32_t> paramIds;

carla_v3_output_param_changes(const PluginParameterData& paramData)
: numParameters(paramData.count),
numParametersUsed(0),
parametersUsed(new bool[paramData.count]),
queue(new carla_v3_output_param_value_queue*[paramData.count])
{
query_interface = v3_query_interface_static<v3_param_changes_iid>;
ref = v3_ref_static;
@@ -694,24 +770,63 @@ struct carla_v3_output_param_changes : v3_param_changes_cpp {
changes.get_param_count = get_param_count;
changes.get_param_data = get_param_data;
changes.add_param_data = add_param_data;

carla_zeroStructs(parametersUsed, numParameters);

for (uint32_t i=0; i<numParameters; ++i)
{
const v3_param_id paramId = paramData.data[i].rindex;
queue[i] = new carla_v3_output_param_value_queue(paramId);
paramIds[paramId] = i;
}
}

~carla_v3_output_param_changes()
{
for (uint32_t i=0; i<numParameters; ++i)
delete queue[i];
delete[] queue;
}

void prepare()
{
numParametersUsed = 0;
carla_zeroStructs(parametersUsed, numParameters);
}

private:
static int32_t V3_API get_param_count(void*)
{
carla_debug("TODO %s", __PRETTY_FUNCTION__);
// there is nothing here for output parameters, plugins are not meant to call this!
return 0;
}

static v3_param_value_queue** V3_API get_param_data(void*, int32_t)
{
carla_debug("TODO %s", __PRETTY_FUNCTION__);
// there is nothing here for output parameters, plugins are not meant to call this!
return nullptr;
}

static v3_param_value_queue** V3_API add_param_data(void*, v3_param_id*, int32_t*)
static v3_param_value_queue** V3_API add_param_data(void* const self,
const v3_param_id* const paramIdPtr,
int32_t* const index)
{
carla_debug("TODO %s", __PRETTY_FUNCTION__);
return nullptr;
carla_v3_output_param_changes* const me = *static_cast<carla_v3_output_param_changes**>(self);
CARLA_SAFE_ASSERT_RETURN(paramIdPtr != nullptr, nullptr);

const v3_param_id paramId = *paramIdPtr;

if (me->paramIds.find(paramId) == me->paramIds.end())
return nullptr;

const int32_t paramIndex = me->paramIds[paramId];
CARLA_SAFE_ASSERT_RETURN(!me->parametersUsed[paramIndex], nullptr);

*index = me->numParametersUsed++;
me->parametersUsed[paramIndex] = true;
me->queue[paramIndex]->init();

return (v3_param_value_queue**)&me->queue[paramIndex];
}

CARLA_DECLARE_NON_COPYABLE(carla_v3_output_param_changes)
@@ -2017,7 +2132,7 @@ public:
if (numParameters > 0)
{
fEvents.paramInputs = new carla_v3_input_param_changes(pData->param);
fEvents.paramOutputs = new carla_v3_output_param_changes;
fEvents.paramOutputs = new carla_v3_output_param_changes(pData->param);
}

if (needsCtrlIn)
@@ -2701,6 +2816,45 @@ public:
v3_cpp_obj(fV3.processor)->process(fV3.processor, &processData);
} CARLA_SAFE_EXCEPTION("process");

// ------------------------------------------------------------------------------------------------------------
// Handle parameter outputs

if (fEvents.paramOutputs != nullptr && fEvents.paramOutputs->numParametersUsed != 0)
{
uint8_t channel;
uint16_t param;

for (uint32_t i=0; i < pData->param.count; ++i)
{
if (fEvents.paramOutputs->parametersUsed[i])
{
carla_v3_output_param_value_queue* const queue = fEvents.paramOutputs->queue[i];
const v3_param_id paramId = pData->param.data[i].rindex;

const float value = v3_cpp_obj(fV3.controller)->normalised_parameter_to_plain(fV3.controller,
paramId,
queue->value);

pData->postponeParameterChangeRtEvent(true, static_cast<int32_t>(i), value);

if (pData->param.data[i].type == PARAMETER_OUTPUT && pData->param.data[i].mappedControlIndex > 0)
{
channel = pData->param.data[i].midiChannel;
param = static_cast<uint16_t>(pData->param.data[i].mappedControlIndex);

pData->event.portOut->writeControlEvent(queue->offset,
channel,
kEngineControlEventTypeParameter,
param,
-1,
queue->value);
}
}
}
}

pData->postRtEvents.trySplice();

fEvents.init();

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
@@ -3587,6 +3741,9 @@ private:
{
if (paramInputs != nullptr)
paramInputs->prepare();

if (paramOutputs != nullptr)
paramOutputs->prepare();
}

CARLA_DECLARE_NON_COPYABLE(Events)


+ 1
- 1
source/discovery/carla-discovery.cpp View File

@@ -1476,7 +1476,7 @@ struct carla_v3_param_changes : v3_param_changes_cpp {
private:
static int32_t V3_API carla_get_param_count(void*) { return 0; }
static v3_param_value_queue** V3_API carla_get_param_data(void*, int32_t) { return nullptr; }
static v3_param_value_queue** V3_API carla_add_param_data(void*, v3_param_id*, int32_t*) { return nullptr; }
static v3_param_value_queue** V3_API carla_add_param_data(void*, const v3_param_id*, int32_t*) { return nullptr; }

CARLA_DECLARE_NON_COPYABLE(carla_v3_param_changes)
CARLA_PREVENT_HEAP_ALLOCATION


+ 2
- 2
source/includes/travesty/audio_processor.h View File

@@ -1,6 +1,6 @@
/*
* travesty, pure C VST3-compatible interface
* Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2021-2023 Filipe Coelho <falktx@falktx.com>
*
* Permission to use, copy, modify, and/or distribute this software for any purpose with
* or without fee is hereby granted, provided that the above copyright notice and this
@@ -108,7 +108,7 @@ struct v3_param_changes {
#endif
int32_t (V3_API* get_param_count)(void* self);
struct v3_param_value_queue** (V3_API* get_param_data)(void* self, int32_t idx);
struct v3_param_value_queue** (V3_API* add_param_data)(void* self, v3_param_id* id, int32_t* index);
struct v3_param_value_queue** (V3_API* add_param_data)(void* self, const v3_param_id* id, int32_t* idx);
};

static constexpr const v3_tuid v3_param_changes_iid =


Loading…
Cancel
Save