Browse Source

Implement latency in LADSPA plugins

tags/1.9.4
falkTX 11 years ago
parent
commit
c83c5e4ac5
1 changed files with 67 additions and 55 deletions
  1. +67
    -55
      source/backend/plugin/LadspaPlugin.cpp

+ 67
- 55
source/backend/plugin/LadspaPlugin.cpp View File

@@ -44,7 +44,8 @@ public:
fRdfDescriptor(nullptr), fRdfDescriptor(nullptr),
fAudioInBuffers(nullptr), fAudioInBuffers(nullptr),
fAudioOutBuffers(nullptr), fAudioOutBuffers(nullptr),
fParamBuffers(nullptr)
fParamBuffers(nullptr),
fLatencyIndex(-1)
{ {
carla_debug("LadspaPlugin::LadspaPlugin(%p, %i)", engine, id); carla_debug("LadspaPlugin::LadspaPlugin(%p, %i)", engine, id);
} }
@@ -189,7 +190,8 @@ public:


if (! isDssiVst) if (! isDssiVst)
{ {
options |= PLUGIN_OPTION_FIXED_BUFFERS;
if (fLatencyIndex == -1)
options |= PLUGIN_OPTION_FIXED_BUFFERS;


if (pData->engine->getProccessMode() != ENGINE_PROCESS_MODE_CONTINUOUS_RACK) if (pData->engine->getProccessMode() != ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{ {
@@ -669,6 +671,7 @@ public:
step = 1.0f; step = 1.0f;
stepSmall = 1.0f; stepSmall = 1.0f;
stepLarge = 1.0f; stepLarge = 1.0f;
fLatencyIndex = static_cast<int32_t>(j);
pData->param.special[j] = PARAMETER_SPECIAL_LATENCY; pData->param.special[j] = PARAMETER_SPECIAL_LATENCY;
} }
else else
@@ -779,60 +782,55 @@ public:
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK; pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;


// check latency // check latency
#ifdef BUILD_BRIDGE
if (aIns > 0 && aOuts > 0)
#else
if (pData->hints & PLUGIN_CAN_DRYWET)
#endif
if (fLatencyIndex >= 0)
{ {
for (uint32_t i=0; i < pData->param.count; ++i)
{
if (pData->param.special[i] != PARAMETER_SPECIAL_LATENCY)
continue;
// we need to pre-run the plugin so it can update its latency control-port


// we need to pre-run the plugin so it can update its latency control-port
float tmpIn[aIns][2];
float tmpOut[aOuts][2];


float tmpIn[aIns][2];
float tmpOut[aOuts][2];
for (uint32_t j=0; j < aIns; ++j)
{
tmpIn[j][0] = 0.0f;
tmpIn[j][1] = 0.0f;


for (uint32_t j=0; j < aIns; ++j)
{
tmpIn[j][0] = 0.0f;
tmpIn[j][1] = 0.0f;
fDescriptor->connect_port(fHandle, pData->audioIn.ports[j].rindex, tmpIn[j]);
}


fDescriptor->connect_port(fHandle, pData->audioIn.ports[j].rindex, tmpIn[j]);
}
for (uint32_t j=0; j < aOuts; ++j)
{
tmpOut[j][0] = 0.0f;
tmpOut[j][1] = 0.0f;


for (uint32_t j=0; j < aOuts; ++j)
{
tmpOut[j][0] = 0.0f;
tmpOut[j][1] = 0.0f;
fDescriptor->connect_port(fHandle, pData->audioOut.ports[j].rindex, tmpOut[j]);
}


fDescriptor->connect_port(fHandle, pData->audioOut.ports[j].rindex, tmpOut[j]);
}
if (fDescriptor->activate != nullptr)
fDescriptor->activate(fHandle);


if (fDescriptor->activate != nullptr)
fDescriptor->activate(fHandle);
fDescriptor->run(fHandle, 2);


fDescriptor->run(fHandle, 2);
if (fDescriptor->deactivate != nullptr)
fDescriptor->deactivate(fHandle);


if (fDescriptor->deactivate != nullptr)
fDescriptor->deactivate(fHandle);
const int32_t latency(static_cast<int32_t>(fParamBuffers[fLatencyIndex]));


// TODO: check >= 0
const uint32_t latency = (uint32_t)fParamBuffers[i];
if (latency >= 0)
{
const uint32_t ulatency(static_cast<uint32_t>(latency));


if (pData->latency != latency)
if (pData->latency != ulatency)
{ {
pData->latency = latency;
pData->client->setLatency(latency);
pData->latency = ulatency;
pData->client->setLatency(ulatency);
carla_stdout("latency = %i", latency);
#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
pData->recreateLatencyBuffers(); pData->recreateLatencyBuffers();
#endif #endif
} }

break;
} }
else
carla_safe_assert_int("latency >= 0", __FILE__, __LINE__, latency);
} }


bufferSizeChanged(pData->engine->getBufferSize()); bufferSizeChanged(pData->engine->getBufferSize());
@@ -1073,7 +1071,27 @@ public:


} // End of Plugin processing (no events) } // End of Plugin processing (no events)


CARLA_PROCESS_CONTINUE_CHECK;
// --------------------------------------------------------------------------------------------------------
// Latency, save values for next callback

if (pData->latency > 0)
{
if (pData->latency <= frames)
{
for (uint32_t i=0; i < pData->audioIn.count; ++i)
FLOAT_COPY(pData->latencyBuffers[i], inBuffer[i]+(frames-pData->latency), pData->latency);
}
else
{
for (uint32_t i=0, j, k; i < pData->audioIn.count; ++i)
{
for (k=0; k < pData->latency-frames; ++k)
pData->latencyBuffers[i][k] = pData->latencyBuffers[i][k+frames];
for (j=0; k < pData->latency; ++j, ++k)
pData->latencyBuffers[i][k] = inBuffer[i][j];
}
}
}


// -------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------
// Control Output // Control Output
@@ -1157,6 +1175,7 @@ public:
{ {
const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f; const bool doDryWet = (pData->hints & PLUGIN_CAN_DRYWET) != 0 && pData->postProc.dryWet != 1.0f;
const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f); const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && (pData->postProc.balanceLeft != -1.0f || pData->postProc.balanceRight != 1.0f);
const bool isMono = (pData->audioIn.count == 1);


bool isPair; bool isPair;
float bufValue, oldBufLeft[doBalance ? frames : 1]; float bufValue, oldBufLeft[doBalance ? frames : 1];
@@ -1168,13 +1187,13 @@ public:
{ {
for (uint32_t k=0; k < frames; ++k) for (uint32_t k=0; k < frames; ++k)
{ {
// TODO
//if (k < pData->latency && pData->latency < frames)
// bufValue = (pData->audioIn.count == 1) ? pData->latencyBuffers[0][k] : pData->latencyBuffers[i][k];
//else
// bufValue = (pData->audioIn.count == 1) ? inBuffer[0][k-m_latency] : inBuffer[i][k-m_latency];
if (k < pData->latency)
bufValue = pData->latencyBuffers[isMono ? 0 : i][k];
else if (pData->latency < frames)
bufValue = fAudioInBuffers[isMono ? 0 : i][k-pData->latency];
else
bufValue = fAudioInBuffers[isMono ? 0 : i][k];


bufValue = fAudioInBuffers[(pData->audioIn.count == 1) ? 0 : i][k];
fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet));
} }
} }
@@ -1217,14 +1236,6 @@ public:
} }
} }


