Browse Source

Carla: Initial code for dry/wet latency compensation, working for VST

tags/v0.9.0
falkTX 13 years ago
parent
commit
5fc1f1479a
6 changed files with 111 additions and 22 deletions
  1. +1
    -1
      c++/carla-backend/carla_native.cpp
  2. +68
    -2
      c++/carla-backend/carla_plugin.h
  3. +5
    -4
      c++/carla-backend/dssi.cpp
  4. +5
    -4
      c++/carla-backend/ladspa.cpp
  5. +7
    -4
      c++/carla-backend/lv2.cpp
  6. +25
    -7
      c++/carla-backend/vst.cpp

+ 1
- 1
c++/carla-backend/carla_native.cpp View File

@@ -1294,7 +1294,7 @@ public:
{ {
for (k=0; k < frames; k++) for (k=0; k < frames; k++)
{ {
if (aOut.count == 1)
if (aIn.count == 1)
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet));
else else
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet));


+ 68
- 2
c++/carla-backend/carla_plugin.h View File

@@ -233,6 +233,10 @@ public:
#endif #endif
m_ctrlInChannel = 0; m_ctrlInChannel = 0;


m_latency = 0;
m_tempBufferIn = nullptr;
m_tempBufferOut = nullptr;

#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
osc.data.path = nullptr; osc.data.path = nullptr;
osc.data.source = nullptr; osc.data.source = nullptr;
@@ -305,6 +309,22 @@ public:
custom.clear(); custom.clear();
} }


if (m_tempBufferIn)
{
for (uint32_t i=0; i < aIn.count; i++)
delete[] m_tempBufferIn[i];

delete[] m_tempBufferIn;
}

if (m_tempBufferOut)
{
for (uint32_t i=0; i < aOut.count; i++)
delete[] m_tempBufferOut[i];

delete[] m_tempBufferOut;
}

m_count -= 1; m_count -= 1;
} }


