mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Use more concise stdlib type aliases
This commit is contained in:
parent
21d87c02c2
commit
7c14c1fcd7
36 changed files with 438 additions and 494 deletions
|
|
@ -159,7 +159,7 @@ private:
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
static std::unique_ptr<Command<Proc>> makeCommand (Func&& func)
|
static std::unique_ptr<Command<Proc>> makeCommand (Func&& func)
|
||||||
{
|
{
|
||||||
using Decayed = typename std::decay<Func>::type;
|
using Decayed = std::decay_t<Func>;
|
||||||
return std::make_unique<TemplateCommand<Proc, Decayed>> (std::forward<Func> (func));
|
return std::make_unique<TemplateCommand<Proc, Decayed>> (std::forward<Func> (func));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -530,7 +530,7 @@ int main (int argc, char** argv)
|
||||||
juce::ArgumentList argumentList { arguments.front(),
|
juce::ArgumentList argumentList { arguments.front(),
|
||||||
juce::StringArray (arguments.data() + 1, (int) arguments.size() - 1) };
|
juce::StringArray (arguments.data() + 1, (int) arguments.size() - 1) };
|
||||||
|
|
||||||
using Fn = std::add_lvalue_reference<decltype (writeBinaryData)>::type;
|
using Fn = int (*) (juce::ArgumentList&&);
|
||||||
|
|
||||||
const std::unordered_map<juce::String, Fn> commands
|
const std::unordered_map<juce::String, Fn> commands
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1177,7 +1177,7 @@ private:
|
||||||
jassert (size >= 0);
|
jassert (size >= 0);
|
||||||
|
|
||||||
auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);
|
auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);
|
||||||
auto requiredSampleAlignment = std::alignment_of<Type>::value;
|
auto requiredSampleAlignment = std::alignment_of_v<Type>;
|
||||||
size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
|
size_t alignmentOverflow = channelListSize % requiredSampleAlignment;
|
||||||
|
|
||||||
if (alignmentOverflow != 0)
|
if (alignmentOverflow != 0)
|
||||||
|
|
|
||||||
|
|
@ -992,7 +992,7 @@ private:
|
||||||
|
|
||||||
#if JUCE_WINDOWS && ! JUCE_MINGW
|
#if JUCE_WINDOWS && ! JUCE_MINGW
|
||||||
#define JUCE_CHECKED_ITERATOR(msg, size) \
|
#define JUCE_CHECKED_ITERATOR(msg, size) \
|
||||||
stdext::checked_array_iterator<typename std::remove_reference<decltype (msg)>::type> ((msg), (size_t) (size))
|
stdext::checked_array_iterator<std::remove_reference_t<decltype (msg)>> ((msg), (size_t) (size))
|
||||||
#else
|
#else
|
||||||
#define JUCE_CHECKED_ITERATOR(msg, size) (msg)
|
#define JUCE_CHECKED_ITERATOR(msg, size) (msg)
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -38,35 +38,35 @@ class Packet
|
||||||
public:
|
public:
|
||||||
Packet() = default;
|
Packet() = default;
|
||||||
|
|
||||||
template <size_t w = numWords, typename std::enable_if<w == 1, int>::type = 0>
|
template <size_t w = numWords, std::enable_if_t<w == 1, int> = 0>
|
||||||
Packet (uint32_t a)
|
Packet (uint32_t a)
|
||||||
: contents { { a } }
|
: contents { { a } }
|
||||||
{
|
{
|
||||||
jassert (Utils::getNumWordsForMessageType (a) == 1);
|
jassert (Utils::getNumWordsForMessageType (a) == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t w = numWords, typename std::enable_if<w == 2, int>::type = 0>
|
template <size_t w = numWords, std::enable_if_t<w == 2, int> = 0>
|
||||||
Packet (uint32_t a, uint32_t b)
|
Packet (uint32_t a, uint32_t b)
|
||||||
: contents { { a, b } }
|
: contents { { a, b } }
|
||||||
{
|
{
|
||||||
jassert (Utils::getNumWordsForMessageType (a) == 2);
|
jassert (Utils::getNumWordsForMessageType (a) == 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t w = numWords, typename std::enable_if<w == 3, int>::type = 0>
|
template <size_t w = numWords, std::enable_if_t<w == 3, int> = 0>
|
||||||
Packet (uint32_t a, uint32_t b, uint32_t c)
|
Packet (uint32_t a, uint32_t b, uint32_t c)
|
||||||
: contents { { a, b, c } }
|
: contents { { a, b, c } }
|
||||||
{
|
{
|
||||||
jassert (Utils::getNumWordsForMessageType (a) == 3);
|
jassert (Utils::getNumWordsForMessageType (a) == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t w = numWords, typename std::enable_if<w == 4, int>::type = 0>
|
template <size_t w = numWords, std::enable_if_t<w == 4, int> = 0>
|
||||||
Packet (uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
Packet (uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
||||||
: contents { { a, b, c, d } }
|
: contents { { a, b, c, d } }
|
||||||
{
|
{
|
||||||
jassert (Utils::getNumWordsForMessageType (a) == 4);
|
jassert (Utils::getNumWordsForMessageType (a) == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t w, typename std::enable_if<w == numWords, int>::type = 0>
|
template <size_t w, std::enable_if_t<w == numWords, int> = 0>
|
||||||
explicit Packet (const std::array<uint32_t, w>& fullPacket)
|
explicit Packet (const std::array<uint32_t, w>& fullPacket)
|
||||||
: contents (fullPacket)
|
: contents (fullPacket)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ public:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Constructor. */
|
/** Constructor. */
|
||||||
SmoothedValue() noexcept
|
SmoothedValue() noexcept
|
||||||
: SmoothedValue ((FloatType) (std::is_same<SmoothingType, ValueSmoothingTypes::Linear>::value ? 0 : 1))
|
: SmoothedValue ((FloatType) (std::is_same_v<SmoothingType, ValueSmoothingTypes::Linear> ? 0 : 1))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,7 +237,7 @@ public:
|
||||||
SmoothedValue (FloatType initialValue) noexcept
|
SmoothedValue (FloatType initialValue) noexcept
|
||||||
{
|
{
|
||||||
// Multiplicative smoothed values cannot ever reach 0!
|
// Multiplicative smoothed values cannot ever reach 0!
|
||||||
jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && initialValue == 0));
|
jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && initialValue == 0));
|
||||||
|
|
||||||
// Visual Studio can't handle base class initialisation with CRTP
|
// Visual Studio can't handle base class initialisation with CRTP
|
||||||
this->currentValue = initialValue;
|
this->currentValue = initialValue;
|
||||||
|
|
@ -280,7 +280,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiplicative smoothed values cannot ever reach 0!
|
// Multiplicative smoothed values cannot ever reach 0!
|
||||||
jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && newValue == 0));
|
jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && newValue == 0));
|
||||||
|
|
||||||
this->target = newValue;
|
this->target = newValue;
|
||||||
this->countdown = stepsToTarget;
|
this->countdown = stepsToTarget;
|
||||||
|
|
@ -351,50 +351,46 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
|
||||||
template <typename T>
|
|
||||||
using LinearVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Linear>::value, void>::type;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using MultiplicativeVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Multiplicative>::value, void>::type;
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = SmoothingType>
|
template <typename T = SmoothingType>
|
||||||
LinearVoid<T> setStepSize() noexcept
|
void setStepSize() noexcept
|
||||||
{
|
{
|
||||||
step = (this->target - this->currentValue) / (FloatType) this->countdown;
|
if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)
|
||||||
}
|
{
|
||||||
|
step = (this->target - this->currentValue) / (FloatType) this->countdown;
|
||||||
template <typename T = SmoothingType>
|
}
|
||||||
MultiplicativeVoid<T> setStepSize()
|
else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)
|
||||||
{
|
{
|
||||||
step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);
|
step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = SmoothingType>
|
template <typename T = SmoothingType>
|
||||||
LinearVoid<T> setNextValue() noexcept
|
void setNextValue() noexcept
|
||||||
{
|
{
|
||||||
this->currentValue += step;
|
if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)
|
||||||
}
|
{
|
||||||
|
this->currentValue += step;
|
||||||
template <typename T = SmoothingType>
|
}
|
||||||
MultiplicativeVoid<T> setNextValue() noexcept
|
else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)
|
||||||
{
|
{
|
||||||
this->currentValue *= step;
|
this->currentValue *= step;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = SmoothingType>
|
template <typename T = SmoothingType>
|
||||||
LinearVoid<T> skipCurrentValue (int numSamples) noexcept
|
void skipCurrentValue (int numSamples) noexcept
|
||||||
{
|
{
|
||||||
this->currentValue += step * (FloatType) numSamples;
|
if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)
|
||||||
}
|
{
|
||||||
|
this->currentValue += step * (FloatType) numSamples;
|
||||||
template <typename T = SmoothingType>
|
}
|
||||||
MultiplicativeVoid<T> skipCurrentValue (int numSamples)
|
else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)
|
||||||
{
|
{
|
||||||
this->currentValue *= (FloatType) std::pow (step, numSamples);
|
this->currentValue *= (FloatType) std::pow (step, numSamples);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
|
||||||
|
|
@ -944,9 +944,10 @@ struct WorkSubmitter
|
||||||
CriticalSection* workMutex;
|
CriticalSection* workMutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Trivial, std::enable_if_t<std::is_trivial<Trivial>::value, int> = 0>
|
template <typename Trivial>
|
||||||
static auto toChars (Trivial value)
|
static auto toChars (Trivial value)
|
||||||
{
|
{
|
||||||
|
static_assert (std::is_trivial_v<Trivial>);
|
||||||
std::array<char, sizeof (Trivial)> result;
|
std::array<char, sizeof (Trivial)> result;
|
||||||
writeUnaligned (result.data(), value);
|
writeUnaligned (result.data(), value);
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -956,7 +957,7 @@ template <typename Context>
|
||||||
class WorkQueue
|
class WorkQueue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static_assert (std::is_trivial<Context>::value, "Context must be copyable as bytes");
|
static_assert (std::is_trivial_v<Context>, "Context must be copyable as bytes");
|
||||||
|
|
||||||
explicit WorkQueue (int size)
|
explicit WorkQueue (int size)
|
||||||
: fifo (size), data (static_cast<size_t> (size)) {}
|
: fifo (size), data (static_cast<size_t> (size)) {}
|
||||||
|
|
@ -3657,8 +3658,8 @@ private:
|
||||||
|
|
||||||
union Data
|
union Data
|
||||||
{
|
{
|
||||||
static_assert (std::is_trivial<PortBacking>::value, "PortBacking must be trivial");
|
static_assert (std::is_trivial_v<PortBacking>, "PortBacking must be trivial");
|
||||||
static_assert (std::is_trivial<PatchBacking>::value, "PatchBacking must be trivial");
|
static_assert (std::is_trivial_v<PatchBacking>, "PatchBacking must be trivial");
|
||||||
|
|
||||||
explicit Data (PortBacking p) : port (p) {}
|
explicit Data (PortBacking p) : port (p) {}
|
||||||
explicit Data (PatchBacking p) : patch (p) {}
|
explicit Data (PatchBacking p) : patch (p) {}
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ public:
|
||||||
template <typename SpecialisationType>
|
template <typename SpecialisationType>
|
||||||
static const ARA::ARAFactory* createARAFactory()
|
static const ARA::ARAFactory* createARAFactory()
|
||||||
{
|
{
|
||||||
static_assert (std::is_base_of<ARADocumentControllerSpecialisation, SpecialisationType>::value,
|
static_assert (std::is_base_of_v<ARADocumentControllerSpecialisation, SpecialisationType>,
|
||||||
"DocumentController specialization types must inherit from ARADocumentControllerSpecialisation");
|
"DocumentController specialization types must inherit from ARADocumentControllerSpecialisation");
|
||||||
return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory();
|
return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -649,7 +649,7 @@ public:
|
||||||
@see add
|
@see add
|
||||||
*/
|
*/
|
||||||
template <class OtherArrayType>
|
template <class OtherArrayType>
|
||||||
typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type
|
std::enable_if_t<! std::is_pointer_v<OtherArrayType>, void>
|
||||||
addArray (const OtherArrayType& arrayToAddFrom,
|
addArray (const OtherArrayType& arrayToAddFrom,
|
||||||
int startIndex,
|
int startIndex,
|
||||||
int numElementsToAdd = -1)
|
int numElementsToAdd = -1)
|
||||||
|
|
|
||||||
|
|
@ -105,9 +105,9 @@ class ArrayBaseTests : public UnitTest
|
||||||
using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;
|
using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;
|
||||||
|
|
||||||
#if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__))
|
#if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__))
|
||||||
static_assert (std::is_trivially_copyable<CopyableType>::value,
|
static_assert (std::is_trivially_copyable_v<CopyableType>,
|
||||||
"Test TriviallyCopyableType is not trivially copyable");
|
"Test TriviallyCopyableType is not trivially copyable");
|
||||||
static_assert (! std::is_trivially_copyable<NoncopyableType>::value,
|
static_assert (! std::is_trivially_copyable_v<NoncopyableType>,
|
||||||
"Test NonTriviallyCopyableType is trivially copyable");
|
"Test NonTriviallyCopyableType is trivially copyable");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ private:
|
||||||
using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;
|
using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;
|
||||||
|
|
||||||
template <class OtherElementType, class OtherCriticalSection>
|
template <class OtherElementType, class OtherCriticalSection>
|
||||||
using AllowConversion = typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>,
|
using AllowConversion = std::enable_if_t<! std::is_same_v<std::tuple<ElementType, TypeOfCriticalSectionToUse>,
|
||||||
std::tuple<OtherElementType, OtherCriticalSection>>::value>::type;
|
std::tuple<OtherElementType, OtherCriticalSection>>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
@ -304,7 +304,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class OtherArrayType>
|
template <class OtherArrayType>
|
||||||
typename std::enable_if<! std::is_pointer<OtherArrayType>::value, int>::type
|
std::enable_if_t<! std::is_pointer_v<OtherArrayType>, int>
|
||||||
addArray (const OtherArrayType& arrayToAddFrom,
|
addArray (const OtherArrayType& arrayToAddFrom,
|
||||||
int startIndex, int numElementsToAdd = -1)
|
int startIndex, int numElementsToAdd = -1)
|
||||||
{
|
{
|
||||||
|
|
@ -385,64 +385,49 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T>
|
|
||||||
#if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)
|
#if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)
|
||||||
using IsTriviallyCopyable = std::is_scalar<T>;
|
static constexpr auto isTriviallyCopyable = std::is_scalar_v<ElementType>;
|
||||||
#else
|
#else
|
||||||
using IsTriviallyCopyable = std::is_trivially_copyable<T>;
|
static constexpr auto isTriviallyCopyable = std::is_trivially_copyable_v<ElementType>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using TriviallyCopyableVoid = typename std::enable_if<IsTriviallyCopyable<T>::value, void>::type;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using NonTriviallyCopyableVoid = typename std::enable_if<! IsTriviallyCopyable<T>::value, void>::type;
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = ElementType>
|
template <typename Type>
|
||||||
TriviallyCopyableVoid<T> addArrayInternal (const ElementType* otherElements, int numElements)
|
void addArrayInternal (const Type* otherElements, int numElements)
|
||||||
{
|
{
|
||||||
if (numElements > 0)
|
if constexpr (isTriviallyCopyable && std::is_same_v<Type, ElementType>)
|
||||||
memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type, typename T = ElementType>
|
|
||||||
TriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)
|
|
||||||
{
|
|
||||||
auto* start = elements + numUsed;
|
|
||||||
|
|
||||||
while (--numElements >= 0)
|
|
||||||
new (start++) ElementType (*(otherElements++));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Type, typename T = ElementType>
|
|
||||||
NonTriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)
|
|
||||||
{
|
|
||||||
auto* start = elements + numUsed;
|
|
||||||
|
|
||||||
while (--numElements >= 0)
|
|
||||||
new (start++) ElementType (*(otherElements++));
|
|
||||||
}
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
template <typename T = ElementType>
|
|
||||||
TriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)
|
|
||||||
{
|
|
||||||
elements.realloc ((size_t) numElements);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = ElementType>
|
|
||||||
NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)
|
|
||||||
{
|
|
||||||
HeapBlock<ElementType> newElements (numElements);
|
|
||||||
|
|
||||||
for (int i = 0; i < numUsed; ++i)
|
|
||||||
{
|
{
|
||||||
new (newElements + i) ElementType (std::move (elements[i]));
|
if (numElements > 0)
|
||||||
elements[i].~ElementType();
|
memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto* start = elements + numUsed;
|
||||||
|
|
||||||
elements = std::move (newElements);
|
while (--numElements >= 0)
|
||||||
|
new (start++) ElementType (*(otherElements++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void setAllocatedSizeInternal (int numElements)
|
||||||
|
{
|
||||||
|
if constexpr (isTriviallyCopyable)
|
||||||
|
{
|
||||||
|
elements.realloc ((size_t) numElements);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HeapBlock<ElementType> newElements (numElements);
|
||||||
|
|
||||||
|
for (int i = 0; i < numUsed; ++i)
|
||||||
|
{
|
||||||
|
new (newElements + i) ElementType (std::move (elements[i]));
|
||||||
|
elements[i].~ElementType();
|
||||||
|
}
|
||||||
|
|
||||||
|
elements = std::move (newElements);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
@ -458,99 +443,99 @@ private:
|
||||||
return elements + indexToInsertAt;
|
return elements + indexToInsertAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = ElementType>
|
void createInsertSpaceInternal (int indexToInsertAt, int numElements)
|
||||||
TriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)
|
|
||||||
{
|
{
|
||||||
auto* start = elements + indexToInsertAt;
|
if constexpr (isTriviallyCopyable)
|
||||||
auto numElementsToShift = numUsed - indexToInsertAt;
|
|
||||||
memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = ElementType>
|
|
||||||
NonTriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)
|
|
||||||
{
|
|
||||||
auto* end = elements + numUsed;
|
|
||||||
auto* newEnd = end + numElements;
|
|
||||||
auto numElementsToShift = numUsed - indexToInsertAt;
|
|
||||||
|
|
||||||
for (int i = 0; i < numElementsToShift; ++i)
|
|
||||||
{
|
{
|
||||||
new (--newEnd) ElementType (std::move (*(--end)));
|
auto* start = elements + indexToInsertAt;
|
||||||
end->~ElementType();
|
auto numElementsToShift = numUsed - indexToInsertAt;
|
||||||
|
memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto* end = elements + numUsed;
|
||||||
|
auto* newEnd = end + numElements;
|
||||||
|
auto numElementsToShift = numUsed - indexToInsertAt;
|
||||||
|
|
||||||
|
for (int i = 0; i < numElementsToShift; ++i)
|
||||||
|
{
|
||||||
|
new (--newEnd) ElementType (std::move (*(--end)));
|
||||||
|
end->~ElementType();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = ElementType>
|
void removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)
|
||||||
TriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)
|
|
||||||
{
|
{
|
||||||
auto* start = elements + indexToRemoveAt;
|
if constexpr (isTriviallyCopyable)
|
||||||
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
|
{
|
||||||
memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));
|
auto* start = elements + indexToRemoveAt;
|
||||||
}
|
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
|
||||||
|
memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
|
||||||
|
auto* destination = elements + indexToRemoveAt;
|
||||||
|
auto* source = destination + numElementsToRemove;
|
||||||
|
|
||||||
template <typename T = ElementType>
|
for (int i = 0; i < numElementsToShift; ++i)
|
||||||
NonTriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)
|
moveAssignElement (destination++, std::move (*(source++)));
|
||||||
{
|
|
||||||
auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);
|
|
||||||
auto* destination = elements + indexToRemoveAt;
|
|
||||||
auto* source = destination + numElementsToRemove;
|
|
||||||
|
|
||||||
for (int i = 0; i < numElementsToShift; ++i)
|
for (int i = 0; i < numElementsToRemove; ++i)
|
||||||
moveAssignElement (destination++, std::move (*(source++)));
|
(destination++)->~ElementType();
|
||||||
|
}
|
||||||
for (int i = 0; i < numElementsToRemove; ++i)
|
|
||||||
(destination++)->~ElementType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = ElementType>
|
void moveInternal (int currentIndex, int newIndex) noexcept
|
||||||
TriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept
|
|
||||||
{
|
{
|
||||||
char tempCopy[sizeof (ElementType)];
|
if constexpr (isTriviallyCopyable)
|
||||||
memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));
|
|
||||||
|
|
||||||
if (newIndex > currentIndex)
|
|
||||||
{
|
{
|
||||||
memmove (elements + currentIndex,
|
char tempCopy[sizeof (ElementType)];
|
||||||
elements + currentIndex + 1,
|
memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));
|
||||||
(size_t) (newIndex - currentIndex) * sizeof (ElementType));
|
|
||||||
|
if (newIndex > currentIndex)
|
||||||
|
{
|
||||||
|
memmove (elements + currentIndex,
|
||||||
|
elements + currentIndex + 1,
|
||||||
|
(size_t) (newIndex - currentIndex) * sizeof (ElementType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memmove (elements + newIndex + 1,
|
||||||
|
elements + newIndex,
|
||||||
|
(size_t) (currentIndex - newIndex) * sizeof (ElementType));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy (elements + newIndex, tempCopy, sizeof (ElementType));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memmove (elements + newIndex + 1,
|
auto* e = elements + currentIndex;
|
||||||
elements + newIndex,
|
ElementType tempCopy (std::move (*e));
|
||||||
(size_t) (currentIndex - newIndex) * sizeof (ElementType));
|
auto delta = newIndex - currentIndex;
|
||||||
}
|
|
||||||
|
|
||||||
memcpy (elements + newIndex, tempCopy, sizeof (ElementType));
|
if (delta > 0)
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = ElementType>
|
|
||||||
NonTriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept
|
|
||||||
{
|
|
||||||
auto* e = elements + currentIndex;
|
|
||||||
ElementType tempCopy (std::move (*e));
|
|
||||||
auto delta = newIndex - currentIndex;
|
|
||||||
|
|
||||||
if (delta > 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < delta; ++i)
|
|
||||||
{
|
{
|
||||||
moveAssignElement (e, std::move (*(e + 1)));
|
for (int i = 0; i < delta; ++i)
|
||||||
++e;
|
{
|
||||||
|
moveAssignElement (e, std::move (*(e + 1)));
|
||||||
|
++e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int i = 0; i < -delta; ++i)
|
|
||||||
{
|
{
|
||||||
moveAssignElement (e, std::move (*(e - 1)));
|
for (int i = 0; i < -delta; ++i)
|
||||||
--e;
|
{
|
||||||
|
moveAssignElement (e, std::move (*(e - 1)));
|
||||||
|
--e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
moveAssignElement (e, std::move (tempCopy));
|
moveAssignElement (e, std::move (tempCopy));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
@ -569,19 +554,17 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = ElementType>
|
void moveAssignElement (ElementType* destination, ElementType&& source)
|
||||||
typename std::enable_if<std::is_move_assignable<T>::value, void>::type
|
|
||||||
moveAssignElement (ElementType* destination, ElementType&& source)
|
|
||||||
{
|
{
|
||||||
*destination = std::move (source);
|
if constexpr (std::is_move_assignable_v<ElementType>)
|
||||||
}
|
{
|
||||||
|
*destination = std::move (source);
|
||||||
template <typename T = ElementType>
|
}
|
||||||
typename std::enable_if<! std::is_move_assignable<T>::value, void>::type
|
else
|
||||||
moveAssignElement (ElementType* destination, ElementType&& source)
|
{
|
||||||
{
|
destination->~ElementType();
|
||||||
destination->~ElementType();
|
new (destination) ElementType (std::move (source));
|
||||||
new (destination) ElementType (std::move (source));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void checkSourceIsNotAMember (const ElementType& element)
|
void checkSourceIsNotAMember (const ElementType& element)
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
class Optional
|
class Optional
|
||||||
{
|
{
|
||||||
template <typename> struct IsOptional : std::false_type {};
|
template <typename> struct IsOptional : std::false_type {};
|
||||||
template <typename T> struct IsOptional<Optional<T>> : std::true_type {};
|
template <typename T> struct IsOptional<Optional<T>> : std::true_type {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Optional() = default;
|
Optional() = default;
|
||||||
|
|
|
||||||
|
|
@ -654,11 +654,8 @@ namespace TypeHelpers
|
||||||
|
|
||||||
@tags{Core}
|
@tags{Core}
|
||||||
*/
|
*/
|
||||||
template <typename Type> struct SmallestFloatType { using type = float; };
|
template <typename Type>
|
||||||
|
using SmallestFloatType = std::conditional_t<std::is_same_v<Type, double>, double, float>;
|
||||||
#ifndef DOXYGEN
|
|
||||||
template <> struct SmallestFloatType <double> { using type = double; };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** These templates are designed to take an integer type, and return an unsigned int
|
/** These templates are designed to take an integer type, and return an unsigned int
|
||||||
version with the same size.
|
version with the same size.
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Scans an array of values for its min and max, and returns these as a Range. */
|
/** Scans an array of values for its min and max, and returns these as a Range. */
|
||||||
template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value, int> = 0>
|
template <typename Integral, std::enable_if_t<std::is_integral_v<Integral>, int> = 0>
|
||||||
static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept
|
static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept
|
||||||
{
|
{
|
||||||
if (numValues <= 0)
|
if (numValues <= 0)
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,8 @@ class HeapBlock
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
template <class OtherElementType>
|
template <class OtherElementType>
|
||||||
using AllowConversion = typename std::enable_if<std::is_base_of<typename std::remove_pointer<ElementType>::type,
|
using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>,
|
||||||
typename std::remove_pointer<OtherElementType>::type>::value>::type;
|
std::remove_pointer_t<OtherElementType>>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
@ -107,7 +107,7 @@ public:
|
||||||
If you want an array of zero values, you can use the calloc() method or the
|
If you want an array of zero values, you can use the calloc() method or the
|
||||||
other constructor that takes an InitialisationState parameter.
|
other constructor that takes an InitialisationState parameter.
|
||||||
*/
|
*/
|
||||||
template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0>
|
template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
|
||||||
explicit HeapBlock (SizeType numElements)
|
explicit HeapBlock (SizeType numElements)
|
||||||
: data (static_cast<ElementType*> (std::malloc (static_cast<size_t> (numElements) * sizeof (ElementType))))
|
: data (static_cast<ElementType*> (std::malloc (static_cast<size_t> (numElements) * sizeof (ElementType))))
|
||||||
{
|
{
|
||||||
|
|
@ -119,7 +119,7 @@ public:
|
||||||
The initialiseToZero parameter determines whether the new memory should be cleared,
|
The initialiseToZero parameter determines whether the new memory should be cleared,
|
||||||
or left uninitialised.
|
or left uninitialised.
|
||||||
*/
|
*/
|
||||||
template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0>
|
template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>
|
||||||
HeapBlock (SizeType numElements, bool initialiseToZero)
|
HeapBlock (SizeType numElements, bool initialiseToZero)
|
||||||
: data (static_cast<ElementType*> (initialiseToZero
|
: data (static_cast<ElementType*> (initialiseToZero
|
||||||
? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType))
|
? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType))
|
||||||
|
|
@ -152,7 +152,7 @@ public:
|
||||||
|
|
||||||
/** Converting move constructor.
|
/** Converting move constructor.
|
||||||
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,
|
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,
|
||||||
where std::is_base_of<Base, Derived>::value == true.
|
where std::is_base_of_v<Base, Derived> == true.
|
||||||
*/
|
*/
|
||||||
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
|
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
|
||||||
HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
|
HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
|
||||||
|
|
@ -163,7 +163,7 @@ public:
|
||||||
|
|
||||||
/** Converting move assignment operator.
|
/** Converting move assignment operator.
|
||||||
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,
|
Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,
|
||||||
where std::is_base_of<Base, Derived>::value == true.
|
where std::is_base_of_v<Base, Derived> == true.
|
||||||
*/
|
*/
|
||||||
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
|
template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>
|
||||||
HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
|
HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept
|
||||||
|
|
|
||||||
|
|
@ -84,9 +84,10 @@ inline void writeUnaligned (void* dstPtr, Type value) noexcept
|
||||||
to a region that has suitable alignment for `Type`, e.g. regions returned from
|
to a region that has suitable alignment for `Type`, e.g. regions returned from
|
||||||
malloc/calloc that should be suitable for any non-over-aligned type.
|
malloc/calloc that should be suitable for any non-over-aligned type.
|
||||||
*/
|
*/
|
||||||
template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0>
|
template <typename Type>
|
||||||
inline Type unalignedPointerCast (void* ptr) noexcept
|
inline Type unalignedPointerCast (void* ptr) noexcept
|
||||||
{
|
{
|
||||||
|
static_assert (std::is_pointer_v<Type>);
|
||||||
return reinterpret_cast<Type> (ptr);
|
return reinterpret_cast<Type> (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,9 +98,10 @@ inline Type unalignedPointerCast (void* ptr) noexcept
|
||||||
to a region that has suitable alignment for `Type`, e.g. regions returned from
|
to a region that has suitable alignment for `Type`, e.g. regions returned from
|
||||||
malloc/calloc that should be suitable for any non-over-aligned type.
|
malloc/calloc that should be suitable for any non-over-aligned type.
|
||||||
*/
|
*/
|
||||||
template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0>
|
template <typename Type>
|
||||||
inline Type unalignedPointerCast (const void* ptr) noexcept
|
inline Type unalignedPointerCast (const void* ptr) noexcept
|
||||||
{
|
{
|
||||||
|
static_assert (std::is_pointer_v<Type>);
|
||||||
return reinterpret_cast<Type> (ptr);
|
return reinterpret_cast<Type> (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,15 +30,10 @@ namespace detail
|
||||||
using Void = void;
|
using Void = void;
|
||||||
|
|
||||||
template <typename, typename = void>
|
template <typename, typename = void>
|
||||||
struct EqualityComparableToNullptr
|
constexpr auto equalityComparableToNullptr = false;
|
||||||
: std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct EqualityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>>
|
constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true;
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr bool shouldCheckAgainstNullptr = EqualityComparableToNullptr<T>::value;
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -53,23 +48,22 @@ namespace detail
|
||||||
*/
|
*/
|
||||||
struct NullCheckedInvocation
|
struct NullCheckedInvocation
|
||||||
{
|
{
|
||||||
template <typename Callable, typename... Args,
|
template <typename Callable, typename... Args>
|
||||||
std::enable_if_t<detail::shouldCheckAgainstNullptr<Callable>, int> = 0>
|
|
||||||
static void invoke (Callable&& fn, Args&&... args)
|
static void invoke (Callable&& fn, Args&&... args)
|
||||||
{
|
{
|
||||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")
|
if constexpr (detail::equalityComparableToNullptr<Callable>)
|
||||||
|
{
|
||||||
|
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")
|
||||||
|
|
||||||
if (fn != nullptr)
|
if (fn != nullptr)
|
||||||
|
fn (std::forward<Args> (args)...);
|
||||||
|
|
||||||
|
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
fn (std::forward<Args> (args)...);
|
fn (std::forward<Args> (args)...);
|
||||||
|
}
|
||||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callable, typename... Args,
|
|
||||||
std::enable_if_t<! detail::shouldCheckAgainstNullptr<Callable>, int> = 0>
|
|
||||||
static void invoke (Callable&& fn, Args&&... args)
|
|
||||||
{
|
|
||||||
fn (std::forward<Args> (args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
|
|
@ -82,7 +76,7 @@ struct NullCheckedInvocation
|
||||||
Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
|
Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
|
||||||
*/
|
*/
|
||||||
template <typename A, typename B>
|
template <typename A, typename B>
|
||||||
using DisableIfSameOrDerived = typename std::enable_if_t<! std::is_base_of<A, std::remove_reference_t<B>>::value>;
|
using DisableIfSameOrDerived = std::enable_if_t<! std::is_base_of_v<A, std::remove_reference_t<B>>>;
|
||||||
|
|
||||||
/** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */
|
/** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */
|
||||||
template <typename Object, typename OtherObject, typename Member>
|
template <typename Object, typename OtherObject, typename Member>
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ struct CFObjectDeleter
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CFType>
|
template <typename CFType>
|
||||||
using CFUniquePtr = std::unique_ptr<typename std::remove_pointer<CFType>::type, CFObjectDeleter<CFType>>;
|
using CFUniquePtr = std::unique_ptr<std::remove_pointer_t<CFType>, CFObjectDeleter<CFType>>;
|
||||||
|
|
||||||
template <typename CFType>
|
template <typename CFType>
|
||||||
struct CFObjectHolder
|
struct CFObjectHolder
|
||||||
|
|
|
||||||
|
|
@ -490,8 +490,8 @@ public:
|
||||||
template <typename ResultType>
|
template <typename ResultType>
|
||||||
struct HexParser
|
struct HexParser
|
||||||
{
|
{
|
||||||
static_assert (std::is_unsigned<ResultType>::value, "ResultType must be unsigned because "
|
static_assert (std::is_unsigned_v<ResultType>, "ResultType must be unsigned because "
|
||||||
"left-shifting a negative value is UB");
|
"left-shifting a negative value is UB");
|
||||||
|
|
||||||
template <typename CharPointerType>
|
template <typename CharPointerType>
|
||||||
static ResultType parse (CharPointerType t) noexcept
|
static ResultType parse (CharPointerType t) noexcept
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,9 @@ private:
|
||||||
// a block of memory here that's big enough to be used internally as a windows
|
// a block of memory here that's big enough to be used internally as a windows
|
||||||
// CRITICAL_SECTION structure.
|
// CRITICAL_SECTION structure.
|
||||||
#if JUCE_64BIT
|
#if JUCE_64BIT
|
||||||
std::aligned_storage<44, 8>::type lock;
|
std::aligned_storage_t<44, 8> lock;
|
||||||
#else
|
#else
|
||||||
std::aligned_storage<24, 8>::type lock;
|
std::aligned_storage_t<24, 8> lock;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
mutable pthread_mutex_t lock;
|
mutable pthread_mutex_t lock;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ 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 T, bool = std::is_floating_point<T>::value>
|
template <typename T, bool = std::is_floating_point_v<T>>
|
||||||
struct ElementType
|
struct ElementType
|
||||||
{
|
{
|
||||||
using Type = T;
|
using Type = T;
|
||||||
|
|
@ -71,10 +71,10 @@ class AudioBlock
|
||||||
private:
|
private:
|
||||||
template <typename OtherSampleType>
|
template <typename OtherSampleType>
|
||||||
using MayUseConvertingConstructor =
|
using MayUseConvertingConstructor =
|
||||||
std::enable_if_t<std::is_same<std::remove_const_t<SampleType>,
|
std::enable_if_t<std::is_same_v<std::remove_const_t<SampleType>,
|
||||||
std::remove_const_t<OtherSampleType>>::value
|
std::remove_const_t<OtherSampleType>>
|
||||||
&& std::is_const<SampleType>::value
|
&& std::is_const_v<SampleType>
|
||||||
&& ! std::is_const<OtherSampleType>::value,
|
&& ! std::is_const_v<OtherSampleType>,
|
||||||
int>;
|
int>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -337,7 +337,7 @@ public:
|
||||||
SIMDRegister then incrementing dstPos by one will increase the sample position
|
SIMDRegister then incrementing dstPos by one will increase the sample position
|
||||||
in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.
|
in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.
|
||||||
*/
|
*/
|
||||||
void copyTo (AudioBuffer<typename std::remove_const<NumericType>::type>& dst, size_t srcPos = 0, size_t dstPos = 0,
|
void copyTo (AudioBuffer<std::remove_const_t<NumericType>>& dst, size_t srcPos = 0, size_t dstPos = 0,
|
||||||
size_t numElements = std::numeric_limits<size_t>::max()) const
|
size_t numElements = std::numeric_limits<size_t>::max()) const
|
||||||
{
|
{
|
||||||
auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor;
|
auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor;
|
||||||
|
|
@ -518,7 +518,7 @@ public:
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Finds the minimum and maximum value of the buffer. */
|
/** Finds the minimum and maximum value of the buffer. */
|
||||||
Range<typename std::remove_const<NumericType>::type> findMinAndMax() const noexcept
|
Range<std::remove_const_t<NumericType>> findMinAndMax() const noexcept
|
||||||
{
|
{
|
||||||
if (numChannels == 0)
|
if (numChannels == 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
@ -559,11 +559,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<std::remove_const_t<SampleType>, float>::value
|
static_assert (std::is_same_v<std::remove_const_t<SampleType>, float>
|
||||||
|| std::is_same<std::remove_const_t<SampleType>, double>::value
|
|| std::is_same_v<std::remove_const_t<SampleType>, double>
|
||||||
#if JUCE_USE_SIMD
|
#if JUCE_USE_SIMD
|
||||||
|| std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value
|
|| std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<float>>
|
||||||
|| std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value
|
|| std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<double>>
|
||||||
#endif
|
#endif
|
||||||
, "AudioBlock only supports single or double precision floating point types");
|
, "AudioBlock only supports single or double precision floating point types");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -319,117 +319,109 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T>
|
void copyingTests()
|
||||||
using ScalarVoid = typename std::enable_if_t < std::is_scalar <T>::value, void>;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
using SIMDVoid = typename std::enable_if_t <! std::is_scalar <T>::value, void>;
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
template <typename T = SampleType>
|
|
||||||
ScalarVoid<T> copyingTests()
|
|
||||||
{
|
{
|
||||||
auto unchangedElement1 = block.getSample (0, 4);
|
if constexpr (std::is_scalar_v<SampleType>)
|
||||||
auto unchangedElement2 = block.getSample (1, 1);
|
{
|
||||||
|
auto unchangedElement1 = block.getSample (0, 4);
|
||||||
|
auto unchangedElement2 = block.getSample (1, 1);
|
||||||
|
|
||||||
AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);
|
AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);
|
||||||
|
|
||||||
block.copyFrom (otherBuffer, 1, 2, 2);
|
block.copyFrom (otherBuffer, 1, 2, 2);
|
||||||
|
|
||||||
expectEquals (block.getSample (0, 4), unchangedElement1);
|
expectEquals (block.getSample (0, 4), unchangedElement1);
|
||||||
expectEquals (block.getSample (1, 1), unchangedElement2);
|
expectEquals (block.getSample (1, 1), unchangedElement2);
|
||||||
expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));
|
expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));
|
||||||
expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));
|
expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));
|
||||||
|
|
||||||
resetBlocks();
|
resetBlocks();
|
||||||
|
|
||||||
unchangedElement1 = otherBuffer.getSample (0, 4);
|
unchangedElement1 = otherBuffer.getSample (0, 4);
|
||||||
unchangedElement2 = otherBuffer.getSample (1, 3);
|
unchangedElement2 = otherBuffer.getSample (1, 3);
|
||||||
|
|
||||||
block.copyTo (otherBuffer, 2, 1, 2);
|
block.copyTo (otherBuffer, 2, 1, 2);
|
||||||
|
|
||||||
expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);
|
expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);
|
||||||
expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);
|
expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);
|
||||||
expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));
|
expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));
|
||||||
expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));
|
expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));
|
||||||
|
}
|
||||||
|
#if JUCE_USE_SIMD
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;
|
||||||
|
AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),
|
||||||
|
(int) (block.getNumSamples() * numSIMDElements));
|
||||||
|
|
||||||
|
for (int c = 0; c < numericData.getNumChannels(); ++c)
|
||||||
|
std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);
|
||||||
|
|
||||||
|
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);
|
||||||
|
|
||||||
|
auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);
|
||||||
|
auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);
|
||||||
|
auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);
|
||||||
|
auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);
|
||||||
|
|
||||||
|
block.copyTo (numericData, 1, 2, 2);
|
||||||
|
|
||||||
|
expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);
|
||||||
|
expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);
|
||||||
|
expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));
|
||||||
|
expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));
|
||||||
|
|
||||||
|
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);
|
||||||
|
|
||||||
|
auto unchangedSIMDElement1 = block.getSample (0, 1);
|
||||||
|
auto unchangedSIMDElement2 = block.getSample (1, 4);
|
||||||
|
|
||||||
|
block.copyFrom (numericData, 1, 2, 2);
|
||||||
|
|
||||||
|
expect (block.getSample (0, 1) == unchangedSIMDElement1);
|
||||||
|
expect (block.getSample (1, 4) == unchangedSIMDElement2);
|
||||||
|
expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));
|
||||||
|
expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));
|
||||||
|
|
||||||
|
if (numSIMDElements > 1)
|
||||||
|
{
|
||||||
|
expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1)));
|
||||||
|
expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JUCE_USE_SIMD
|
//==============================================================================
|
||||||
template <typename T = SampleType>
|
void smoothedValueTests()
|
||||||
SIMDVoid<T> copyingTests()
|
|
||||||
{
|
{
|
||||||
auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;
|
if constexpr (std::is_scalar_v<SampleType>)
|
||||||
AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),
|
|
||||||
(int) (block.getNumSamples() * numSIMDElements));
|
|
||||||
|
|
||||||
for (int c = 0; c < numericData.getNumChannels(); ++c)
|
|
||||||
std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);
|
|
||||||
|
|
||||||
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);
|
|
||||||
|
|
||||||
auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);
|
|
||||||
auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);
|
|
||||||
auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);
|
|
||||||
auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);
|
|
||||||
|
|
||||||
block.copyTo (numericData, 1, 2, 2);
|
|
||||||
|
|
||||||
expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);
|
|
||||||
expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);
|
|
||||||
expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));
|
|
||||||
expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));
|
|
||||||
|
|
||||||
numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);
|
|
||||||
|
|
||||||
auto unchangedSIMDElement1 = block.getSample (0, 1);
|
|
||||||
auto unchangedSIMDElement2 = block.getSample (1, 4);
|
|
||||||
|
|
||||||
block.copyFrom (numericData, 1, 2, 2);
|
|
||||||
|
|
||||||
expect (block.getSample (0, 1) == unchangedSIMDElement1);
|
|
||||||
expect (block.getSample (1, 4) == unchangedSIMDElement2);
|
|
||||||
expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));
|
|
||||||
expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));
|
|
||||||
|
|
||||||
if (numSIMDElements > 1)
|
|
||||||
{
|
{
|
||||||
expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1)));
|
block.fill ((SampleType) 1.0);
|
||||||
expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1)));
|
SmoothedValue<SampleType> sv { (SampleType) 1.0 };
|
||||||
|
sv.reset (1, 4);
|
||||||
|
sv.setTargetValue ((SampleType) 0.0);
|
||||||
|
|
||||||
|
block.multiplyBy (sv);
|
||||||
|
expect (block.getSample (0, 2) < (SampleType) 1.0);
|
||||||
|
expect (block.getSample (1, 2) < (SampleType) 1.0);
|
||||||
|
expect (block.getSample (0, 2) > (SampleType) 0.0);
|
||||||
|
expect (block.getSample (1, 2) > (SampleType) 0.0);
|
||||||
|
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
|
||||||
|
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
|
||||||
|
|
||||||
|
sv.setCurrentAndTargetValue (-1.0f);
|
||||||
|
sv.setTargetValue (0.0f);
|
||||||
|
otherBlock.fill (-1.0f);
|
||||||
|
block.replaceWithProductOf (otherBlock, sv);
|
||||||
|
expect (block.getSample (0, 2) < (SampleType) 1.0);
|
||||||
|
expect (block.getSample (1, 2) < (SampleType) 1.0);
|
||||||
|
expect (block.getSample (0, 2) > (SampleType) 0.0);
|
||||||
|
expect (block.getSample (1, 2) > (SampleType) 0.0);
|
||||||
|
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
|
||||||
|
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
//==============================================================================
|
|
||||||
template <typename T = SampleType>
|
|
||||||
ScalarVoid<T> smoothedValueTests()
|
|
||||||
{
|
|
||||||
block.fill ((SampleType) 1.0);
|
|
||||||
SmoothedValue<SampleType> sv { (SampleType) 1.0 };
|
|
||||||
sv.reset (1, 4);
|
|
||||||
sv.setTargetValue ((SampleType) 0.0);
|
|
||||||
|
|
||||||
block.multiplyBy (sv);
|
|
||||||
expect (block.getSample (0, 2) < (SampleType) 1.0);
|
|
||||||
expect (block.getSample (1, 2) < (SampleType) 1.0);
|
|
||||||
expect (block.getSample (0, 2) > (SampleType) 0.0);
|
|
||||||
expect (block.getSample (1, 2) > (SampleType) 0.0);
|
|
||||||
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
|
|
||||||
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
|
|
||||||
|
|
||||||
sv.setCurrentAndTargetValue (-1.0f);
|
|
||||||
sv.setTargetValue (0.0f);
|
|
||||||
otherBlock.fill (-1.0f);
|
|
||||||
block.replaceWithProductOf (otherBlock, sv);
|
|
||||||
expect (block.getSample (0, 2) < (SampleType) 1.0);
|
|
||||||
expect (block.getSample (1, 2) < (SampleType) 1.0);
|
|
||||||
expect (block.getSample (0, 2) > (SampleType) 0.0);
|
|
||||||
expect (block.getSample (1, 2) > (SampleType) 0.0);
|
|
||||||
expectEquals (block.getSample (0, 5), (SampleType) 0.0);
|
|
||||||
expectEquals (block.getSample (1, 5), (SampleType) 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = SampleType>
|
|
||||||
SIMDVoid<T> smoothedValueTests() {}
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
void resetBlocks()
|
void resetBlocks()
|
||||||
|
|
@ -451,7 +443,7 @@ private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
static SampleType* allocateAlignedMemory (int numSamplesToAllocate)
|
static SampleType* allocateAlignedMemory (int numSamplesToAllocate)
|
||||||
{
|
{
|
||||||
auto alignmentLowerBound = std::alignment_of<SampleType>::value;
|
auto alignmentLowerBound = std::alignment_of_v<SampleType>;
|
||||||
#if ! JUCE_WINDOWS
|
#if ! JUCE_WINDOWS
|
||||||
alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);
|
alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -56,13 +56,13 @@ namespace detail
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fn, typename Ret, typename... Args>
|
template <typename Fn, typename Ret, typename... Args>
|
||||||
typename std::enable_if<std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)
|
std::enable_if_t<std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)
|
||||||
{
|
{
|
||||||
(*reinterpret_cast<Fn*> (s)) (args...);
|
(*reinterpret_cast<Fn*> (s)) (args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Fn, typename Ret, typename... Args>
|
template <typename Fn, typename Ret, typename... Args>
|
||||||
typename std::enable_if<! std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)
|
std::enable_if_t<! std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)
|
||||||
{
|
{
|
||||||
return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);
|
return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);
|
||||||
}
|
}
|
||||||
|
|
@ -102,16 +102,16 @@ template <size_t len, typename Ret, typename... Args>
|
||||||
class FixedSizeFunction<len, Ret (Args...)>
|
class FixedSizeFunction<len, Ret (Args...)>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using Storage = typename std::aligned_storage<len>::type;
|
using Storage = std::aligned_storage_t<len>;
|
||||||
|
|
||||||
template <typename Item>
|
template <typename Item>
|
||||||
using Decay = typename std::decay<Item>::type;
|
using Decay = std::decay_t<Item>;
|
||||||
|
|
||||||
template <typename Item, typename Fn = Decay<Item>>
|
template <typename Item, typename Fn = Decay<Item>>
|
||||||
using IntIfValidConversion = typename std::enable_if<sizeof (Fn) <= len
|
using IntIfValidConversion = std::enable_if_t<sizeof (Fn) <= len
|
||||||
&& alignof (Fn) <= alignof (Storage)
|
&& alignof (Fn) <= alignof (Storage)
|
||||||
&& ! std::is_same<FixedSizeFunction, Fn>::value,
|
&& ! std::is_same_v<FixedSizeFunction, Fn>,
|
||||||
int>::type;
|
int>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Create an empty function. */
|
/** Create an empty function. */
|
||||||
|
|
@ -149,7 +149,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converting constructor from smaller FixedSizeFunctions. */
|
/** Converting constructor from smaller FixedSizeFunctions. */
|
||||||
template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>
|
template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>
|
||||||
FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
|
FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
|
||||||
: vtable (other.vtable)
|
: vtable (other.vtable)
|
||||||
{
|
{
|
||||||
|
|
@ -172,7 +172,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Move assignment from smaller FixedSizeFunctions. */
|
/** Move assignment from smaller FixedSizeFunctions. */
|
||||||
template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>
|
template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>
|
||||||
FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
|
FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
|
||||||
{
|
{
|
||||||
return *this = FixedSizeFunction (std::move (other));
|
return *this = FixedSizeFunction (std::move (other));
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ struct SIMDRegister
|
||||||
|
|
||||||
/** The corresponding primitive integer type, for example, this will be int32_t
|
/** The corresponding primitive integer type, for example, this will be int32_t
|
||||||
if type is a float. */
|
if type is a float. */
|
||||||
using MaskType = typename SIMDInternal::MaskTypeFor<ElementType>::type;
|
using MaskType = SIMDInternal::MaskType<ElementType>;
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Here are some types which are needed internally
|
// Here are some types which are needed internally
|
||||||
|
|
|
||||||
|
|
@ -30,31 +30,30 @@ namespace dsp
|
||||||
|
|
||||||
namespace SIMDRegister_test_internal
|
namespace SIMDRegister_test_internal
|
||||||
{
|
{
|
||||||
template <typename type, typename = void> struct RandomPrimitive {};
|
|
||||||
|
|
||||||
template <typename type>
|
template <typename type>
|
||||||
struct RandomPrimitive<type, typename std::enable_if<std::is_floating_point<type>::value>::type>
|
struct RandomPrimitive
|
||||||
{
|
{
|
||||||
static type next (Random& random)
|
static type next (Random& random)
|
||||||
{
|
{
|
||||||
return static_cast<type> (std::is_signed<type>::value ? (random.nextFloat() * 16.0) - 8.0
|
if constexpr (std::is_floating_point_v<type>)
|
||||||
: (random.nextFloat() * 8.0));
|
{
|
||||||
}
|
return static_cast<type> (std::is_signed_v<type> ? (random.nextFloat() * 16.0) - 8.0
|
||||||
};
|
: (random.nextFloat() * 8.0));
|
||||||
|
}
|
||||||
template <typename type>
|
else if constexpr (std::is_integral_v<type>)
|
||||||
struct RandomPrimitive<type, typename std::enable_if<std::is_integral<type>::value>::type>
|
{
|
||||||
{
|
return static_cast<type> (random.nextInt64());
|
||||||
static type next (Random& random)
|
}
|
||||||
{
|
|
||||||
return static_cast<type> (random.nextInt64());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename type>
|
template <typename type>
|
||||||
struct RandomValue
|
struct RandomValue
|
||||||
{
|
{
|
||||||
static type next (Random& random) { return RandomPrimitive<type>::next (random); }
|
static type next (Random& random)
|
||||||
|
{
|
||||||
|
return RandomPrimitive<type>::next (random);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename type>
|
template <typename type>
|
||||||
|
|
@ -756,11 +755,10 @@ public:
|
||||||
template <typename type>
|
template <typename type>
|
||||||
static void run (UnitTest& u, Random& random, Tag<type>)
|
static void run (UnitTest& u, Random& random, Tag<type>)
|
||||||
{
|
{
|
||||||
bool is_signed = std::is_signed<type>::value;
|
|
||||||
type array [SIMDRegister<type>::SIMDNumElements];
|
type array [SIMDRegister<type>::SIMDNumElements];
|
||||||
|
|
||||||
auto value = is_signed ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)
|
auto value = std::is_signed_v<type> ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)
|
||||||
: static_cast<type> (random.nextFloat() * 8.0);
|
: static_cast<type> (random.nextFloat() * 8.0);
|
||||||
|
|
||||||
std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value);
|
std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value);
|
||||||
SIMDRegister<type> a, b;
|
SIMDRegister<type> a, b;
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ public:
|
||||||
stereo processing.
|
stereo processing.
|
||||||
*/
|
*/
|
||||||
template <typename ProcessContext,
|
template <typename ProcessContext,
|
||||||
std::enable_if_t<std::is_same<typename ProcessContext::SampleType, float>::value, int> = 0>
|
std::enable_if_t<std::is_same_v<typename ProcessContext::SampleType, float>, int> = 0>
|
||||||
void process (const ProcessContext& context) noexcept
|
void process (const ProcessContext& context) noexcept
|
||||||
{
|
{
|
||||||
processSamples (context.getInputBlock(), context.getOutputBlock(), context.isBypassed);
|
processSamples (context.getInputBlock(), context.getOutputBlock(), context.isBypassed);
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,10 @@ 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 = typename std::remove_cv<Primitive>::type; };
|
template <typename Primitive> using MaskType = typename MaskTypeFor<Primitive>::type;
|
||||||
template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = typename std::remove_cv<Primitive>::type; };
|
|
||||||
|
template <typename Primitive> struct PrimitiveType { using type = std::remove_cv_t<Primitive>; };
|
||||||
|
template <typename Primitive> struct PrimitiveType<std::complex<Primitive>> { using type = std::remove_cv_t<Primitive>; };
|
||||||
|
|
||||||
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 }; };
|
||||||
|
|
@ -63,7 +65,7 @@ struct SIMDFallbackOps
|
||||||
static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value;
|
static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value;
|
||||||
|
|
||||||
// helper types
|
// helper types
|
||||||
using MaskType = typename SIMDInternal::MaskTypeFor<ScalarType>::type;
|
using MaskType = SIMDInternal::MaskType<ScalarType>;
|
||||||
union UnionType { vSIMDType v; ScalarType s[n]; };
|
union UnionType { vSIMDType v; ScalarType s[n]; };
|
||||||
union UnionMaskType { vSIMDType v; MaskType m[n]; };
|
union UnionMaskType { vSIMDType v; MaskType m[n]; };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,126 +201,104 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = InterpolationType>
|
SampleType interpolateSample (int channel)
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, SampleType>::type
|
|
||||||
interpolateSample (int channel) const
|
|
||||||
{
|
{
|
||||||
auto index = (readPos[(size_t) channel] + delayInt) % totalSize;
|
if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::None>)
|
||||||
return bufferData.getSample (channel, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = InterpolationType>
|
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, SampleType>::type
|
|
||||||
interpolateSample (int channel) const
|
|
||||||
{
|
|
||||||
auto index1 = readPos[(size_t) channel] + delayInt;
|
|
||||||
auto index2 = index1 + 1;
|
|
||||||
|
|
||||||
if (index2 >= totalSize)
|
|
||||||
{
|
{
|
||||||
index1 %= totalSize;
|
auto index = (readPos[(size_t) channel] + delayInt) % totalSize;
|
||||||
index2 %= totalSize;
|
return bufferData.getSample (channel, index);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Linear>)
|
||||||
auto value1 = bufferData.getSample (channel, index1);
|
|
||||||
auto value2 = bufferData.getSample (channel, index2);
|
|
||||||
|
|
||||||
return value1 + delayFrac * (value2 - value1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = InterpolationType>
|
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, SampleType>::type
|
|
||||||
interpolateSample (int channel) const
|
|
||||||
{
|
|
||||||
auto index1 = readPos[(size_t) channel] + delayInt;
|
|
||||||
auto index2 = index1 + 1;
|
|
||||||
auto index3 = index2 + 1;
|
|
||||||
auto index4 = index3 + 1;
|
|
||||||
|
|
||||||
if (index4 >= totalSize)
|
|
||||||
{
|
{
|
||||||
index1 %= totalSize;
|
auto index1 = readPos[(size_t) channel] + delayInt;
|
||||||
index2 %= totalSize;
|
auto index2 = index1 + 1;
|
||||||
index3 %= totalSize;
|
|
||||||
index4 %= totalSize;
|
if (index2 >= totalSize)
|
||||||
|
{
|
||||||
|
index1 %= totalSize;
|
||||||
|
index2 %= totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto value1 = bufferData.getSample (channel, index1);
|
||||||
|
auto value2 = bufferData.getSample (channel, index2);
|
||||||
|
|
||||||
|
return value1 + delayFrac * (value2 - value1);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)
|
||||||
auto* samples = bufferData.getReadPointer (channel);
|
|
||||||
|
|
||||||
auto value1 = samples[index1];
|
|
||||||
auto value2 = samples[index2];
|
|
||||||
auto value3 = samples[index3];
|
|
||||||
auto value4 = samples[index4];
|
|
||||||
|
|
||||||
auto d1 = delayFrac - 1.f;
|
|
||||||
auto d2 = delayFrac - 2.f;
|
|
||||||
auto d3 = delayFrac - 3.f;
|
|
||||||
|
|
||||||
auto c1 = -d1 * d2 * d3 / 6.f;
|
|
||||||
auto c2 = d2 * d3 * 0.5f;
|
|
||||||
auto c3 = -d1 * d3 * 0.5f;
|
|
||||||
auto c4 = d1 * d2 / 6.f;
|
|
||||||
|
|
||||||
return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = InterpolationType>
|
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, SampleType>::type
|
|
||||||
interpolateSample (int channel)
|
|
||||||
{
|
|
||||||
auto index1 = readPos[(size_t) channel] + delayInt;
|
|
||||||
auto index2 = index1 + 1;
|
|
||||||
|
|
||||||
if (index2 >= totalSize)
|
|
||||||
{
|
{
|
||||||
index1 %= totalSize;
|
auto index1 = readPos[(size_t) channel] + delayInt;
|
||||||
index2 %= totalSize;
|
auto index2 = index1 + 1;
|
||||||
|
auto index3 = index2 + 1;
|
||||||
|
auto index4 = index3 + 1;
|
||||||
|
|
||||||
|
if (index4 >= totalSize)
|
||||||
|
{
|
||||||
|
index1 %= totalSize;
|
||||||
|
index2 %= totalSize;
|
||||||
|
index3 %= totalSize;
|
||||||
|
index4 %= totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* samples = bufferData.getReadPointer (channel);
|
||||||
|
|
||||||
|
auto value1 = samples[index1];
|
||||||
|
auto value2 = samples[index2];
|
||||||
|
auto value3 = samples[index3];
|
||||||
|
auto value4 = samples[index4];
|
||||||
|
|
||||||
|
auto d1 = delayFrac - 1.f;
|
||||||
|
auto d2 = delayFrac - 2.f;
|
||||||
|
auto d3 = delayFrac - 3.f;
|
||||||
|
|
||||||
|
auto c1 = -d1 * d2 * d3 / 6.f;
|
||||||
|
auto c2 = d2 * d3 * 0.5f;
|
||||||
|
auto c3 = -d1 * d3 * 0.5f;
|
||||||
|
auto c4 = d1 * d2 / 6.f;
|
||||||
|
|
||||||
|
return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);
|
||||||
}
|
}
|
||||||
|
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)
|
||||||
|
{
|
||||||
|
auto index1 = readPos[(size_t) channel] + delayInt;
|
||||||
|
auto index2 = index1 + 1;
|
||||||
|
|
||||||
auto value1 = bufferData.getSample (channel, index1);
|
if (index2 >= totalSize)
|
||||||
auto value2 = bufferData.getSample (channel, index2);
|
{
|
||||||
|
index1 %= totalSize;
|
||||||
|
index2 %= totalSize;
|
||||||
|
}
|
||||||
|
|
||||||
auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);
|
auto value1 = bufferData.getSample (channel, index1);
|
||||||
v[(size_t) channel] = output;
|
auto value2 = bufferData.getSample (channel, index2);
|
||||||
|
|
||||||
return output;
|
auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);
|
||||||
|
v[(size_t) channel] = output;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
template <typename T = InterpolationType>
|
void updateInternalVariables()
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, void>::type
|
|
||||||
updateInternalVariables()
|
|
||||||
{
|
{
|
||||||
}
|
if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)
|
||||||
|
|
||||||
template <typename T = InterpolationType>
|
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, void>::type
|
|
||||||
updateInternalVariables()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T = InterpolationType>
|
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, void>::type
|
|
||||||
updateInternalVariables()
|
|
||||||
{
|
|
||||||
if (delayInt >= 1)
|
|
||||||
{
|
{
|
||||||
delayFrac++;
|
if (delayInt >= 1)
|
||||||
delayInt--;
|
{
|
||||||
|
delayFrac++;
|
||||||
|
delayInt--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)
|
||||||
|
|
||||||
template <typename T = InterpolationType>
|
|
||||||
typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, void>::type
|
|
||||||
updateInternalVariables()
|
|
||||||
{
|
|
||||||
if (delayFrac < (SampleType) 0.618 && delayInt >= 1)
|
|
||||||
{
|
{
|
||||||
delayFrac++;
|
if (delayFrac < (SampleType) 0.618 && delayInt >= 1)
|
||||||
delayInt--;
|
{
|
||||||
}
|
delayFrac++;
|
||||||
|
delayInt--;
|
||||||
|
}
|
||||||
|
|
||||||
alpha = (1 - delayFrac) / (1 + delayFrac);
|
alpha = (1 - delayFrac) / (1 + delayFrac);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,7 @@ namespace FIR
|
||||||
template <typename ProcessContext>
|
template <typename ProcessContext>
|
||||||
void process (const ProcessContext& context) noexcept
|
void process (const ProcessContext& context) noexcept
|
||||||
{
|
{
|
||||||
static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,
|
static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
|
||||||
"The sample-type of the FIR filter must match the sample-type supplied to this process callback");
|
"The sample-type of the FIR filter must match the sample-type supplied to this process callback");
|
||||||
check();
|
check();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ template <typename SampleType>
|
||||||
template <typename ProcessContext, bool bypassed>
|
template <typename ProcessContext, bool bypassed>
|
||||||
void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept
|
void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept
|
||||||
{
|
{
|
||||||
static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,
|
static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
|
||||||
"The sample-type of the IIR filter must match the sample-type supplied to this process callback");
|
"The sample-type of the IIR filter must match the sample-type supplied to this process callback");
|
||||||
check();
|
check();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ namespace detail
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using TupleIndexSequence = std::make_index_sequence<std::tuple_size<std::remove_cv_t<std::remove_reference_t<T>>>::value>;
|
using TupleIndexSequence = std::make_index_sequence<std::tuple_size_v<std::remove_cv_t<std::remove_reference_t<T>>>>;
|
||||||
|
|
||||||
template <typename Fn, typename Tuple>
|
template <typename Fn, typename Tuple>
|
||||||
constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple)
|
constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple)
|
||||||
|
|
@ -99,23 +99,24 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Context, typename Proc, size_t Ix, std::enable_if_t<! detail::useContextDirectly<Context, Ix>, int> = 0>
|
template <typename Context, typename Proc, size_t Ix>
|
||||||
void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept
|
void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept
|
||||||
{
|
{
|
||||||
jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());
|
if constexpr (detail::useContextDirectly<Context, Ix>)
|
||||||
ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());
|
{
|
||||||
replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);
|
auto contextCopy = context;
|
||||||
|
contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);
|
||||||
|
|
||||||
proc.process (replacingContext);
|
proc.process (contextCopy);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());
|
||||||
|
ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());
|
||||||
|
replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);
|
||||||
|
|
||||||
template <typename Context, typename Proc, size_t Ix, std::enable_if_t<detail::useContextDirectly<Context, Ix>, int> = 0>
|
proc.process (replacingContext);
|
||||||
void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept
|
}
|
||||||
{
|
|
||||||
auto contextCopy = context;
|
|
||||||
contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);
|
|
||||||
|
|
||||||
proc.process (contextCopy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Processors...> processors;
|
std::tuple<Processors...> processors;
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ namespace StateVariableFilter
|
||||||
template <typename ProcessContext>
|
template <typename ProcessContext>
|
||||||
void process (const ProcessContext& context) noexcept
|
void process (const ProcessContext& context) noexcept
|
||||||
{
|
{
|
||||||
static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,
|
static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,
|
||||||
"The sample-type of the filter must match the sample-type supplied to this process callback");
|
"The sample-type of the filter must match the sample-type supplied to this process callback");
|
||||||
|
|
||||||
if (context.isBypassed)
|
if (context.isBypassed)
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ private:
|
||||||
class DereferencingIterator
|
class DereferencingIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using value_type = typename std::remove_reference<decltype(**std::declval<Iterator>())>::type;
|
using value_type = std::remove_reference_t<decltype(**std::declval<Iterator>())>;
|
||||||
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
|
using difference_type = typename std::iterator_traits<Iterator>::difference_type;
|
||||||
using pointer = value_type*;
|
using pointer = value_type*;
|
||||||
using reference = value_type&;
|
using reference = value_type&;
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ public:
|
||||||
template <typename OtherType>
|
template <typename OtherType>
|
||||||
constexpr Point operator* (OtherType multiplier) const noexcept
|
constexpr Point operator* (OtherType multiplier) const noexcept
|
||||||
{
|
{
|
||||||
using CommonType = typename std::common_type<ValueType, OtherType>::type;
|
using CommonType = std::common_type_t<ValueType, OtherType>;
|
||||||
return Point ((ValueType) ((CommonType) x * (CommonType) multiplier),
|
return Point ((ValueType) ((CommonType) x * (CommonType) multiplier),
|
||||||
(ValueType) ((CommonType) y * (CommonType) multiplier));
|
(ValueType) ((CommonType) y * (CommonType) multiplier));
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +132,7 @@ public:
|
||||||
template <typename OtherType>
|
template <typename OtherType>
|
||||||
constexpr Point operator/ (OtherType divisor) const noexcept
|
constexpr Point operator/ (OtherType divisor) const noexcept
|
||||||
{
|
{
|
||||||
using CommonType = typename std::common_type<ValueType, OtherType>::type;
|
using CommonType = std::common_type_t<ValueType, OtherType>;
|
||||||
return Point ((ValueType) ((CommonType) x / (CommonType) divisor),
|
return Point ((ValueType) ((CommonType) x / (CommonType) divisor),
|
||||||
(ValueType) ((CommonType) y / (CommonType) divisor));
|
(ValueType) ((CommonType) y / (CommonType) divisor));
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ public:
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** This type will be double if the Point's type is double, otherwise it will be float. */
|
/** This type will be double if the Point's type is double, otherwise it will be float. */
|
||||||
using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type;
|
using FloatType = TypeHelpers::SmallestFloatType<ValueType>;
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
/** Returns the straight-line distance between this point and the origin. */
|
/** Returns the straight-line distance between this point and the origin. */
|
||||||
|
|
|
||||||
|
|
@ -813,7 +813,7 @@ public:
|
||||||
*/
|
*/
|
||||||
Rectangle transformedBy (const AffineTransform& transform) const noexcept
|
Rectangle transformedBy (const AffineTransform& transform) const noexcept
|
||||||
{
|
{
|
||||||
using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type;
|
using FloatType = TypeHelpers::SmallestFloatType<ValueType>;
|
||||||
|
|
||||||
auto x1 = static_cast<FloatType> (pos.x), y1 = static_cast<FloatType> (pos.y);
|
auto x1 = static_cast<FloatType> (pos.x), y1 = static_cast<FloatType> (pos.y);
|
||||||
auto x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y);
|
auto x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y);
|
||||||
|
|
|
||||||
|
|
@ -2811,7 +2811,7 @@ private:
|
||||||
CombineRgn (rgn, rgn, clipRgn, RGN_AND);
|
CombineRgn (rgn, rgn, clipRgn, RGN_AND);
|
||||||
DeleteObject (clipRgn);
|
DeleteObject (clipRgn);
|
||||||
|
|
||||||
std::aligned_storage<8192, alignof (RGNDATA)>::type rgnData;
|
std::aligned_storage_t<8192, alignof (RGNDATA)> rgnData;
|
||||||
const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) &rgnData);
|
const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) &rgnData);
|
||||||
|
|
||||||
if (res > 0 && res <= sizeof (rgnData))
|
if (res > 0 && res <= sizeof (rgnData))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue