| @@ -109,7 +109,7 @@ public: | |||
| /*! | |||
| * Get the plugin's options (currently in use). | |||
| * | |||
| * @see PluginOptions, getAvailableOptions() and setOption() | |||
| * @see PluginOptions, getOptionsAvailable() and setOption() | |||
| */ | |||
| uint getOptionsEnabled() const noexcept; | |||
| @@ -154,7 +154,7 @@ public: | |||
| /*! | |||
| * Get the plugin's latency, in sample frames. | |||
| */ | |||
| uint32_t getLatencyInFrames() const noexcept; | |||
| virtual uint32_t getLatencyInFrames() const noexcept; | |||
| // ------------------------------------------------------------------- | |||
| // Information (count) | |||
| @@ -266,7 +266,7 @@ public: | |||
| * Get the complete plugin chunk data into @a dataPtr. | |||
| * | |||
| * @note Make sure to verify the plugin supports chunks before calling this function! | |||
| * \return The size of the chunk or 0 if invalid. | |||
| * @return The size of the chunk or 0 if invalid. | |||
| * | |||
| * @see setChunkData() | |||
| */ | |||
| @@ -326,6 +326,7 @@ public: | |||
| /*! | |||
| * Get the custom text of the parameter @a parameterId. | |||
| * @see PARAMETER_USES_CUSTOM_TEXT | |||
| */ | |||
| virtual void getParameterText(const uint32_t parameterId, char* const strBuf) const noexcept; | |||
| @@ -436,7 +437,7 @@ public: | |||
| /*! | |||
| * Set a plugin's option. | |||
| * | |||
| * @see getOptions() and getAvailableOptions() | |||
| * @see getOptions() and getOptionsAvailable() | |||
| */ | |||
| virtual void setOption(const uint option, const bool yesNo, const bool sendCallback); | |||
| @@ -845,7 +845,7 @@ const char* CarlaEngine::getUniquePluginName(const char* const name) const | |||
| return sname.dup(); | |||
| } | |||
| const size_t maxNameSize(carla_min<uint>(getMaxClientNameSize(), 0xff, 6) - 6); // 6 = strlen(" (10)") + 1 | |||
| const std::size_t maxNameSize(carla_minWithBase<uint>(getMaxClientNameSize(), 0xff, 6U) - 6); // 6 = strlen(" (10)") + 1 | |||
| if (maxNameSize == 0 || ! isRunning()) | |||
| return sname.dup(); | |||
| @@ -1454,7 +1454,11 @@ void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize) | |||
| carla_debug("CarlaEngine::bufferSizeChanged(%i)", newBufferSize); | |||
| #ifndef BUILD_BRIDGE | |||
| pData->graph.setBufferSize(newBufferSize); | |||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
| { | |||
| pData->graph.setBufferSize(newBufferSize); | |||
| } | |||
| #endif | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| @@ -1473,7 +1477,11 @@ void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||
| carla_debug("CarlaEngine::sampleRateChanged(%g)", newSampleRate); | |||
| #ifndef BUILD_BRIDGE | |||
| pData->graph.setSampleRate(newSampleRate); | |||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
| { | |||
| pData->graph.setSampleRate(newSampleRate); | |||
| } | |||
| #endif | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| @@ -1492,7 +1500,11 @@ void CarlaEngine::offlineModeChanged(const bool isOfflineNow) | |||
| carla_debug("CarlaEngine::offlineModeChanged(%s)", bool2str(isOfflineNow)); | |||
| #ifndef BUILD_BRIDGE | |||
| pData->graph.setOffline(isOfflineNow); | |||
| if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK || | |||
| pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY) | |||
| { | |||
| pData->graph.setOffline(isOfflineNow); | |||
| } | |||
| #endif | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| @@ -646,10 +646,10 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB | |||
| if (oldAudioInCount > 0) | |||
| { | |||
| range = FloatVectorOperations::findMinAndMax(inBuf0, iframes); | |||
| pluginData.insPeak[0] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| pluginData.insPeak[0] = carla_maxLimited<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| range = FloatVectorOperations::findMinAndMax(inBuf1, iframes); | |||
| pluginData.insPeak[1] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| pluginData.insPeak[1] = carla_maxLimited<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| } | |||
| else | |||
| { | |||
| @@ -660,10 +660,10 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB | |||
| if (plugin->getAudioOutCount() > 0) | |||
| { | |||
| range = FloatVectorOperations::findMinAndMax(outBuf[0], iframes); | |||
| pluginData.outsPeak[0] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| pluginData.outsPeak[0] = carla_maxLimited<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| range = FloatVectorOperations::findMinAndMax(outBuf[1], iframes); | |||
| pluginData.outsPeak[1] = carla_max<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| pluginData.outsPeak[1] = carla_maxLimited<float>(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| } | |||
| else | |||
| { | |||
| @@ -33,6 +33,9 @@ CARLA_BACKEND_START_NAMESPACE | |||
| #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return false; } | |||
| #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); setLastError(err); return nullptr; } | |||
| #define CARLA_SAFE_EXCEPTION_RETURN_ERR(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); setLastError(errMsg); return false; } | |||
| #define CARLA_SAFE_EXCEPTION_RETURN_ERRN(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); setLastError(errMsg); return nullptr; } | |||
| // ----------------------------------------------------------------------- | |||
| // InternalEvents | |||
| @@ -162,7 +162,7 @@ int64_t CarlaPlugin::getUniqueId() const noexcept | |||
| uint32_t CarlaPlugin::getLatencyInFrames() const noexcept | |||
| { | |||
| return pData->latency; | |||
| return 0; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -1397,6 +1397,17 @@ void CarlaPlugin::idle() | |||
| #if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE) | |||
| const bool sendOsc(pData->engine->isOscControlRegistered()); | |||
| #endif | |||
| const uint32_t latency(getLatencyInFrames()); | |||
| if (pData->latency.frames != latency) | |||
| { | |||
| carla_stdout("latency changed to %i", latency); | |||
| const ScopedSingleProcessLocker sspl(this, true); | |||
| pData->client->setLatency(latency); | |||
| pData->latency.recreateBuffers(pData->latency.channels, latency); | |||
| } | |||
| const CarlaMutexLocker sl(pData->postRtEvents.mutex); | |||
| @@ -681,6 +681,7 @@ public: | |||
| } | |||
| #endif | |||
| #if 0 // TODO | |||
| void idle() override | |||
| { | |||
| if (fLatencyChanged && fLatencyIndex != -1) | |||
| @@ -712,6 +713,7 @@ public: | |||
| CarlaPlugin::idle(); | |||
| } | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Plugin state | |||
| @@ -1125,6 +1127,7 @@ public: | |||
| if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0)) | |||
| pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK; | |||
| #if 0 // TODO | |||
| // check latency | |||
| if (fLatencyIndex >= 0) | |||
| { | |||
| @@ -1193,6 +1196,7 @@ public: | |||
| fLatencyChanged = false; | |||
| } | |||
| #endif | |||
| bufferSizeChanged(pData->engine->getBufferSize()); | |||
| reloadPrograms(true); | |||
| @@ -1389,11 +1393,13 @@ public: | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| #if 0 // TODO | |||
| if (pData->latency > 0) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioIn.count; ++i) | |||
| FloatVectorOperations::clear(pData->latencyBuffers[i], static_cast<int>(pData->latency)); | |||
| } | |||
| #endif | |||
| #endif | |||
| pData->needsReset = false; | |||
| @@ -1775,6 +1781,7 @@ public: | |||
| } // End of Plugin processing (no events) | |||
| #ifndef BUILD_BRIDGE | |||
| #if 0 // TODO | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Latency, save values for next callback | |||
| @@ -1803,6 +1810,7 @@ public: | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Control Output | |||
| @@ -1943,11 +1951,13 @@ public: | |||
| { | |||
| for (uint32_t k=0; k < frames; ++k) | |||
| { | |||
| #if 0 // TODO | |||
| 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 | |||
| #endif | |||
| bufValue = fAudioInBuffers[isMono ? 0 : i][k]; | |||
| fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); | |||
| @@ -384,6 +384,73 @@ void CarlaPlugin::ProtectedData::ExternalNotes::clear() noexcept | |||
| mutex.unlock(); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // ProtectedData::Latency | |||
| CarlaPlugin::ProtectedData::Latency::Latency() noexcept | |||
| : channels(0), | |||
| frames(0), | |||
| buffers(nullptr) {} | |||
| CarlaPlugin::ProtectedData::Latency::~Latency() noexcept | |||
| { | |||
| clearBuffers(); | |||
| } | |||
| void CarlaPlugin::ProtectedData::Latency::clearBuffers() noexcept | |||
| { | |||
| if (buffers != nullptr) | |||
| { | |||
| for (uint32_t i=0; i < channels; ++i) | |||
| { | |||
| CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); | |||
| delete[] buffers[i]; | |||
| buffers[i] = nullptr; | |||
| } | |||
| delete[] buffers; | |||
| buffers = nullptr; | |||
| } | |||
| channels = 0; | |||
| frames = 0; | |||
| } | |||
| void CarlaPlugin::ProtectedData::Latency::recreateBuffers(const uint32_t newChannels, const uint32_t newFrames) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(channels != newChannels || frames != newFrames,); | |||
| // delete old buffer | |||
| if (buffers != nullptr) | |||
| { | |||
| for (uint32_t i=0; i < channels; ++i) | |||
| { | |||
| CARLA_SAFE_ASSERT_CONTINUE(buffers[i] != nullptr); | |||
| delete[] buffers[i]; | |||
| buffers[i] = nullptr; | |||
| } | |||
| delete[] buffers; | |||
| buffers = nullptr; | |||
| } | |||
| channels = newChannels; | |||
| frames = newFrames; | |||
| if (channels > 0 && frames > 0) | |||
| { | |||
| buffers = new float*[channels]; | |||
| for (uint32_t i=0; i < channels; ++i) | |||
| { | |||
| buffers[i] = new float[frames]; | |||
| FloatVectorOperations::clear(buffers[i], static_cast<int>(frames)); | |||
| } | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| // ProtectedData::PostRtEvents | |||
| @@ -476,10 +543,6 @@ CarlaPlugin::ProtectedData::ProtectedData(CarlaEngine* const eng, const uint idx | |||
| ctrlChannel(0), | |||
| extraHints(0x0), | |||
| transientTryCounter(0), | |||
| latency(0), | |||
| #ifndef BUILD_BRIDGE | |||
| latencyBuffers(nullptr), | |||
| #endif | |||
| name(nullptr), | |||
| filename(nullptr), | |||
| iconName(nullptr), | |||
| @@ -496,6 +559,7 @@ CarlaPlugin::ProtectedData::ProtectedData(CarlaEngine* const eng, const uint idx | |||
| singleMutex(), | |||
| stateSave(), | |||
| extNotes(), | |||
| latency(), | |||
| postRtEvents(), | |||
| postUiEvents(), | |||
| #ifndef BUILD_BRIDGE | |||
| @@ -598,75 +662,15 @@ CarlaPlugin::ProtectedData::~ProtectedData() noexcept | |||
| void CarlaPlugin::ProtectedData::clearBuffers() noexcept | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (latencyBuffers != nullptr) | |||
| { | |||
| CARLA_SAFE_ASSERT(audioIn.count > 0); | |||
| for (uint32_t i=0; i < audioIn.count; ++i) | |||
| { | |||
| CARLA_SAFE_ASSERT_CONTINUE(latencyBuffers[i] != nullptr); | |||
| delete[] latencyBuffers[i]; | |||
| latencyBuffers[i] = nullptr; | |||
| } | |||
| delete[] latencyBuffers; | |||
| latencyBuffers = nullptr; | |||
| latency = 0; | |||
| } | |||
| else | |||
| { | |||
| if (latency != 0) | |||
| { | |||
| carla_safe_assert_int("latency != 0", __FILE__, __LINE__, static_cast<int>(latency)); | |||
| latency = 0; | |||
| } | |||
| } | |||
| #else | |||
| latency = 0; | |||
| #endif | |||
| audioIn.clear(); | |||
| audioOut.clear(); | |||
| cvIn.clear(); | |||
| cvOut.clear(); | |||
| param.clear(); | |||
| event.clear(); | |||
| latency.clearBuffers(); | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| void CarlaPlugin::ProtectedData::recreateLatencyBuffers() | |||
| { | |||
| if (latencyBuffers != nullptr) | |||
| { | |||
| CARLA_SAFE_ASSERT(audioIn.count > 0); | |||
| for (uint32_t i=0; i < audioIn.count; ++i) | |||
| { | |||
| CARLA_SAFE_ASSERT_CONTINUE(latencyBuffers[i] != nullptr); | |||
| delete[] latencyBuffers[i]; | |||
| latencyBuffers[i] = nullptr; | |||
| } | |||
| delete[] latencyBuffers; | |||
| latencyBuffers = nullptr; | |||
| } | |||
| if (audioIn.count > 0 && latency > 0) | |||
| { | |||
| latencyBuffers = new float*[audioIn.count]; | |||
| for (uint32_t i=0; i < audioIn.count; ++i) | |||
| { | |||
| latencyBuffers[i] = new float[latency]; | |||
| FloatVectorOperations::clear(latencyBuffers[i], static_cast<int>(latency)); | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| // Post-poned events | |||
| @@ -34,6 +34,15 @@ using juce::FloatVectorOperations; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| // ----------------------------------------------------------------------- | |||
| // Engine helper macro, sets lastError and returns false/NULL | |||
| #define CARLA_SAFE_ASSERT_RETURN_ERR(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return false; } | |||
| #define CARLA_SAFE_ASSERT_RETURN_ERRN(cond, err) if (! (cond)) { carla_safe_assert(#cond, __FILE__, __LINE__); pData->engine->setLastError(err); return nullptr; } | |||
| #define CARLA_SAFE_EXCEPTION_RETURN_ERR(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return false; } | |||
| #define CARLA_SAFE_EXCEPTION_RETURN_ERRN(excptMsg, errMsg) catch(...) { carla_safe_exception(excptMsg, __FILE__, __LINE__); pData->engine->setLastError(errMsg); return nullptr; } | |||
| // ----------------------------------------------------------------------- | |||
| // Maximum pre-allocated events for some plugin types | |||
| @@ -225,12 +234,6 @@ struct CarlaPlugin::ProtectedData { | |||
| uint extraHints; | |||
| uint transientTryCounter; | |||
| // latency | |||
| uint32_t latency; | |||
| #ifndef BUILD_BRIDGE | |||
| float** latencyBuffers; | |||
| #endif | |||
| // data 1 | |||
| const char* name; | |||
| const char* filename; | |||
| @@ -266,6 +269,20 @@ struct CarlaPlugin::ProtectedData { | |||
| } extNotes; | |||
| struct Latency { | |||
| uint32_t channels; | |||
| uint32_t frames; | |||
| float** buffers; | |||
| Latency() noexcept; | |||
| ~Latency() noexcept; | |||
| void clearBuffers() noexcept; | |||
| void recreateBuffers(const uint32_t newChannels, const uint32_t newFrames); | |||
| CARLA_DECLARE_NON_COPY_STRUCT(Latency) | |||
| } latency; | |||
| struct PostRtEvents { | |||
| CarlaMutex mutex; | |||
| RtLinkedList<PluginPostRtEvent>::Pool dataPool; | |||
| @@ -317,9 +334,6 @@ struct CarlaPlugin::ProtectedData { | |||
| // Buffer functions | |||
| void clearBuffers() noexcept; | |||
| #ifndef BUILD_BRIDGE | |||
| void recreateLatencyBuffers(); | |||
| #endif | |||
| // ------------------------------------------------------------------- | |||
| // Post-poned events | |||
| @@ -1432,6 +1432,7 @@ public: | |||
| } | |||
| } | |||
| #if 0 // TODO | |||
| void idle() override | |||
| { | |||
| if (fLatencyChanged && fLatencyIndex != -1) | |||
| @@ -1463,6 +1464,7 @@ public: | |||
| CarlaPlugin::idle(); | |||
| } | |||
| #endif | |||
| void uiIdle() override | |||
| { | |||
| @@ -2361,6 +2363,7 @@ public: | |||
| pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK; | |||
| } | |||
| #if 0 // TODO | |||
| // check latency | |||
| if (fLatencyIndex >= 0) | |||
| { | |||
| @@ -2429,6 +2432,7 @@ public: | |||
| fLatencyChanged = false; | |||
| } | |||
| #endif | |||
| bufferSizeChanged(pData->engine->getBufferSize()); | |||
| reloadPrograms(true); | |||
| @@ -2730,11 +2734,13 @@ public: | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| #if 0 // TODO | |||
| if (pData->latency > 0) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioIn.count; ++i) | |||
| FloatVectorOperations::clear(pData->latencyBuffers[i], static_cast<int>(pData->latency)); | |||
| } | |||
| #endif | |||
| #endif | |||
| pData->needsReset = false; | |||
| @@ -3340,6 +3346,7 @@ public: | |||
| } // End of Plugin processing (no events) | |||
| #ifndef BUILD_BRIDGE | |||
| #if 0 // TODO | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| // Latency, save values for next callback | |||
| @@ -3368,6 +3375,7 @@ public: | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| #endif | |||
| // -------------------------------------------------------------------------------------------------------- | |||
| @@ -3614,11 +3622,13 @@ public: | |||
| { | |||
| for (uint32_t k=0; k < frames; ++k) | |||
| { | |||
| #if 0 // TODO | |||
| 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 | |||
| #endif | |||
| bufValue = fAudioInBuffers[isMono ? 0 : i][k]; | |||
| fAudioOutBuffers[i][k] = (fAudioOutBuffers[i][k] * pData->postProc.dryWet) + (bufValue * (1.0f - pData->postProc.dryWet)); | |||
| @@ -843,6 +843,7 @@ public: | |||
| deactivate(); | |||
| } | |||
| #if 0 // TODO | |||
| // check latency | |||
| if (pData->hints & PLUGIN_CAN_DRYWET) | |||
| { | |||
| @@ -859,6 +860,7 @@ public: | |||
| pData->recreateLatencyBuffers(); | |||
| #endif | |||
| } | |||
| #endif | |||
| // special plugin fixes | |||
| // 1. IL Harmless - disable threaded processing | |||
| @@ -1061,11 +1063,13 @@ public: | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| #if 0 // TODO | |||
| if (pData->latency > 0) | |||
| { | |||
| for (uint32_t i=0; i < pData->audioIn.count; ++i) | |||
| FloatVectorOperations::clear(pData->latencyBuffers[i], static_cast<int>(pData->latency)); | |||
| } | |||
| #endif | |||
| #endif | |||
| pData->needsReset = false; | |||
| @@ -160,10 +160,10 @@ protected: | |||
| Range<float> range; | |||
| range = FloatVectorOperations::findMinAndMax(inputs[0], static_cast<int>(frames)); | |||
| fOutLeft = carla_max(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| fOutLeft = carla_maxLimited(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| range = FloatVectorOperations::findMinAndMax(inputs[1], static_cast<int>(frames)); | |||
| fOutRight = carla_max(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| fOutRight = carla_maxLimited(std::abs(range.getStart()), std::abs(range.getEnd()), 1.0f); | |||
| } | |||
| private: | |||
| @@ -27,11 +27,11 @@ | |||
| // math functions (base) | |||
| /* | |||
| * Return the lower of 2 values, with 'min' as the minimum possible value. | |||
| * Return the lower of 2 values, with 'min' as the minimum possible value (ie, base). | |||
| */ | |||
| template<typename T> | |||
| static inline | |||
| const T& carla_min(const T& v1, const T& v2, const T& min) noexcept | |||
| const T& carla_minWithBase(const T& v1, const T& v2, const T& min) noexcept | |||
| { | |||
| return ((v1 <= min || v2 <= min) ? min : (v1 < v2 ? v1 : v2)); | |||
| } | |||
| @@ -56,11 +56,11 @@ T carla_minPositive(const T& v1, const T& v2) noexcept | |||
| } | |||
| /* | |||
| * Return the higher of 2 values, with 'max' as the maximum possible value. | |||
| * Return the higher of 2 values, with 'max' as the maximum possible value (ie, limit). | |||
| */ | |||
| template<typename T> | |||
| static inline | |||
| const T& carla_max(const T& v1, const T& v2, const T& max) noexcept | |||
| const T& carla_maxLimited(const T& v1, const T& v2, const T& max) noexcept | |||
| { | |||
| return ((v1 >= max || v2 >= max) ? max : (v1 > v2 ? v1 : v2)); | |||
| } | |||