@@ -1367,7 +1387,49 @@ public:
*/ */
virtual void bufferSizeChanged(const uint32_t newBufferSize) virtual void bufferSizeChanged(const uint32_t newBufferSize)
{ {
Q_UNUSED(newBufferSize);
recreateTempBuffers(newBufferSize);
}

/*!
* Recreate temporary audio buffers.
*/
void recreateTempBuffers(const uint32_t bufferSize)
{
if (m_tempBufferIn)
{
for (uint32_t i=0; i < aIn.count; i++)
delete[] m_tempBufferIn[i];

delete[] m_tempBufferIn;
}

if (m_tempBufferOut)
{
for (uint32_t i=0; i < aOut.count; i++)
delete[] m_tempBufferOut[i];

delete[] m_tempBufferOut;
}

if (aIn.count > 0)
{
m_tempBufferIn = new float* [aIn.count];

for (uint32_t i=0; i < aIn.count; i++)
m_tempBufferIn[i] = new float [bufferSize];
}
else
m_tempBufferIn = nullptr;

if (aOut.count > 0)
{
m_tempBufferOut = new float* [aOut.count];

for (uint32_t i=0; i < aOut.count; i++)
m_tempBufferOut[i] = new float [bufferSize];
}
else
m_tempBufferOut = nullptr;
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -2177,7 +2239,11 @@ protected:
const char* m_name; const char* m_name;
const char* m_filename; const char* m_filename;


int8_t m_ctrlInChannel;
int8_t m_ctrlInChannel;

uint32_t m_latency;
float** m_tempBufferIn;
float** m_tempBufferOut;


// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Storage Data // Storage Data


+ 5
- 4
c++/carla-backend/dssi.cpp View File

@@ -699,7 +699,7 @@ public:
// check latency // check latency
{ {
bool hasLatency = false; bool hasLatency = false;
uint32_t latency = 0;
m_latency = 0;


for (uint32_t i=0; i < param.count; i++) for (uint32_t i=0; i < param.count; i++)
{ {
@@ -731,7 +731,7 @@ public:
ldescriptor->run(handle, 2); ldescriptor->run(handle, 2);
ldescriptor->deactivate(handle); ldescriptor->deactivate(handle);


latency = rint(paramBuffers[i]);
m_latency = rint(paramBuffers[i]);
hasLatency = true; hasLatency = true;
break; break;
} }
@@ -740,7 +740,7 @@ public:
if (hasLatency) if (hasLatency)
{ {
for (uint32_t i=0; i < aIn.count; i++) for (uint32_t i=0; i < aIn.count; i++)
aIn.ports[i]->setLatency(latency);
aIn.ports[i]->setLatency(m_latency);


x_client->recomputeLatencies(); x_client->recomputeLatencies();
} }
@@ -748,6 +748,7 @@ public:


reloadPrograms(true); reloadPrograms(true);


recreateTempBuffers(x_engine->getBufferSize());
x_client->activate(); x_client->activate();


qDebug("DssiPlugin::reload() - end"); qDebug("DssiPlugin::reload() - end");
@@ -1303,7 +1304,7 @@ public:
{ {
for (k=0; k < frames; k++) for (k=0; k < frames; k++)
{ {
if (aOut.count == 1)
if (aIn.count == 1)
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet));
else else
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet));


+ 5
- 4
c++/carla-backend/ladspa.cpp View File

@@ -668,7 +668,7 @@ public:
// check latency // check latency
{ {
bool hasLatency = false; bool hasLatency = false;
uint32_t latency = 0;
m_latency = 0;


for (uint32_t i=0; i < param.count; i++) for (uint32_t i=0; i < param.count; i++)
{ {
@@ -700,7 +700,7 @@ public:
descriptor->run(handle, 2); descriptor->run(handle, 2);
descriptor->deactivate(handle); descriptor->deactivate(handle);


latency = rint(paramBuffers[i]);
m_latency = rint(paramBuffers[i]);
hasLatency = true; hasLatency = true;
break; break;
} }
@@ -709,12 +709,13 @@ public:
if (hasLatency) if (hasLatency)
{ {
for (uint32_t i=0; i < aIn.count; i++) for (uint32_t i=0; i < aIn.count; i++)
aIn.ports[i]->setLatency(latency);
aIn.ports[i]->setLatency(m_latency);


x_client->recomputeLatencies(); x_client->recomputeLatencies();
} }
} }


recreateTempBuffers(x_engine->getBufferSize());
x_client->activate(); x_client->activate();


qDebug("LadspaPlugin::reload() - end"); qDebug("LadspaPlugin::reload() - end");
@@ -979,7 +980,7 @@ public:
{ {
for (k=0; k < frames; k++) for (k=0; k < frames; k++)
{ {
if (aOut.count == 1)
if (aIn.count == 1)
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet));
else else
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet));


+ 7
- 4
c++/carla-backend/lv2.cpp View File

@@ -1740,7 +1740,7 @@ public:
// check latency // check latency
{ {
bool hasLatency = false; bool hasLatency = false;
uint32_t latency = 0;
m_latency = 0;


for (uint32_t i=0; i < param.count; i++) for (uint32_t i=0; i < param.count; i++)
{ {
@@ -1763,7 +1763,7 @@ public:
descriptor->run(handle, 0); descriptor->run(handle, 0);
descriptor->deactivate(handle); descriptor->deactivate(handle);


latency = rint(paramBuffers[i]);
m_latency = rint(paramBuffers[i]);
hasLatency = true; hasLatency = true;
break; break;
} }
@@ -1772,7 +1772,7 @@ public:
if (hasLatency) if (hasLatency)
{ {
for (uint32_t i=0; i < aIn.count; i++) for (uint32_t i=0; i < aIn.count; i++)
aIn.ports[i]->setLatency(latency);
aIn.ports[i]->setLatency(m_latency);


x_client->recomputeLatencies(); x_client->recomputeLatencies();
} }
@@ -1780,6 +1780,7 @@ public:


reloadPrograms(true); reloadPrograms(true);


recreateTempBuffers(x_engine->getBufferSize());
x_client->activate(); x_client->activate();


qDebug("Lv2Plugin::reload() - end"); qDebug("Lv2Plugin::reload() - end");
@@ -2580,7 +2581,7 @@ public:
{ {
for (k=0; k < frames; k++) for (k=0; k < frames; k++)
{ {
if (aOut.count == 1)
if (aIn.count == 1)
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet));
else else
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet));
@@ -2761,6 +2762,8 @@ public:
void bufferSizeChanged(const uint32_t newBufferSize) void bufferSizeChanged(const uint32_t newBufferSize)
{ {
lv2Options.bufferSize = newBufferSize; lv2Options.bufferSize = newBufferSize;

CarlaPlugin::bufferSizeChanged(newBufferSize);
} }


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


+ 25
- 7
c++/carla-backend/vst.cpp View File

@@ -734,19 +734,20 @@ public:
#ifdef VESTIGE_HEADER #ifdef VESTIGE_HEADER
char* const empty3Ptr = &effect->empty3[0]; char* const empty3Ptr = &effect->empty3[0];
int32_t* initialDelayPtr = (int32_t*)empty3Ptr; int32_t* initialDelayPtr = (int32_t*)empty3Ptr;
uint32_t latency = *initialDelayPtr;
m_latency = *initialDelayPtr;
#else #else
uint32_t latency = effect->initialDelay;
m_latency = effect->initialDelay;
#endif #endif


for (uint32_t i=0; i < aIn.count; i++) for (uint32_t i=0; i < aIn.count; i++)
aIn.ports[i]->setLatency(latency);
aIn.ports[i]->setLatency(m_latency);


x_client->recomputeLatencies(); x_client->recomputeLatencies();
} }


reloadPrograms(true); reloadPrograms(true);


recreateTempBuffers(x_engine->getBufferSize());
x_client->activate(); x_client->activate();


qDebug("VstPlugin::reload() - end"); qDebug("VstPlugin::reload() - end");
@@ -1209,6 +1210,12 @@ public:
midiEventCount = MAX_MIDI_CHANNELS*2; midiEventCount = MAX_MIDI_CHANNELS*2;
} }


for (i=0; i < aIn.count; i++)
memset(m_tempBufferIn[i], 0, sizeof(float)*x_engine->getBufferSize());

for (i=0; i < aOut.count; i++)
memset(m_tempBufferOut[i], 0, sizeof(float)*x_engine->getBufferSize());

effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f); effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
} }


