Browse Source

More tests with CV controls, working for ladspa

Signed-off-by: falkTX <falktx@falktx.com>
tags/v2.1-rc1
falkTX 5 years ago
parent
commit
5d81b6431f
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
4 changed files with 156 additions and 12 deletions
  1. +28
    -0
      source/backend/CarlaEngine.hpp
  2. +1
    -0
      source/backend/engine/CarlaEngineInternal.hpp
  3. +83
    -7
      source/backend/engine/CarlaEnginePorts.cpp
  4. +44
    -5
      source/backend/plugin/CarlaPluginLADSPADSSI.cpp

+ 28
- 0
source/backend/CarlaEngine.hpp View File

@@ -385,6 +385,14 @@ public:
return kIsInput;
}

/*!
* Get the index offset as passed in the constructor.
*/
uint32_t getIndexOffset() const noexcept
{
return kIndexOffset;
}

/*!
* Get this ports' engine client.
*/
@@ -494,9 +502,24 @@ public:
return fBuffer;
}

/*!
* Get min/max range for this CV port.
*/
void getRange(float& min, float& max) const noexcept
{
min = fMinimum;
max = fMaximum;
}

/*!
* Set min/max range for this CV port.
*/
void setRange(float min, float max) noexcept;

#ifndef DOXYGEN
protected:
float* fBuffer;
float fMinimum, fMaximum;

CARLA_DECLARE_NON_COPY_CLASS(CarlaEngineCVPort)
#endif
@@ -537,6 +560,11 @@ public:
*/
void removeCVSource(CarlaEngineCVPort* port) noexcept;

/*!
* Remove a CV port as a source of events.
*/
void mixWithCvBuffer(const float* buffer, uint32_t frames, uint32_t indexOffset) noexcept;

/*!
* Initialize the port's internal buffer for @a engine.
*/


+ 1
- 0
source/backend/engine/CarlaEngineInternal.hpp View File

@@ -215,6 +215,7 @@ struct EnginePluginData {
struct CarlaEngineEventCV {
CarlaEngineCVPort* cvPort;
float previousValue;
uint32_t indexOffset;
};

struct CarlaEngineEventPort::ProtectedData {


+ 83
- 7
source/backend/engine/CarlaEnginePorts.cpp View File

@@ -20,6 +20,8 @@
#include "CarlaMathUtils.hpp"
#include "CarlaMIDI.h"

#include "lv2/lv2.h"

CARLA_BACKEND_START_NAMESPACE

// -----------------------------------------------------------------------
@@ -71,7 +73,9 @@ void CarlaEngineAudioPort::initBuffer() noexcept

CarlaEngineCVPort::CarlaEngineCVPort(const CarlaEngineClient& client, const bool isInputPort, const uint32_t indexOffset) noexcept
: CarlaEnginePort(client, isInputPort, indexOffset),
fBuffer(nullptr)
fBuffer(nullptr),
fMinimum(-1.0f),
fMaximum(1.0f)
{
carla_debug("CarlaEngineCVPort::CarlaEngineCVPort(%s)", bool2str(isInputPort));
}
@@ -85,6 +89,26 @@ void CarlaEngineCVPort::initBuffer() noexcept
{
}

void CarlaEngineCVPort::setRange(const float min, const float max) noexcept
{
fMinimum = min;
fMaximum = max;

char strBufMin[STR_MAX];
char strBufMax[STR_MAX];
carla_zeroChars(strBufMin, STR_MAX);
carla_zeroChars(strBufMax, STR_MAX);

{
const CarlaScopedLocale csl;
std::snprintf(strBufMin, STR_MAX-1, "%f", static_cast<double>(min));
std::snprintf(strBufMax, STR_MAX-1, "%f", static_cast<double>(max));
}

setMetaData(LV2_CORE__minimum, strBufMin, "");
setMetaData(LV2_CORE__maximum, strBufMax, "");
}

// -----------------------------------------------------------------------
// Carla Engine Event port

@@ -107,7 +131,7 @@ void CarlaEngineEventPort::addCVSource(CarlaEngineCVPort* const port) noexcept
CARLA_SAFE_ASSERT_RETURN(port->isInput(),);
carla_debug("CarlaEngineEventPort::addCVSource(%p)", port);

const CarlaEngineEventCV ecv { port, 0.0f };
const CarlaEngineEventCV ecv { port, 0.0f, port->getIndexOffset() };
pData->cvs.append(ecv);
}

@@ -121,17 +145,69 @@ void CarlaEngineEventPort::removeCVSource(CarlaEngineCVPort* const port) noexcep
(void)port;
}

static CarlaEngineEventCV kFallbackEngineEventCV = { nullptr, 0.0f, (uint32_t)-1 };

