Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optional memory optomizations #556

Merged
merged 3 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ namespace dsp
template <typename Callable,
typename Fn = Decay<Callable>,
IntIfValidConversion<Callable> = 0>
FixedSizeFunction (Callable&& callable)
FixedSizeFunction (Callable&& callable) // NOLINT
{
static_assert (sizeof (Fn) <= len,
"The requested function cannot fit in this FixedSizeFunction");
Expand All @@ -137,6 +137,7 @@ namespace dsp

auto* ptr = new (&storage) Fn (std::forward<Callable> (callable));
jassertquiet ((void*) ptr == (void*) &storage);
ignoreUnused (ptr);
}

/** Move constructor. */
Expand All @@ -148,7 +149,7 @@ namespace dsp

/** Converting constructor from smaller FixedSizeFunctions. */
template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>
FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept // NOLINT
: vtable (other.vtable)
{
move (std::move (other));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,51 @@ namespace chowdsp
template <typename FloatType, typename ValueSmoothingTypes>
void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::setParameterHandle (std::atomic<float>* handle)
{
#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
#if JUCE_MODULE_AVAILABLE_chowdsp_parameters
modulatableParameterHandle = nullptr;
#endif

parameterHandle = handle;
reset (parameterHandle->load());
#endif
}

#if JUCE_MODULE_AVAILABLE_chowdsp_parameters
template <typename FloatType, typename ValueSmoothingTypes>
void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::setParameterHandle ([[maybe_unused]] const FloatParameter* handle)
{
parameterHandle = nullptr;

#if JUCE_MODULE_AVAILABLE_chowdsp_parameters
modulatableParameterHandle = handle;
reset (modulatableParameterHandle->getCurrentValue());
#endif
}
#endif

template <typename FloatType, typename ValueSmoothingTypes>
void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::prepare (double fs, int samplesPerBlock, bool useInternalVector)
{
sampleRate = fs;
if (useInternalVector)
{
#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
buffer.resize ((size_t) samplesPerBlock, {});
bufferData = buffer.data();
#else
jassertfalse;
#endif
}
smoother.reset (sampleRate, rampLengthInSeconds);

#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
if (parameterHandle != nullptr)
reset (parameterHandle->load());
#if JUCE_MODULE_AVAILABLE_chowdsp_parameters
else if (modulatableParameterHandle != nullptr)
reset (modulatableParameterHandle->getCurrentValue());
#endif
else
#endif
reset();
}

Expand All @@ -53,6 +63,7 @@ void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::reset (FloatType reset
template <typename FloatType, typename ValueSmoothingTypes>
void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::reset()
{
#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
if (parameterHandle != nullptr)
{
reset ((FloatType) parameterHandle->load());
Expand All @@ -64,6 +75,7 @@ void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::reset()
}
#endif
else
#endif
{
reset (getCurrentValue());
}
Expand All @@ -81,6 +93,7 @@ void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::setRampLength (double
template <typename FloatType, typename ValueSmoothingTypes>
void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::process (int numSamples)
{
#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
if (parameterHandle != nullptr)
{
process ((FloatType) parameterHandle->load(), numSamples);
Expand All @@ -92,6 +105,7 @@ void SmoothedBufferValue<FloatType, ValueSmoothingTypes>::process (int numSample
}
#endif
else
#endif
{
// you must set a parameter handle that is not nullptr using setParameterHandle
// before calling the method!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ namespace juce

namespace chowdsp
{
#ifndef DOXYGEN
class FloatParameter;
#endif

/**
* Template class for smoothing a value over a series of buffers.
* This can be used with raw values or with parameter handles.
Expand All @@ -38,13 +34,15 @@ class SmoothedBufferValue
*/
void setParameterHandle (std::atomic<float>* handle);

#if JUCE_MODULE_AVAILABLE_chowdsp_parameters
/**
* Sets a parameter handle for this buffer to use for smoothing.
* Note that the parameter handle must not be deleted before this object!
*
* @param handle A parameter handle to use for smoothing
*/
void setParameterHandle (const FloatParameter* handle);
#endif

/**
* Prepare the smoother to process samples with a given sample rate
Expand Down Expand Up @@ -98,23 +96,34 @@ class SmoothedBufferValue
* If using a custom mapping function, make sure this is set properly before calling
* `prepare()` or `reset()`.
*/
std::function<FloatType (FloatType)> mappingFunction = [] (auto x)
#if CHOWDSP_SMOOTHED_BUFFER_SMALL
using MappingFunction = juce::dsp::FixedSizeFunction<16, FloatType (FloatType)>;
#else
using MappingFunction = std::function<FloatType (FloatType)>;
#endif
MappingFunction mappingFunction = [] (auto x)
{ return x; };

private:
#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
#if ! CHOWDSP_NO_XSIMD
std::vector<FloatType, xsimd::default_allocator<FloatType>> buffer;
#else
std::vector<FloatType> buffer;
#endif
#endif
FloatType* bufferData = nullptr;

juce::SmoothedValue<FloatType, ValueSmoothingType> smoother;
bool isCurrentlySmoothing = false;

#if ! CHOWDSP_SMOOTHED_BUFFER_SMALL
std::atomic<float>* parameterHandle = nullptr;

#if JUCE_MODULE_AVAILABLE_chowdsp_parameters
const FloatParameter* modulatableParameterHandle = nullptr;
#endif
#endif

double sampleRate = 48000.0;
double rampLengthInSeconds = 0.05;
Expand Down
40 changes: 20 additions & 20 deletions modules/dsp/chowdsp_dsp_utils/Delay/chowdsp_DelayInterpolation.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
{
}

template <typename SampleType, typename NumericType = SampleTypeHelpers::NumericType<SampleType>>
template <typename SampleType, typename NumericType = SampleTypeHelpers::NumericType<SampleType>, typename StorageType = SampleType>
inline SampleType call (const SampleType* buffer, int delayInt, NumericType /*delayFrac*/ = {}, const SampleType& /*state*/ = {})
{
return buffer[delayInt];
return static_cast<SampleType> (buffer[delayInt]);

Check warning on line 26 in modules/dsp/chowdsp_dsp_utils/Delay/chowdsp_DelayInterpolation.h

View check run for this annotation

Codecov / codecov/patch

modules/dsp/chowdsp_dsp_utils/Delay/chowdsp_DelayInterpolation.h#L26

Added line #L26 was not covered by tests
}
};

Expand All @@ -40,14 +40,14 @@
{
}

template <typename SampleType, typename NumericType>
inline SampleType call (const SampleType* buffer, int delayInt, NumericType delayFrac, const SampleType& /*state*/ = {})
template <typename SampleType, typename NumericType, typename StorageType = SampleType>
inline SampleType call (const StorageType* buffer, int delayInt, NumericType delayFrac, const SampleType& /*state*/ = {})
{
auto index1 = delayInt;
auto index2 = index1 + 1;

auto value1 = buffer[index1];
auto value2 = buffer[index2];
auto value1 = static_cast<SampleType> (buffer[index1]);
auto value2 = static_cast<SampleType> (buffer[index2]);

return value1 + (SampleType) delayFrac * (value2 - value1);
}
Expand All @@ -71,18 +71,18 @@
}
}

template <typename SampleType, typename NumericType>
inline SampleType call (const SampleType* buffer, int delayInt, NumericType delayFrac, const SampleType& /*state*/ = {})
template <typename SampleType, typename NumericType, typename StorageType = SampleType>
inline SampleType call (const StorageType* buffer, int delayInt, NumericType delayFrac, const SampleType& /*state*/ = {})
{
auto index1 = delayInt;
auto index2 = index1 + 1;
auto index3 = index2 + 1;
auto index4 = index3 + 1;

auto value1 = buffer[index1];
auto value2 = buffer[index2];
auto value3 = buffer[index3];
auto value4 = buffer[index4];
auto value1 = static_cast<SampleType> (buffer[index1]);
auto value2 = static_cast<SampleType> (buffer[index2]);
auto value3 = static_cast<SampleType> (buffer[index3]);
auto value4 = static_cast<SampleType> (buffer[index4]);

auto d1 = delayFrac - (NumericType) 1.0;
auto d2 = delayFrac - (NumericType) 2.0;
Expand Down Expand Up @@ -114,8 +114,8 @@
}
}

template <typename SampleType, typename NumericType>
inline SampleType call (const SampleType* buffer, int delayInt, NumericType delayFrac, const SampleType& /*state*/ = {})
template <typename SampleType, typename NumericType, typename StorageType = SampleType>
inline SampleType call (const StorageType* buffer, int delayInt, NumericType delayFrac, const SampleType& /*state*/ = {})
{
auto index1 = delayInt;
auto index2 = index1 + 1;
Expand All @@ -124,12 +124,12 @@
auto index5 = index4 + 1;
auto index6 = index5 + 1;

auto value1 = buffer[index1];
auto value2 = buffer[index2];
auto value3 = buffer[index3];
auto value4 = buffer[index4];
auto value5 = buffer[index5];
auto value6 = buffer[index6];
auto value1 = static_cast<SampleType> (buffer[index1]);
auto value2 = static_cast<SampleType> (buffer[index2]);
auto value3 = static_cast<SampleType> (buffer[index3]);
auto value4 = static_cast<SampleType> (buffer[index4]);
auto value5 = static_cast<SampleType> (buffer[index5]);
auto value6 = static_cast<SampleType> (buffer[index6]);

auto d1 = delayFrac - (NumericType) 1.0;
auto d2 = delayFrac - (NumericType) 2.0;
Expand Down
29 changes: 15 additions & 14 deletions modules/dsp/chowdsp_dsp_utils/Delay/chowdsp_DelayLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@
namespace chowdsp
{
//==============================================================================
template <typename SampleType, typename InterpolationType>
DelayLine<SampleType, InterpolationType>::DelayLine()
template <typename SampleType, typename InterpolationType, typename StorageType>
DelayLine<SampleType, InterpolationType, StorageType>::DelayLine()
: DelayLine (1 << 18)
{
}

template <typename SampleType, typename InterpolationType>
DelayLine<SampleType, InterpolationType>::DelayLine (int maximumDelayInSamples)
template <typename SampleType, typename InterpolationType, typename StorageType>
DelayLine<SampleType, InterpolationType, StorageType>::DelayLine (int maximumDelayInSamples)
{
jassert (maximumDelayInSamples >= 0);

totalSize = juce::jmax (4, maximumDelayInSamples + 1);
}

//==============================================================================
template <typename SampleType, typename InterpolationType>
void DelayLine<SampleType, InterpolationType>::setDelay (DelayLine<SampleType, InterpolationType>::NumericType newDelayInSamples)
template <typename SampleType, typename InterpolationType, typename StorageType>
void DelayLine<SampleType, InterpolationType, StorageType>::setDelay (DelayLine<SampleType, InterpolationType, StorageType>::NumericType newDelayInSamples)
{
auto upperLimit = (NumericType) (totalSize - 1);
jassert (juce::isPositiveAndNotGreaterThan (newDelayInSamples, upperLimit));
Expand All @@ -54,15 +54,16 @@ void DelayLine<SampleType, InterpolationType>::setDelay (DelayLine<SampleType, I
interpolator.updateInternalVariables (delayInt, delayFrac);
}

template <typename SampleType, typename InterpolationType>
SampleTypeHelpers::ProcessorNumericType<DelayLine<SampleType, InterpolationType>> DelayLine<SampleType, InterpolationType>::getDelay() const
template <typename SampleType, typename InterpolationType, typename StorageType>
SampleTypeHelpers::ProcessorNumericType<DelayLine<SampleType, InterpolationType, StorageType>>
DelayLine<SampleType, InterpolationType, StorageType>::getDelay() const
{
return delay;
}

//==============================================================================
template <typename SampleType, typename InterpolationType>
void DelayLine<SampleType, InterpolationType>::prepare (const juce::dsp::ProcessSpec& spec)
template <typename SampleType, typename InterpolationType, typename StorageType>
void DelayLine<SampleType, InterpolationType, StorageType>::prepare (const juce::dsp::ProcessSpec& spec)
{
jassert (spec.numChannels > 0);

Expand All @@ -80,8 +81,8 @@ void DelayLine<SampleType, InterpolationType>::prepare (const juce::dsp::Process
bufferPtrs[(size_t) ch] = this->bufferData.getWritePointer (ch);
}

template <typename SampleType, typename InterpolationType>
void DelayLine<SampleType, InterpolationType>::free()
template <typename SampleType, typename InterpolationType, typename StorageType>
void DelayLine<SampleType, InterpolationType, StorageType>::free()
{
this->bufferData.setMaxSize (0, 0);

Expand All @@ -91,8 +92,8 @@ void DelayLine<SampleType, InterpolationType>::free()
bufferPtrs.clear();
}

template <typename SampleType, typename InterpolationType>
void DelayLine<SampleType, InterpolationType>::reset()
template <typename SampleType, typename InterpolationType, typename StorageType>
void DelayLine<SampleType, InterpolationType, StorageType>::reset()
{
for (auto vec : { &this->writePos, &this->readPos })
std::fill (vec->begin(), vec->end(), 0);
Expand Down
16 changes: 8 additions & 8 deletions modules/dsp/chowdsp_dsp_utils/Delay/chowdsp_DelayLine.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace chowdsp
{
#ifndef DOXYGEN
/** Base class for delay lines with any interpolation type */
template <typename SampleType>
template <typename SampleType, typename StorageType = SampleType>
class DelayLineBase
{
public:
Expand All @@ -50,7 +50,7 @@ class DelayLineBase
virtual SampleType popSample (int /* channel */, NumericType /* delayInSamples */, bool /* updateReadPointer */) noexcept = 0;
virtual void incrementReadPointer (int channel) noexcept = 0;

void copyState (const DelayLineBase<SampleType>& other)
void copyState (const DelayLineBase& other)
{
const auto numChannels = other.bufferData.getNumChannels();
const auto numSamples = other.bufferData.getNumSamples();
Expand All @@ -71,7 +71,7 @@ class DelayLineBase
}

protected:
Buffer<SampleType> bufferData;
Buffer<StorageType> bufferData;
std::vector<SampleType> v;
std::vector<int> writePos, readPos;
};
Expand All @@ -90,8 +90,8 @@ class DelayLineBase
Note: If you intend to change the delay in real time, you may want to smooth
changes to the delay systematically using either a ramp or a low-pass filter.
*/
template <typename SampleType, typename InterpolationType = DelayLineInterpolationTypes::Linear>
class DelayLine : public DelayLineBase<SampleType>
template <typename SampleType, typename InterpolationType = DelayLineInterpolationTypes::Linear, typename StorageType = SampleType>
class DelayLine : public DelayLineBase<SampleType, StorageType>
{
using NumericType = SampleTypeHelpers::ProcessorNumericType<DelayLine>;

Expand Down Expand Up @@ -132,8 +132,8 @@ class DelayLine : public DelayLineBase<SampleType>
inline void pushSample (int channel, SampleType sample) noexcept final
{
const auto writePtr = this->writePos[(size_t) channel];
bufferPtrs[(size_t) channel][writePtr] = sample;
bufferPtrs[(size_t) channel][writePtr + totalSize] = sample;
bufferPtrs[(size_t) channel][writePtr] = static_cast<StorageType> (sample);
bufferPtrs[(size_t) channel][writePtr + totalSize] = static_cast<StorageType> (sample);
incrementWritePointer (channel);
}

Expand Down Expand Up @@ -263,7 +263,7 @@ class DelayLine : public DelayLineBase<SampleType>

//==============================================================================
InterpolationType interpolator;
std::vector<SampleType*> bufferPtrs;
std::vector<StorageType*> bufferPtrs;
NumericType delay = 0.0, delayFrac = 0.0;
int delayInt = 0, totalSize = 4;

Expand Down
Loading