Browse Source

DSP: Allowed AudioBlocks of const elements

tags/2021-05-28
reuk Tom Poole 6 years ago
parent
commit
827055c2c1
9 changed files with 142 additions and 58 deletions
  1. +22
    -0
      BREAKING-CHANGES.txt
  2. +102
    -36
      modules/juce_dsp/containers/juce_AudioBlock.h
  3. +0
    -7
      modules/juce_dsp/containers/juce_SIMDRegister.h
  4. +2
    -2
      modules/juce_dsp/frequency/juce_Convolution.cpp
  5. +1
    -1
      modules/juce_dsp/frequency/juce_Convolution.h
  6. +2
    -2
      modules/juce_dsp/native/juce_fallback_SIMDNativeOps.h
  7. +2
    -2
      modules/juce_dsp/processors/juce_FIRFilter_test.cpp
  8. +9
    -6
      modules/juce_dsp/processors/juce_ProcessContext.h
  9. +2
    -2
      modules/juce_dsp/processors/juce_ProcessorDuplicator.h

+ 22
- 0
BREAKING-CHANGES.txt View File

@@ -4,6 +4,28 @@ JUCE breaking changes
Develop Develop
======= =======


Change
------
The AudioBlock class now differentiates between const and non-const data.

Possible Issues
---------------
The return type of the getInputBlock() method of the ProcessContextReplacing
and ProcessContextNonReplacing classes has changed from AudioBlock<X> to
AudioBlock<const X>.

Workaround
----------
For ProcessContextReplacing you should use getOutputBlock() instead of
getInputBlock(). For ProcessContextNonReplacing attempting to modify the input
block is very likely an error.

Rationale
---------
This change makes the intent of the code much clearer and means that we can
remove some const_cast operations.


Change Change
------ ------
The formatting of floating point numbers written to XML and JSON files has The formatting of floating point numbers written to XML and JSON files has


+ 102
- 36
modules/juce_dsp/containers/juce_AudioBlock.h View File