void CarlaEngineEventPort::mixWithCvBuffer(const float* const buffer,
const uint32_t frames,
const uint32_t indexOffset) noexcept
{
CARLA_SAFE_ASSERT_RETURN(pData->buffer != nullptr,)
CARLA_SAFE_ASSERT_RETURN(kIsInput,);

uint32_t eventIndex = 0;
float v, min, max;

for (; eventIndex < kMaxEngineEventInternalCount; ++eventIndex)
{
if (pData->buffer[eventIndex].type == kEngineEventTypeNull)
break;
}

if (eventIndex == kMaxEngineEventInternalCount)
return;

for (LinkedList<CarlaEngineEventCV>::Itenerator it = pData->cvs.begin2(); it.valid(); it.next())
{
CarlaEngineEventCV& ecv(it.getValue(kFallbackEngineEventCV));

if (ecv.indexOffset != indexOffset)
continue;
CARLA_SAFE_ASSERT_RETURN(ecv.cvPort != nullptr,);

float previousValue = ecv.previousValue;
ecv.cvPort->getRange(min, max);

for (uint32_t i=0; i<frames; ++i)
{
v = buffer[i];

if (carla_isNotEqual(v, previousValue))
{
previousValue = v;

EngineEvent& event(pData->buffer[i++]);

event.type = kEngineEventTypeControl;
event.time = i;
event.channel = 0xFF;

event.ctrl.type = kEngineControlEventTypeParameter;
event.ctrl.param = static_cast<uint16_t>(indexOffset);
event.ctrl.value = carla_fixedValue(0.0f, 1.0f, (v - min) / (max - min));
}
}

ecv.previousValue = previousValue;
break;
}
}

void CarlaEngineEventPort::initBuffer() noexcept
{
if (pData->processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || pData->processMode == ENGINE_PROCESS_MODE_BRIDGE)
pData->buffer = kClient.getEngine().getInternalEventBuffer(kIsInput);
else if (pData->processMode == ENGINE_PROCESS_MODE_PATCHBAY && ! kIsInput)
carla_zeroStructs(pData->buffer, kMaxEngineEventInternalCount);

for (LinkedList<CarlaEngineEventCV>::Itenerator it = pData->cvs.begin2(); it.valid(); it.next())
{
// TODO append events to buffer
}
}

uint32_t CarlaEngineEventPort::getEventCount() const noexcept


+ 44
- 5
source/backend/plugin/CarlaPluginLADSPADSSI.cpp View File

@@ -1238,6 +1238,7 @@ public:
// Parameter as CV
CarlaEngineCVPort* const cvPort =
(CarlaEngineCVPort*)pData->client->addPort(kEnginePortTypeCV, portName, true, i);
cvPort->setRange(pData->param.ranges[i].min, pData->param.ranges[i].max);
pData->event.portIn->addCVSource(cvPort);
}
}
@@ -1494,7 +1495,9 @@ public:
}
}

void process(const float** const audioIn, float** const audioOut, const float** const, float** const, const uint32_t frames) override
void process(const float** const audioIn, float** const audioOut,
const float** const cvIn, float** const,
const uint32_t frames) override
{
// --------------------------------------------------------------------------------------------------------
// Check if active
@@ -1574,6 +1577,19 @@ public:

} // End of MIDI Input (External)

// ----------------------------------------------------------------------------------------------------
// CV Control Input

for (uint32_t i=0, j=0; i < pData->param.count; ++i)
{
if (pData->param.data[i].type != PARAMETER_INPUT)
continue;

const uint32_t cvIndex = j++;

pData->event.portIn->mixWithCvBuffer(cvIn[cvIndex], frames, i);
}

// ----------------------------------------------------------------------------------------------------
// Event Input (System)

@@ -1636,12 +1652,37 @@ public:
break;

case kEngineControlEventTypeParameter: {
float value;

#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
// via CV
if (event.channel == 0xFF)
{
const uint32_t k = ctrlEvent.param;
CARLA_SAFE_ASSERT_CONTINUE(k < pData->param.count);

if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
{
value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;
}
else
{
if (pData->param.data[k].hints & PARAMETER_IS_LOGARITHMIC)
value = pData->param.ranges[k].getUnnormalizedLogValue(ctrlEvent.value);
else
value = pData->param.ranges[k].getUnnormalizedValue(ctrlEvent.value);

if (pData->param.data[k].hints & PARAMETER_IS_INTEGER)
value = std::rint(value);
}

setParameterValueRT(k, value, true);
continue;
}

// Control backend stuff
if (event.channel == pData->ctrlChannel)
{
float value;

if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
{
value = ctrlEvent.value;
@@ -1692,8 +1733,6 @@ public:
if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
continue;

float value;

if (pData->param.data[k].hints & PARAMETER_IS_BOOLEAN)
{
value = (ctrlEvent.value < 0.5f) ? pData->param.ranges[k].min : pData->param.ranges[k].max;


Loading…
Cancel
Save