@@ -1260,7 +1267,7 @@ public:
bool do_balance = (m_hints & PLUGIN_CAN_BALANCE) > 0 && (x_balanceLeft != -1.0 || x_balanceRight != 1.0); bool do_balance = (m_hints & PLUGIN_CAN_BALANCE) > 0 && (x_balanceLeft != -1.0 || x_balanceRight != 1.0);


double bal_rangeL, bal_rangeR; double bal_rangeL, bal_rangeR;
float oldBufLeft[do_balance ? frames : 0];
float bufValue, oldBufLeft[do_balance ? frames : 0];


for (i=0; i < aOut.count; i++) for (i=0; i < aOut.count; i++)
{ {
@@ -1269,10 +1276,12 @@ public:
{ {
for (k=0; k < frames; k++) for (k=0; k < frames; k++)
{ {
if (aOut.count == 1)
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[0][k]*(1.0-x_dryWet));
if (k < m_latency && m_latency < frames)
bufValue = (aIn.count == 1) ? m_tempBufferIn[0][k] : m_tempBufferIn[i][k];
else else
outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet));
bufValue = (aIn.count == 1) ? inBuffer[0][k-m_latency] : inBuffer[i][k-m_latency];

outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(bufValue*(1.0-x_dryWet));
} }
} }


@@ -1316,6 +1325,13 @@ public:
aOutsPeak[i] = abs(outBuffer[i][k]); aOutsPeak[i] = abs(outBuffer[i][k]);
} }
} }

// Latency, save values for next callback
if (m_latency > 0 && m_latency < frames)
{
for (i=0; i < aIn.count; i++)
memcpy(m_tempBufferIn[i], inBuffer[i] + (frames - m_latency), sizeof(float)*m_latency);
}
} }
else else
{ {
@@ -1376,6 +1392,8 @@ public:


if (m_active) if (m_active)
effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f); effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);

CarlaPlugin::bufferSizeChanged(newBufferSize);
} }


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


Loading…
Cancel
Save