@@ -32,10 +32,17 @@ namespace dsp
#ifndef DOXYGEN #ifndef DOXYGEN
namespace SampleTypeHelpers // Internal classes needed for handling sample type classes namespace SampleTypeHelpers // Internal classes needed for handling sample type classes
{ {
template <typename Container> struct ElementType { using Type = typename Container::value_type; };
template <> struct ElementType<float> { using Type = float; };
template <> struct ElementType<double> { using Type = double; };
template <> struct ElementType<long double> { using Type = long double; };
template <typename T, bool = std::is_floating_point<T>::value>
struct ElementType
{
using Type = T;
};
template <typename T>
struct ElementType<T, false>
{
using Type = typename T::value_type;
};
} }
#endif #endif
@@ -56,6 +63,15 @@ namespace SampleTypeHelpers // Internal classes needed for handling sample type
template <typename SampleType> template <typename SampleType>
class AudioBlock class AudioBlock
{ {
private:
template <typename OtherSampleType>
using MayUseConvertingConstructor =
std::enable_if_t<std::is_same<std::remove_const_t<SampleType>,
std::remove_const_t<OtherSampleType>>::value
&& std::is_const<SampleType>::value
&& ! std::is_const<OtherSampleType>::value,
int>;
public: public:
//============================================================================== //==============================================================================
using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type; using NumericType = typename SampleTypeHelpers::ElementType<SampleType>::Type;
@@ -127,7 +143,8 @@ public:
Therefore it is the user's responsibility to ensure that the buffer is retained Therefore it is the user's responsibility to ensure that the buffer is retained
throughout the life-time of the AudioBlock without being modified. throughout the life-time of the AudioBlock without being modified.
*/ */
AudioBlock (AudioBuffer<SampleType>& buffer) noexcept
template <typename OtherSampleType>
AudioBlock (AudioBuffer<OtherSampleType>& buffer) noexcept
: channels (buffer.getArrayOfWritePointers()), : channels (buffer.getArrayOfWritePointers()),
numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())), numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())),
numSamples (static_cast<size_t> (buffer.getNumSamples())) numSamples (static_cast<size_t> (buffer.getNumSamples()))
@@ -139,7 +156,8 @@ public:
Therefore it is the user's responsibility to ensure that the buffer is retained Therefore it is the user's responsibility to ensure that the buffer is retained
throughout the life-time of the AudioBlock without being modified. throughout the life-time of the AudioBlock without being modified.
*/ */
AudioBlock (AudioBuffer<SampleType>& buffer, size_t startSampleIndex) noexcept
template <typename OtherSampleType>
AudioBlock (AudioBuffer<OtherSampleType>& buffer, size_t startSampleIndex) noexcept
: channels (buffer.getArrayOfWritePointers()), : channels (buffer.getArrayOfWritePointers()),
numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())), numChannels (static_cast<ChannelCountType> (buffer.getNumChannels())),
startSample (startSampleIndex), startSample (startSampleIndex),
@@ -151,16 +169,45 @@ public:
AudioBlock (const AudioBlock& other) noexcept = default; AudioBlock (const AudioBlock& other) noexcept = default;
AudioBlock& operator= (const AudioBlock& other) noexcept = default; AudioBlock& operator= (const AudioBlock& other) noexcept = default;
template <typename OtherSampleType, MayUseConvertingConstructor<OtherSampleType> = 0>
AudioBlock (const AudioBlock<OtherSampleType>& other) noexcept
: channels { other.channels },
numChannels { other.numChannels },
startSample { other.startSample },
numSamples { other.numSamples }
{
}
template <typename OtherSampleType, MayUseConvertingConstructor<OtherSampleType> = 0>
AudioBlock& operator= (const AudioBlock<OtherSampleType>& other) noexcept
{
AudioBlock copy { other };
swap (copy);
return *this;
}
void swap (AudioBlock& other) noexcept
{
std::swap (other.channels, channels);
std::swap (other.numChannels, numChannels);
std::swap (other.startSample, startSample);
std::swap (other.numSamples, numSamples);
}
//============================================================================== //==============================================================================
bool operator== (const AudioBlock& other) const noexcept
template <typename OtherSampleType>
bool operator== (const AudioBlock<OtherSampleType>& other) const noexcept
{ {
return std::equal (channels, channels + numChannels,
other.channels, other.channels + other.numChannels)
&& startSample == other.startSample
&& numSamples == other.numSamples;
return std::equal (channels,
channels + numChannels,
other.channels,
other.channels + other.numChannels)
&& startSample == other.startSample
&& numSamples == other.numSamples;
} }
bool operator!= (const AudioBlock& other) const noexcept
template <typename OtherSampleType>
bool operator!= (const AudioBlock<OtherSampleType>& other) const noexcept
{ {
return ! (*this == other); return ! (*this == other);
} }
@@ -264,7 +311,8 @@ public:
} }
/** Copy the values in src to the receiver. */ /** Copy the values in src to the receiver. */
forcedinline AudioBlock& copy (AudioBlock src) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& copy (const AudioBlock<OtherSampleType>& src) noexcept
{ {
auto maxChannels = jmin (src.numChannels, numChannels); auto maxChannels = jmin (src.numChannels, numChannels);
auto n = static_cast<int> (jmin (src.numSamples, numSamples) * sizeFactor); auto n = static_cast<int> (jmin (src.numSamples, numSamples) * sizeFactor);
@@ -381,7 +429,8 @@ public:
} }
/** Adds the source values to the receiver. */ /** Adds the source values to the receiver. */
forcedinline AudioBlock& add (AudioBlock src) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& add (AudioBlock<OtherSampleType> src) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -393,7 +442,8 @@ public:
} }
/** Adds a fixed value to each source value and stores it in the destination array of the receiver. */ /** Adds a fixed value to each source value and stores it in the destination array of the receiver. */
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE add (AudioBlock src, SampleType value) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE add (AudioBlock<OtherSampleType> src, SampleType value) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -405,7 +455,8 @@ public:
} }
/** Adds each source1 value to the corresponding source2 value and stores it in the destination array of the receiver. */ /** Adds each source1 value to the corresponding source2 value and stores it in the destination array of the receiver. */
forcedinline AudioBlock& add (AudioBlock src1, AudioBlock src2) noexcept
template <typename Src1SampleType, typename Src2SampleType>
forcedinline AudioBlock& add (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept
{ {
jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels); jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);
@@ -423,7 +474,8 @@ public:
} }
/** Subtracts the source values from the receiver. */ /** Subtracts the source values from the receiver. */
forcedinline AudioBlock& subtract (AudioBlock src) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& subtract (AudioBlock<OtherSampleType> src) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -435,13 +487,15 @@ public:
} }
/** Subtracts a fixed value from each source value and stores it in the destination array of the receiver. */ /** Subtracts a fixed value from each source value and stores it in the destination array of the receiver. */
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE subtract (AudioBlock src, SampleType value) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE subtract (AudioBlock<OtherSampleType> src, SampleType value) noexcept
{ {
return add (src, static_cast<SampleType> (-1.0) * value); return add (src, static_cast<SampleType> (-1.0) * value);
} }
/** Subtracts each source2 value from the corresponding source1 value and stores it in the destination array of the receiver. */ /** Subtracts each source2 value from the corresponding source1 value and stores it in the destination array of the receiver. */
forcedinline AudioBlock& subtract (AudioBlock src1, AudioBlock src2) noexcept
template <typename Src1SampleType, typename Src2SampleType>
forcedinline AudioBlock& subtract (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept
{ {
jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels); jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);
@@ -464,7 +518,8 @@ public:
} }
/** Multiplies the source values to the receiver. */ /** Multiplies the source values to the receiver. */
forcedinline AudioBlock& multiply (AudioBlock src) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& multiply (AudioBlock<OtherSampleType> src) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -476,7 +531,8 @@ public:
} }
/** Multiplies a fixed value to each source value and stores it in the destination array of the receiver. */ /** Multiplies a fixed value to each source value and stores it in the destination array of the receiver. */
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE multiply (AudioBlock src, SampleType value) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE multiply (AudioBlock<OtherSampleType> src, SampleType value) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -488,7 +544,8 @@ public:
} }
/** Multiplies each source1 value to the corresponding source2 value and stores it in the destination array of the receiver. */ /** Multiplies each source1 value to the corresponding source2 value and stores it in the destination array of the receiver. */
forcedinline AudioBlock& multiply (AudioBlock src1, AudioBlock src2) noexcept
template <typename Src1SampleType, typename Src2SampleType>
forcedinline AudioBlock& multiply (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept
{ {
jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels); jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);
@@ -522,8 +579,8 @@ public:
} }
/** Multiplies all channels of the source by a smoothly changing value and stores them in the receiver. */ /** Multiplies all channels of the source by a smoothly changing value and stores them in the receiver. */
template <typename SmoothingType>
AudioBlock& multiply (AudioBlock src, SmoothedValue<SampleType, SmoothingType>& value) noexcept
template <typename OtherSampleType, typename SmoothingType>
AudioBlock& multiply (AudioBlock<OtherSampleType> src, SmoothedValue<SampleType, SmoothingType>& value) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
@@ -548,7 +605,8 @@ public:
} }
/** Multiplies each value in src with factor and adds the result to the receiver. */ /** Multiplies each value in src with factor and adds the result to the receiver. */
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE addWithMultiply (AudioBlock src, SampleType factor) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& JUCE_VECTOR_CALLTYPE addWithMultiply (AudioBlock<OtherSampleType> src, SampleType factor) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -560,7 +618,8 @@ public:
} }
/** Multiplies each value in srcA with the corresponding value in srcB and adds the result to the receiver. */ /** Multiplies each value in srcA with the corresponding value in srcB and adds the result to the receiver. */
forcedinline AudioBlock& addWithMultiply (AudioBlock src1, AudioBlock src2) noexcept
template <typename Src1SampleType, typename Src2SampleType>
forcedinline AudioBlock& addWithMultiply (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept
{ {
jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels); jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src1.numSamples, src2.numSamples) * sizeFactor);
@@ -578,7 +637,8 @@ public:
} }
/** Negates each value of source and stores it in the receiver. */ /** Negates each value of source and stores it in the receiver. */
forcedinline AudioBlock& replaceWithNegativeOf (AudioBlock src) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& replaceWithNegativeOf (AudioBlock<OtherSampleType> src) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -590,7 +650,8 @@ public:
} }
/** Takes the absolute value of each element of src and stores it inside the receiver. */ /** Takes the absolute value of each element of src and stores it inside the receiver. */
forcedinline AudioBlock& replaceWithAbsoluteValueOf (AudioBlock src) noexcept
template <typename OtherSampleType>
forcedinline AudioBlock& replaceWithAbsoluteValueOf (AudioBlock<OtherSampleType> src) noexcept
{ {
jassert (numChannels == src.numChannels); jassert (numChannels == src.numChannels);
auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor); auto n = static_cast<int> (jmin (numSamples, src.numSamples) * sizeFactor);
@@ -602,7 +663,8 @@ public:
} }
/** Each element of receiver will be the minimum of the corresponding element of the source arrays. */ /** Each element of receiver will be the minimum of the corresponding element of the source arrays. */
forcedinline AudioBlock& min (AudioBlock src1, AudioBlock src2) noexcept
template <typename Src1SampleType, typename Src2SampleType>
forcedinline AudioBlock& min (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept
{ {
jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels); jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
auto n = static_cast<int> (jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor); auto n = static_cast<int> (jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor);
@@ -614,7 +676,8 @@ public:
} }
/** Each element of the receiver will be the maximum of the corresponding element of the source arrays. */ /** Each element of the receiver will be the maximum of the corresponding element of the source arrays. */
forcedinline AudioBlock& max (AudioBlock src1, AudioBlock src2) noexcept
template <typename Src1SampleType, typename Src2SampleType>
forcedinline AudioBlock& max (AudioBlock<Src1SampleType> src1, AudioBlock<Src2SampleType> src2) noexcept
{ {
jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels); jassert (numChannels == src1.numChannels && src1.numChannels == src2.numChannels);
auto n = static_cast<int> (jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor); auto n = static_cast<int> (jmin (src1.numSamples, src2.numSamples, numSamples) * sizeFactor);
@@ -653,11 +716,11 @@ public:
//============================================================================== //==============================================================================
// This class can only be used with floating point types // This class can only be used with floating point types
static_assert (std::is_same<SampleType, float>::value
|| std::is_same<SampleType, double>::value
static_assert (std::is_same<std::remove_const_t<SampleType>, float>::value
|| std::is_same<std::remove_const_t<SampleType>, double>::value
#if JUCE_USE_SIMD #if JUCE_USE_SIMD
|| std::is_same<SampleType, SIMDRegister<float>>::value
|| std::is_same<SampleType, SIMDRegister<double>>::value
|| std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value
|| std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value
#endif #endif
, "AudioBlock only supports single or double precision floating point types"); , "AudioBlock only supports single or double precision floating point types");
@@ -666,8 +729,8 @@ public:
The function supplied must take a SampleType as its parameter, and return a SampleType. The function supplied must take a SampleType as its parameter, and return a SampleType.
The two blocks must have the same number of channels and samples. The two blocks must have the same number of channels and samples.
*/ */
template <typename FunctionType>
static void process (AudioBlock inBlock, AudioBlock outBlock, FunctionType&& function)
template <typename Src1SampleType, typename Src2SampleType, typename FunctionType>
static void process (AudioBlock<Src1SampleType> inBlock, AudioBlock<Src2SampleType> outBlock, FunctionType&& function)
{ {
auto len = inBlock.getNumSamples(); auto len = inBlock.getNumSamples();
auto numChans = inBlock.getNumChannels(); auto numChans = inBlock.getNumChannels();
@@ -707,6 +770,9 @@ private:
SampleType* const* channels; SampleType* const* channels;
ChannelCountType numChannels = 0; ChannelCountType numChannels = 0;
size_t startSample = 0, numSamples = 0; size_t startSample = 0, numSamples = 0;
template <typename OtherSampleType>
friend class AudioBlock;
}; };
} // namespace dsp } // namespace dsp


