diff --git a/c++/carla-backend/carla_native.cpp b/c++/carla-backend/carla_native.cpp index f2d9041..117ea1f 100644 --- a/c++/carla-backend/carla_native.cpp +++ b/c++/carla-backend/carla_native.cpp @@ -1294,7 +1294,7 @@ public: { 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)); else outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); diff --git a/c++/carla-backend/carla_plugin.h b/c++/carla-backend/carla_plugin.h index 44d8ab6..c247060 100644 --- a/c++/carla-backend/carla_plugin.h +++ b/c++/carla-backend/carla_plugin.h @@ -233,6 +233,10 @@ public: #endif m_ctrlInChannel = 0; + m_latency = 0; + m_tempBufferIn = nullptr; + m_tempBufferOut = nullptr; + #ifndef BUILD_BRIDGE osc.data.path = nullptr; osc.data.source = nullptr; @@ -305,6 +309,22 @@ public: 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; } @@ -1367,7 +1387,49 @@ public: */ 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_filename; - int8_t m_ctrlInChannel; + int8_t m_ctrlInChannel; + + uint32_t m_latency; + float** m_tempBufferIn; + float** m_tempBufferOut; // ------------------------------------------------------------------- // Storage Data diff --git a/c++/carla-backend/dssi.cpp b/c++/carla-backend/dssi.cpp index 7fe5532..bcc0665 100644 --- a/c++/carla-backend/dssi.cpp +++ b/c++/carla-backend/dssi.cpp @@ -699,7 +699,7 @@ public: // check latency { bool hasLatency = false; - uint32_t latency = 0; + m_latency = 0; for (uint32_t i=0; i < param.count; i++) { @@ -731,7 +731,7 @@ public: ldescriptor->run(handle, 2); ldescriptor->deactivate(handle); - latency = rint(paramBuffers[i]); + m_latency = rint(paramBuffers[i]); hasLatency = true; break; } @@ -740,7 +740,7 @@ public: if (hasLatency) { for (uint32_t i=0; i < aIn.count; i++) - aIn.ports[i]->setLatency(latency); + aIn.ports[i]->setLatency(m_latency); x_client->recomputeLatencies(); } @@ -748,6 +748,7 @@ public: reloadPrograms(true); + recreateTempBuffers(x_engine->getBufferSize()); x_client->activate(); qDebug("DssiPlugin::reload() - end"); @@ -1303,7 +1304,7 @@ public: { 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)); else outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); diff --git a/c++/carla-backend/ladspa.cpp b/c++/carla-backend/ladspa.cpp index 3104682..cea6f37 100644 --- a/c++/carla-backend/ladspa.cpp +++ b/c++/carla-backend/ladspa.cpp @@ -668,7 +668,7 @@ public: // check latency { bool hasLatency = false; - uint32_t latency = 0; + m_latency = 0; for (uint32_t i=0; i < param.count; i++) { @@ -700,7 +700,7 @@ public: descriptor->run(handle, 2); descriptor->deactivate(handle); - latency = rint(paramBuffers[i]); + m_latency = rint(paramBuffers[i]); hasLatency = true; break; } @@ -709,12 +709,13 @@ public: if (hasLatency) { for (uint32_t i=0; i < aIn.count; i++) - aIn.ports[i]->setLatency(latency); + aIn.ports[i]->setLatency(m_latency); x_client->recomputeLatencies(); } } + recreateTempBuffers(x_engine->getBufferSize()); x_client->activate(); qDebug("LadspaPlugin::reload() - end"); @@ -979,7 +980,7 @@ public: { 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)); else outBuffer[i][k] = (outBuffer[i][k]*x_dryWet)+(inBuffer[i][k]*(1.0-x_dryWet)); diff --git a/c++/carla-backend/lv2.cpp b/c++/carla-backend/lv2.cpp index 64cec8f..799b8bb 100644 --- a/c++/carla-backend/lv2.cpp +++ b/c++/carla-backend/lv2.cpp @@ -1740,7 +1740,7 @@ public: // check latency { bool hasLatency = false; - uint32_t latency = 0; + m_latency = 0; for (uint32_t i=0; i < param.count; i++) { @@ -1763,7 +1763,7 @@ public: descriptor->run(handle, 0); descriptor->deactivate(handle); - latency = rint(paramBuffers[i]); + m_latency = rint(paramBuffers[i]); hasLatency = true; break; } @@ -1772,7 +1772,7 @@ public: if (hasLatency) { for (uint32_t i=0; i < aIn.count; i++) - aIn.ports[i]->setLatency(latency); + aIn.ports[i]->setLatency(m_latency); x_client->recomputeLatencies(); } @@ -1780,6 +1780,7 @@ public: reloadPrograms(true); + recreateTempBuffers(x_engine->getBufferSize()); x_client->activate(); qDebug("Lv2Plugin::reload() - end"); @@ -2580,7 +2581,7 @@ public: { 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)); else 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) { lv2Options.bufferSize = newBufferSize; + + CarlaPlugin::bufferSizeChanged(newBufferSize); } // ------------------------------------------------------------------- diff --git a/c++/carla-backend/vst.cpp b/c++/carla-backend/vst.cpp index 5aa4e7d..d23c597 100644 --- a/c++/carla-backend/vst.cpp +++ b/c++/carla-backend/vst.cpp @@ -734,19 +734,20 @@ public: #ifdef VESTIGE_HEADER char* const empty3Ptr = &effect->empty3[0]; int32_t* initialDelayPtr = (int32_t*)empty3Ptr; - uint32_t latency = *initialDelayPtr; + m_latency = *initialDelayPtr; #else - uint32_t latency = effect->initialDelay; + m_latency = effect->initialDelay; #endif for (uint32_t i=0; i < aIn.count; i++) - aIn.ports[i]->setLatency(latency); + aIn.ports[i]->setLatency(m_latency); x_client->recomputeLatencies(); } reloadPrograms(true); + recreateTempBuffers(x_engine->getBufferSize()); x_client->activate(); qDebug("VstPlugin::reload() - end"); @@ -1209,6 +1210,12 @@ public: 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); } @@ -1260,7 +1267,7 @@ public: bool do_balance = (m_hints & PLUGIN_CAN_BALANCE) > 0 && (x_balanceLeft != -1.0 || x_balanceRight != 1.0); 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++) { @@ -1269,10 +1276,12 @@ public: { 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 - 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]); } } + + // 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 { @@ -1376,6 +1392,8 @@ public: if (m_active) effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f); + + CarlaPlugin::bufferSizeChanged(newBufferSize); } // -------------------------------------------------------------------