#if 0
// Latency, save values for next callback, TODO
if (pData->latency > 0 && pData->latency < frames)
{
for (i=0; i < pData->audioIn.count; ++i)
FLOAT_COPY(pData->latencyBuffers[i], inBuffer[i] + (frames - pData->latency), pData->latency);
}
#endif
} // End of Post-processing } // End of Post-processing


#else // BUILD_BRIDGE #else // BUILD_BRIDGE
@@ -1481,7 +1492,7 @@ public:
// set default options // set default options
pData->options = 0x0; pData->options = 0x0;


if (isDssiVst)
if (fLatencyIndex >= 0 || isDssiVst)
pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;


if (pData->engine->getOptions().forceStereo) if (pData->engine->getOptions().forceStereo)
@@ -1499,7 +1510,7 @@ public:
pData->options = pData->loadSettings(pData->options, getOptionsAvailable()); pData->options = pData->loadSettings(pData->options, getOptionsAvailable());


// ignore settings, we need this anyway // ignore settings, we need this anyway
if (isDssiVst)
if (fLatencyIndex >= 0 || isDssiVst)
pData->options |= PLUGIN_OPTION_FIXED_BUFFERS; pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
#endif #endif
} }
@@ -1518,6 +1529,7 @@ private:
float** fAudioInBuffers; float** fAudioInBuffers;
float** fAudioOutBuffers; float** fAudioOutBuffers;
float* fParamBuffers; float* fParamBuffers;
int32_t fLatencyIndex; // -1 if invalid


CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LadspaPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LadspaPlugin)
}; };


Loading…
Cancel
Save