+ 0
- 7
modules/juce_dsp/containers/juce_SIMDRegister.h View File

@@ -358,13 +358,6 @@ struct SIMDRegister
return snapPointerToAlignment (ptr, SIMDRegisterSize); return snapPointerToAlignment (ptr, SIMDRegisterSize);
} }
#ifndef DOXYGEN
static inline const ElementType* getNextSIMDAlignedPtr (const ElementType* ptr) noexcept
{
return snapPointerToAlignment (ptr, SIMDRegisterSize);
}
#endif
private: private:
static inline vMaskType JUCE_VECTOR_CALLTYPE toMaskType (vSIMDType a) noexcept static inline vMaskType JUCE_VECTOR_CALLTYPE toMaskType (vSIMDType a) noexcept
{ {


+ 2
- 2
modules/juce_dsp/frequency/juce_Convolution.cpp View File

@@ -718,7 +718,7 @@ struct Convolution::Pimpl : private Thread
/** Convolution processing handling interpolation between previous and new states /** Convolution processing handling interpolation between previous and new states
of the convolution engines. of the convolution engines.
*/ */
void processSamples (const AudioBlock<float>& input, AudioBlock<float>& output)
void processSamples (const AudioBlock<const float>& input, AudioBlock<float>& output)
{ {
processFifo(); processFifo();
@@ -1197,7 +1197,7 @@ void Convolution::reset() noexcept
pimpl->reset(); pimpl->reset();
} }
void Convolution::processSamples (const AudioBlock<float>& input, AudioBlock<float>& output, bool isBypassed) noexcept
void Convolution::processSamples (const AudioBlock<const float>& input, AudioBlock<float>& output, bool isBypassed) noexcept
{ {
if (! isActive) if (! isActive)
return; return;


+ 1
- 1
modules/juce_dsp/frequency/juce_Convolution.h View File

@@ -156,7 +156,7 @@ private:
std::unique_ptr<Pimpl> pimpl; std::unique_ptr<Pimpl> pimpl;
//============================================================================== //==============================================================================
void processSamples (const AudioBlock<float>&, AudioBlock<float>&, bool isBypassed) noexcept;
void processSamples (const AudioBlock<const float>&, AudioBlock<float>&, bool isBypassed) noexcept;
//============================================================================== //==============================================================================
double sampleRate; double sampleRate;


+ 2
- 2
modules/juce_dsp/native/juce_fallback_SIMDNativeOps.h View File

@@ -43,8 +43,8 @@ namespace SIMDInternal
template <> struct MaskTypeFor <std::complex<float>> { using type = uint32_t; }; template <> struct MaskTypeFor <std::complex<float>> { using type = uint32_t; };
template <> struct MaskTypeFor <std::complex<double>> { using type = uint64_t; }; template <> struct MaskTypeFor <std::complex<double>> { using type = uint64_t; };
template <typename Primitive> struct PrimitiveType { using type = Primitive; };
template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = Primitive; };
template <typename Primitive> struct PrimitiveType { using type = typename std::remove_cv<Primitive>::type; };
template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = typename std::remove_cv<Primitive>::type; };
template <int n> struct Log2Helper { enum { value = Log2Helper<n/2>::value + 1 }; }; template <int n> struct Log2Helper { enum { value = Log2Helper<n/2>::value + 1 }; };
template <> struct Log2Helper<1> { enum { value = 0 }; }; template <> struct Log2Helper<1> { enum { value = 0 }; };


+ 2
- 2
modules/juce_dsp/processors/juce_FIRFilter_test.cpp View File

@@ -121,7 +121,7 @@ class FIRFilterTest : public UnitTest
template <typename FloatType> template <typename FloatType>
static void run (FIR::Filter<FloatType>& filter, FloatType* src, FloatType* dst, size_t n) static void run (FIR::Filter<FloatType>& filter, FloatType* src, FloatType* dst, size_t n)
{ {
AudioBlock<FloatType> input (&src, 1, n);
AudioBlock<const FloatType> input (&src, 1, n);
AudioBlock<FloatType> output (&dst, 1, n); AudioBlock<FloatType> output (&dst, 1, n);
ProcessContextNonReplacing<FloatType> context (input, output); ProcessContextNonReplacing<FloatType> context (input, output);
@@ -151,7 +151,7 @@ class FIRFilterTest : public UnitTest
auto* src = input + i; auto* src = input + i;
auto* dst = output + i; auto* dst = output + i;
AudioBlock<FloatType> inBlock (&src, 1, len);
AudioBlock<const FloatType> inBlock (&src, 1, len);
AudioBlock<FloatType> outBlock (&dst, 1, len); AudioBlock<FloatType> outBlock (&dst, 1, len);
ProcessContextNonReplacing<FloatType> context (inBlock, outBlock); ProcessContextNonReplacing<FloatType> context (inBlock, outBlock);


+ 9
- 6
modules/juce_dsp/processors/juce_ProcessContext.h View File

@@ -83,6 +83,7 @@ public:
using SampleType = ContextSampleType; using SampleType = ContextSampleType;
/** The type of audio block that this context handles. */ /** The type of audio block that this context handles. */
using AudioBlockType = AudioBlock<SampleType>; using AudioBlockType = AudioBlock<SampleType>;
using ConstAudioBlockType = AudioBlock<const SampleType>;
/** Creates a ProcessContextReplacing that uses the given audio block. /** Creates a ProcessContextReplacing that uses the given audio block.
Note that the caller must not delete the block while it is still in use by this object! Note that the caller must not delete the block while it is still in use by this object!
@@ -93,10 +94,10 @@ public:
ProcessContextReplacing (ProcessContextReplacing&&) = default; ProcessContextReplacing (ProcessContextReplacing&&) = default;
/** Returns the audio block to use as the input to a process function. */ /** Returns the audio block to use as the input to a process function. */
const AudioBlockType& getInputBlock() const noexcept { return ioBlock; }
const ConstAudioBlockType& getInputBlock() const noexcept { return constBlock; }
/** Returns the audio block to use as the output to a process function. */ /** Returns the audio block to use as the output to a process function. */
AudioBlockType& getOutputBlock() const noexcept { return const_cast<AudioBlockType&> (ioBlock); }
AudioBlockType& getOutputBlock() const noexcept { return ioBlock; }
/** All process context classes will define this constant method so that templated /** All process context classes will define this constant method so that templated
code can determine whether the input and output blocks refer to the same buffer, code can determine whether the input and output blocks refer to the same buffer,
@@ -111,6 +112,7 @@ public:
private: private:
AudioBlockType& ioBlock; AudioBlockType& ioBlock;
ConstAudioBlockType constBlock { ioBlock };
}; };
//============================================================================== //==============================================================================
@@ -134,11 +136,12 @@ public:
using SampleType = ContextSampleType; using SampleType = ContextSampleType;
/** The type of audio block that this context handles. */ /** The type of audio block that this context handles. */
using AudioBlockType = AudioBlock<SampleType>; using AudioBlockType = AudioBlock<SampleType>;
using ConstAudioBlockType = AudioBlock<const SampleType>;
/** Creates a ProcessContextReplacing that uses the given input and output blocks. /** Creates a ProcessContextReplacing that uses the given input and output blocks.
Note that the caller must not delete these blocks while they are still in use by this object! Note that the caller must not delete these blocks while they are still in use by this object!
*/ */
ProcessContextNonReplacing (const AudioBlockType& input, AudioBlockType& output) noexcept
ProcessContextNonReplacing (const ConstAudioBlockType& input, AudioBlockType& output) noexcept
: inputBlock (input), outputBlock (output) : inputBlock (input), outputBlock (output)
{ {
// If the input and output blocks are the same then you should use // If the input and output blocks are the same then you should use
@@ -150,10 +153,10 @@ public:
ProcessContextNonReplacing (ProcessContextNonReplacing&&) = default; ProcessContextNonReplacing (ProcessContextNonReplacing&&) = default;
/** Returns the audio block to use as the input to a process function. */ /** Returns the audio block to use as the input to a process function. */
const AudioBlockType& getInputBlock() const noexcept { return inputBlock; }
const ConstAudioBlockType& getInputBlock() const noexcept { return inputBlock; }
/** Returns the audio block to use as the output to a process function. */ /** Returns the audio block to use as the output to a process function. */
AudioBlockType& getOutputBlock() const noexcept { return const_cast<AudioBlockType&> (outputBlock); }
AudioBlockType& getOutputBlock() const noexcept { return outputBlock; }
/** All process context classes will define this constant method so that templated /** All process context classes will define this constant method so that templated
code can determine whether the input and output blocks refer to the same buffer, code can determine whether the input and output blocks refer to the same buffer,
@@ -167,7 +170,7 @@ public:
bool isBypassed = false; bool isBypassed = false;
private: private:
const AudioBlockType& inputBlock;
const ConstAudioBlockType& inputBlock;
AudioBlockType& outputBlock; AudioBlockType& outputBlock;
}; };


+ 2
- 2
modules/juce_dsp/processors/juce_ProcessorDuplicator.h View File

@@ -89,8 +89,8 @@ private:
size_t channel; size_t channel;
typename ProcessContext::AudioBlockType getInputBlock() const noexcept { return ProcessContext::getInputBlock().getSingleChannelBlock (channel); }
typename ProcessContext::AudioBlockType getOutputBlock() const noexcept { return ProcessContext::getOutputBlock().getSingleChannelBlock (channel); }
typename ProcessContext::ConstAudioBlockType getInputBlock() const noexcept { return ProcessContext::getInputBlock() .getSingleChannelBlock (channel); }
typename ProcessContext::AudioBlockType getOutputBlock() const noexcept { return ProcessContext::getOutputBlock().getSingleChannelBlock (channel); }
}; };
juce::OwnedArray<MonoProcessorType> processors; juce::OwnedArray<MonoProcessorType> processors;


Loading…
Cancel
Save