| @@ -159,7 +159,7 @@ private: | |||
| template <typename 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)); | |||
| } | |||
| @@ -530,7 +530,7 @@ int main (int argc, char** argv) | |||
| juce::ArgumentList argumentList { arguments.front(), | |||
| 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 | |||
| { | |||
| @@ -1177,7 +1177,7 @@ private: | |||
| jassert (size >= 0); | |||
| 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; | |||
| if (alignmentOverflow != 0) | |||
| @@ -992,7 +992,7 @@ private: | |||
| #if JUCE_WINDOWS && ! JUCE_MINGW | |||
| #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 | |||
| #define JUCE_CHECKED_ITERATOR(msg, size) (msg) | |||
| #endif | |||
| @@ -38,35 +38,35 @@ class Packet | |||
| public: | |||
| 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) | |||
| : contents { { a } } | |||
| { | |||
| 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) | |||
| : contents { { a, b } } | |||
| { | |||
| 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) | |||
| : contents { { a, b, c } } | |||
| { | |||
| 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) | |||
| : contents { { a, b, c, d } } | |||
| { | |||
| 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) | |||
| : contents (fullPacket) | |||
| { | |||
| @@ -229,7 +229,7 @@ public: | |||
| //============================================================================== | |||
| /** Constructor. */ | |||
| 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 | |||
| { | |||
| // 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 | |||
| this->currentValue = initialValue; | |||
| @@ -280,7 +280,7 @@ public: | |||
| } | |||
| // 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->countdown = stepsToTarget; | |||
| @@ -352,49 +352,45 @@ public: | |||
| 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> | |||
| LinearVoid<T> setStepSize() noexcept | |||
| { | |||
| step = (this->target - this->currentValue) / (FloatType) this->countdown; | |||
| } | |||
| template <typename T = SmoothingType> | |||
| MultiplicativeVoid<T> setStepSize() | |||
| void setStepSize() noexcept | |||
| { | |||
| step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown); | |||
| if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>) | |||
| { | |||
| step = (this->target - this->currentValue) / (FloatType) this->countdown; | |||
| } | |||
| 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); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| template <typename T = SmoothingType> | |||
| LinearVoid<T> setNextValue() noexcept | |||
| void setNextValue() noexcept | |||
| { | |||
| this->currentValue += step; | |||
| } | |||
| template <typename T = SmoothingType> | |||
| MultiplicativeVoid<T> setNextValue() noexcept | |||
| { | |||
| this->currentValue *= step; | |||
| if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>) | |||
| { | |||
| this->currentValue += step; | |||
| } | |||
| else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>) | |||
| { | |||
| this->currentValue *= step; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| template <typename T = SmoothingType> | |||
| LinearVoid<T> skipCurrentValue (int numSamples) noexcept | |||
| void skipCurrentValue (int numSamples) noexcept | |||
| { | |||
| this->currentValue += step * (FloatType) numSamples; | |||
| } | |||
| template <typename T = SmoothingType> | |||
| MultiplicativeVoid<T> skipCurrentValue (int numSamples) | |||
| { | |||
| this->currentValue *= (FloatType) std::pow (step, numSamples); | |||
| if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>) | |||
| { | |||
| this->currentValue += step * (FloatType) numSamples; | |||
| } | |||
| else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>) | |||
| { | |||
| this->currentValue *= (FloatType) std::pow (step, numSamples); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -944,9 +944,10 @@ struct WorkSubmitter | |||
| 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_assert (std::is_trivial_v<Trivial>); | |||
| std::array<char, sizeof (Trivial)> result; | |||
| writeUnaligned (result.data(), value); | |||
| return result; | |||
| @@ -956,7 +957,7 @@ template <typename Context> | |||
| class WorkQueue | |||
| { | |||
| 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) | |||
| : fifo (size), data (static_cast<size_t> (size)) {} | |||
| @@ -3657,8 +3658,8 @@ private: | |||
| union Data | |||
| { | |||
| static_assert (std::is_trivial<PortBacking>::value, "PortBacking must be trivial"); | |||
| static_assert (std::is_trivial<PatchBacking>::value, "PatchBacking must be trivial"); | |||
| static_assert (std::is_trivial_v<PortBacking>, "PortBacking must be trivial"); | |||
| static_assert (std::is_trivial_v<PatchBacking>, "PatchBacking must be trivial"); | |||
| explicit Data (PortBacking p) : port (p) {} | |||
| explicit Data (PatchBacking p) : patch (p) {} | |||
| @@ -123,7 +123,7 @@ public: | |||
| template <typename SpecialisationType> | |||
| 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"); | |||
| return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory(); | |||
| } | |||
| @@ -649,7 +649,7 @@ public: | |||
| @see add | |||
| */ | |||
| 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, | |||
| int startIndex, | |||
| int numElementsToAdd = -1) | |||
| @@ -105,9 +105,9 @@ class ArrayBaseTests : public UnitTest | |||
| using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType; | |||
| #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"); | |||
| static_assert (! std::is_trivially_copyable<NoncopyableType>::value, | |||
| static_assert (! std::is_trivially_copyable_v<NoncopyableType>, | |||
| "Test NonTriviallyCopyableType is trivially copyable"); | |||
| #endif | |||
| @@ -43,8 +43,8 @@ private: | |||
| using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type; | |||
| template <class OtherElementType, class OtherCriticalSection> | |||
| using AllowConversion = typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>, | |||
| std::tuple<OtherElementType, OtherCriticalSection>>::value>::type; | |||
| using AllowConversion = std::enable_if_t<! std::is_same_v<std::tuple<ElementType, TypeOfCriticalSectionToUse>, | |||
| std::tuple<OtherElementType, OtherCriticalSection>>>; | |||
| public: | |||
| //============================================================================== | |||
| @@ -304,7 +304,7 @@ public: | |||
| } | |||
| 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, | |||
| int startIndex, int numElementsToAdd = -1) | |||
| { | |||
| @@ -385,64 +385,49 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| template <typename T> | |||
| #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__) | |||
| using IsTriviallyCopyable = std::is_scalar<T>; | |||
| static constexpr auto isTriviallyCopyable = std::is_scalar_v<ElementType>; | |||
| #else | |||
| using IsTriviallyCopyable = std::is_trivially_copyable<T>; | |||
| static constexpr auto isTriviallyCopyable = std::is_trivially_copyable_v<ElementType>; | |||
| #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> | |||
| TriviallyCopyableVoid<T> addArrayInternal (const ElementType* otherElements, int numElements) | |||
| { | |||
| if (numElements > 0) | |||
| 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) | |||
| template <typename Type> | |||
| void addArrayInternal (const Type* otherElements, int numElements) | |||
| { | |||
| auto* start = elements + numUsed; | |||
| if constexpr (isTriviallyCopyable && std::is_same_v<Type, ElementType>) | |||
| { | |||
| if (numElements > 0) | |||
| memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType)); | |||
| } | |||
| else | |||
| { | |||
| auto* start = elements + numUsed; | |||
| while (--numElements >= 0) | |||
| new (start++) ElementType (*(otherElements++)); | |||
| while (--numElements >= 0) | |||
| new (start++) ElementType (*(otherElements++)); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| template <typename T = ElementType> | |||
| TriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements) | |||
| void 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) | |||
| if constexpr (isTriviallyCopyable) | |||
| { | |||
| new (newElements + i) ElementType (std::move (elements[i])); | |||
| elements[i].~ElementType(); | |||
| 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); | |||
| elements = std::move (newElements); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -458,99 +443,99 @@ private: | |||
| return elements + indexToInsertAt; | |||
| } | |||
| template <typename T = ElementType> | |||
| TriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements) | |||
| { | |||
| auto* start = elements + indexToInsertAt; | |||
| auto numElementsToShift = numUsed - indexToInsertAt; | |||
| memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType)); | |||
| } | |||
| template <typename T = ElementType> | |||
| NonTriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements) | |||
| void createInsertSpaceInternal (int indexToInsertAt, int numElements) | |||
| { | |||
| auto* end = elements + numUsed; | |||
| auto* newEnd = end + numElements; | |||
| auto numElementsToShift = numUsed - indexToInsertAt; | |||
| for (int i = 0; i < numElementsToShift; ++i) | |||
| if constexpr (isTriviallyCopyable) | |||
| { | |||
| new (--newEnd) ElementType (std::move (*(--end))); | |||
| end->~ElementType(); | |||
| auto* start = elements + indexToInsertAt; | |||
| auto numElementsToShift = numUsed - indexToInsertAt; | |||
| memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType)); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| template <typename T = ElementType> | |||
| TriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove) | |||
| { | |||
| auto* start = elements + indexToRemoveAt; | |||
| auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove); | |||
| memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType)); | |||
| } | |||
| template <typename T = ElementType> | |||
| NonTriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove) | |||
| { | |||
| auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove); | |||
| auto* destination = elements + indexToRemoveAt; | |||
| auto* source = destination + numElementsToRemove; | |||
| for (int i = 0; i < numElementsToShift; ++i) | |||
| moveAssignElement (destination++, std::move (*(source++))); | |||
| else | |||
| { | |||
| auto* end = elements + numUsed; | |||
| auto* newEnd = end + numElements; | |||
| auto numElementsToShift = numUsed - indexToInsertAt; | |||
| for (int i = 0; i < numElementsToRemove; ++i) | |||
| (destination++)->~ElementType(); | |||
| for (int i = 0; i < numElementsToShift; ++i) | |||
| { | |||
| new (--newEnd) ElementType (std::move (*(--end))); | |||
| end->~ElementType(); | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| template <typename T = ElementType> | |||
| TriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept | |||
| void removeElementsInternal (int indexToRemoveAt, int numElementsToRemove) | |||
| { | |||
| char tempCopy[sizeof (ElementType)]; | |||
| memcpy (tempCopy, elements + currentIndex, sizeof (ElementType)); | |||
| if (newIndex > currentIndex) | |||
| if constexpr (isTriviallyCopyable) | |||
| { | |||
| memmove (elements + currentIndex, | |||
| elements + currentIndex + 1, | |||
| (size_t) (newIndex - currentIndex) * sizeof (ElementType)); | |||
| auto* start = elements + indexToRemoveAt; | |||
| auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove); | |||
| memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType)); | |||
| } | |||
| else | |||
| { | |||
| memmove (elements + newIndex + 1, | |||
| elements + newIndex, | |||
| (size_t) (currentIndex - newIndex) * sizeof (ElementType)); | |||
| } | |||
| auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove); | |||
| auto* destination = elements + indexToRemoveAt; | |||
| auto* source = destination + numElementsToRemove; | |||
| memcpy (elements + newIndex, tempCopy, sizeof (ElementType)); | |||
| for (int i = 0; i < numElementsToShift; ++i) | |||
| moveAssignElement (destination++, std::move (*(source++))); | |||
| for (int i = 0; i < numElementsToRemove; ++i) | |||
| (destination++)->~ElementType(); | |||
| } | |||
| } | |||
| template <typename T = ElementType> | |||
| NonTriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept | |||
| //============================================================================== | |||
| void moveInternal (int currentIndex, int newIndex) noexcept | |||
| { | |||
| auto* e = elements + currentIndex; | |||
| ElementType tempCopy (std::move (*e)); | |||
| auto delta = newIndex - currentIndex; | |||
| if (delta > 0) | |||
| if constexpr (isTriviallyCopyable) | |||
| { | |||
| for (int i = 0; i < delta; ++i) | |||
| char tempCopy[sizeof (ElementType)]; | |||
| memcpy (tempCopy, elements + currentIndex, sizeof (ElementType)); | |||
| if (newIndex > currentIndex) | |||
| { | |||
| moveAssignElement (e, std::move (*(e + 1))); | |||
| ++e; | |||
| 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 | |||
| { | |||
| for (int i = 0; i < -delta; ++i) | |||
| auto* e = elements + currentIndex; | |||
| ElementType tempCopy (std::move (*e)); | |||
| auto delta = newIndex - currentIndex; | |||
| if (delta > 0) | |||
| { | |||
| moveAssignElement (e, std::move (*(e - 1))); | |||
| --e; | |||
| for (int i = 0; i < delta; ++i) | |||
| { | |||
| moveAssignElement (e, std::move (*(e + 1))); | |||
| ++e; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| for (int i = 0; i < -delta; ++i) | |||
| { | |||
| 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> | |||
| typename std::enable_if<std::is_move_assignable<T>::value, void>::type | |||
| moveAssignElement (ElementType* destination, ElementType&& source) | |||
| void moveAssignElement (ElementType* destination, ElementType&& source) | |||
| { | |||
| *destination = std::move (source); | |||
| } | |||
| template <typename T = ElementType> | |||
| typename std::enable_if<! std::is_move_assignable<T>::value, void>::type | |||
| moveAssignElement (ElementType* destination, ElementType&& source) | |||
| { | |||
| destination->~ElementType(); | |||
| new (destination) ElementType (std::move (source)); | |||
| if constexpr (std::is_move_assignable_v<ElementType>) | |||
| { | |||
| *destination = std::move (source); | |||
| } | |||
| else | |||
| { | |||
| destination->~ElementType(); | |||
| new (destination) ElementType (std::move (source)); | |||
| } | |||
| } | |||
| void checkSourceIsNotAMember (const ElementType& element) | |||
| @@ -53,8 +53,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702) | |||
| template <typename Value> | |||
| class Optional | |||
| { | |||
| template <typename> struct IsOptional : std::false_type {}; | |||
| template <typename T> struct IsOptional<Optional<T>> : std::true_type {}; | |||
| template <typename> struct IsOptional : std::false_type {}; | |||
| template <typename T> struct IsOptional<Optional<T>> : std::true_type {}; | |||
| public: | |||
| Optional() = default; | |||
| @@ -654,11 +654,8 @@ namespace TypeHelpers | |||
| @tags{Core} | |||
| */ | |||
| template <typename Type> struct SmallestFloatType { using type = float; }; | |||
| #ifndef DOXYGEN | |||
| template <> struct SmallestFloatType <double> { using type = double; }; | |||
| #endif | |||
| template <typename Type> | |||
| using SmallestFloatType = std::conditional_t<std::is_same_v<Type, double>, double, float>; | |||
| /** These templates are designed to take an integer type, and return an unsigned int | |||
| 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. */ | |||
| 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 | |||
| { | |||
| if (numValues <= 0) | |||
| @@ -87,8 +87,8 @@ class HeapBlock | |||
| { | |||
| private: | |||
| template <class OtherElementType> | |||
| using AllowConversion = typename std::enable_if<std::is_base_of<typename std::remove_pointer<ElementType>::type, | |||
| typename std::remove_pointer<OtherElementType>::type>::value>::type; | |||
| using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>, | |||
| std::remove_pointer_t<OtherElementType>>>; | |||
| public: | |||
| //============================================================================== | |||
| @@ -107,7 +107,7 @@ public: | |||
| If you want an array of zero values, you can use the calloc() method or the | |||
| 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) | |||
| : 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, | |||
| 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) | |||
| : data (static_cast<ElementType*> (initialiseToZero | |||
| ? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType)) | |||
| @@ -152,7 +152,7 @@ public: | |||
| /** Converting move constructor. | |||
| 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>> | |||
| HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept | |||
| @@ -163,7 +163,7 @@ public: | |||
| /** Converting move assignment operator. | |||
| 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>> | |||
| 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 | |||
| 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 | |||
| { | |||
| static_assert (std::is_pointer_v<Type>); | |||
| 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 | |||
| 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 | |||
| { | |||
| static_assert (std::is_pointer_v<Type>); | |||
| return reinterpret_cast<Type> (ptr); | |||
| } | |||
| @@ -30,15 +30,10 @@ namespace detail | |||
| using Void = void; | |||
| template <typename, typename = void> | |||
| struct EqualityComparableToNullptr | |||
| : std::false_type {}; | |||
| constexpr auto equalityComparableToNullptr = false; | |||
| template <typename T> | |||
| struct EqualityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> | |||
| : std::true_type {}; | |||
| template <typename T> | |||
| constexpr bool shouldCheckAgainstNullptr = EqualityComparableToNullptr<T>::value; | |||
| constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true; | |||
| } // namespace detail | |||
| #endif | |||
| @@ -53,23 +48,22 @@ namespace detail | |||
| */ | |||
| struct NullCheckedInvocation | |||
| { | |||
| template <typename Callable, typename... Args, | |||
| std::enable_if_t<detail::shouldCheckAgainstNullptr<Callable>, int> = 0> | |||
| template <typename Callable, typename... Args> | |||
| static void invoke (Callable&& fn, Args&&... args) | |||
| { | |||
| JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress") | |||
| if (fn != nullptr) | |||
| fn (std::forward<Args> (args)...); | |||
| if constexpr (detail::equalityComparableToNullptr<Callable>) | |||
| { | |||
| JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress") | |||
| JUCE_END_IGNORE_WARNINGS_GCC_LIKE | |||
| } | |||
| if (fn != nullptr) | |||
| fn (std::forward<Args> (args)...); | |||
| 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)...); | |||
| JUCE_END_IGNORE_WARNINGS_GCC_LIKE | |||
| } | |||
| else | |||
| { | |||
| fn (std::forward<Args> (args)...); | |||
| } | |||
| } | |||
| template <typename... Args> | |||
| @@ -82,7 +76,7 @@ struct NullCheckedInvocation | |||
| Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/ | |||
| */ | |||
| 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. */ | |||
| template <typename Object, typename OtherObject, typename Member> | |||
| @@ -37,7 +37,7 @@ struct CFObjectDeleter | |||
| }; | |||
| 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> | |||
| struct CFObjectHolder | |||
| @@ -490,8 +490,8 @@ public: | |||
| template <typename ResultType> | |||
| struct HexParser | |||
| { | |||
| static_assert (std::is_unsigned<ResultType>::value, "ResultType must be unsigned because " | |||
| "left-shifting a negative value is UB"); | |||
| static_assert (std::is_unsigned_v<ResultType>, "ResultType must be unsigned because " | |||
| "left-shifting a negative value is UB"); | |||
| template <typename CharPointerType> | |||
| 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 | |||
| // CRITICAL_SECTION structure. | |||
| #if JUCE_64BIT | |||
| std::aligned_storage<44, 8>::type lock; | |||
| std::aligned_storage_t<44, 8> lock; | |||
| #else | |||
| std::aligned_storage<24, 8>::type lock; | |||
| std::aligned_storage_t<24, 8> lock; | |||
| #endif | |||
| #else | |||
| mutable pthread_mutex_t lock; | |||
| @@ -31,7 +31,7 @@ namespace dsp | |||
| #ifndef DOXYGEN | |||
| 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 | |||
| { | |||
| using Type = T; | |||
| @@ -71,10 +71,10 @@ 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, | |||
| std::enable_if_t<std::is_same_v<std::remove_const_t<SampleType>, | |||
| std::remove_const_t<OtherSampleType>> | |||
| && std::is_const_v<SampleType> | |||
| && ! std::is_const_v<OtherSampleType>, | |||
| int>; | |||
| public: | |||
| @@ -337,7 +337,7 @@ public: | |||
| SIMDRegister then incrementing dstPos by one will increase the sample position | |||
| 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 | |||
| { | |||
| auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor; | |||
| @@ -518,7 +518,7 @@ public: | |||
| //============================================================================== | |||
| /** 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) | |||
| return {}; | |||
| @@ -559,11 +559,11 @@ public: | |||
| //============================================================================== | |||
| // This class can only be used with floating point types | |||
| static_assert (std::is_same<std::remove_const_t<SampleType>, float>::value | |||
| || std::is_same<std::remove_const_t<SampleType>, double>::value | |||
| static_assert (std::is_same_v<std::remove_const_t<SampleType>, float> | |||
| || std::is_same_v<std::remove_const_t<SampleType>, double> | |||
| #if JUCE_USE_SIMD | |||
| || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value | |||
| || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value | |||
| || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<float>> | |||
| || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<double>> | |||
| #endif | |||
| , "AudioBlock only supports single or double precision floating point types"); | |||
| @@ -319,118 +319,110 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| template <typename T> | |||
| 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() | |||
| void copyingTests() | |||
| { | |||
| auto unchangedElement1 = block.getSample (0, 4); | |||
| auto unchangedElement2 = block.getSample (1, 1); | |||
| if constexpr (std::is_scalar_v<SampleType>) | |||
| { | |||
| 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 (1, 1), unchangedElement2); | |||
| expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1)); | |||
| expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2)); | |||
| expectEquals (block.getSample (0, 4), unchangedElement1); | |||
| expectEquals (block.getSample (1, 1), unchangedElement2); | |||
| expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1)); | |||
| expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2)); | |||
| resetBlocks(); | |||
| unchangedElement1 = otherBuffer.getSample (0, 4); | |||
| unchangedElement2 = otherBuffer.getSample (1, 3); | |||
| resetBlocks(); | |||
| block.copyTo (otherBuffer, 2, 1, 2); | |||
| unchangedElement1 = otherBuffer.getSample (0, 4); | |||
| unchangedElement2 = otherBuffer.getSample (1, 3); | |||
| expectEquals (otherBuffer.getSample (0, 4), unchangedElement1); | |||
| expectEquals (otherBuffer.getSample (1, 3), unchangedElement2); | |||
| expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2)); | |||
| expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3)); | |||
| } | |||
| block.copyTo (otherBuffer, 2, 1, 2); | |||
| #if JUCE_USE_SIMD | |||
| template <typename T = SampleType> | |||
| SIMDVoid<T> copyingTests() | |||
| { | |||
| auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements; | |||
| AudioBuffer<NumericType> numericData ((int) block.getNumChannels(), | |||
| (int) (block.getNumSamples() * numSIMDElements)); | |||
| expectEquals (otherBuffer.getSample (0, 4), unchangedElement1); | |||
| expectEquals (otherBuffer.getSample (1, 3), unchangedElement2); | |||
| expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2)); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| 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); | |||
| 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)); | |||
| 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); | |||
| numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7); | |||
| auto unchangedSIMDElement1 = block.getSample (0, 1); | |||
| auto unchangedSIMDElement2 = block.getSample (1, 4); | |||
| auto unchangedSIMDElement1 = block.getSample (0, 1); | |||
| auto unchangedSIMDElement2 = block.getSample (1, 4); | |||
| block.copyFrom (numericData, 1, 2, 2); | |||
| 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))); | |||
| 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))); | |||
| 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 | |||
| } | |||
| #endif | |||
| //============================================================================== | |||
| template <typename T = SampleType> | |||
| ScalarVoid<T> smoothedValueTests() | |||
| void 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); | |||
| if constexpr (std::is_scalar_v<SampleType>) | |||
| { | |||
| 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() | |||
| { | |||
| @@ -451,7 +443,7 @@ private: | |||
| //============================================================================== | |||
| static SampleType* allocateAlignedMemory (int numSamplesToAllocate) | |||
| { | |||
| auto alignmentLowerBound = std::alignment_of<SampleType>::value; | |||
| auto alignmentLowerBound = std::alignment_of_v<SampleType>; | |||
| #if ! JUCE_WINDOWS | |||
| alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound); | |||
| #endif | |||
| @@ -56,13 +56,13 @@ namespace detail | |||
| } | |||
| 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...); | |||
| } | |||
| 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)...); | |||
| } | |||
| @@ -102,16 +102,16 @@ template <size_t len, typename Ret, typename... Args> | |||
| class FixedSizeFunction<len, Ret (Args...)> | |||
| { | |||
| private: | |||
| using Storage = typename std::aligned_storage<len>::type; | |||
| using Storage = std::aligned_storage_t<len>; | |||
| template <typename Item> | |||
| using Decay = typename std::decay<Item>::type; | |||
| using Decay = std::decay_t<Item>; | |||
| template <typename Item, typename Fn = Decay<Item>> | |||
| using IntIfValidConversion = typename std::enable_if<sizeof (Fn) <= len | |||
| && alignof (Fn) <= alignof (Storage) | |||
| && ! std::is_same<FixedSizeFunction, Fn>::value, | |||
| int>::type; | |||
| using IntIfValidConversion = std::enable_if_t<sizeof (Fn) <= len | |||
| && alignof (Fn) <= alignof (Storage) | |||
| && ! std::is_same_v<FixedSizeFunction, Fn>, | |||
| int>; | |||
| public: | |||
| /** Create an empty function. */ | |||
| @@ -149,7 +149,7 @@ public: | |||
| } | |||
| /** 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 | |||
| : vtable (other.vtable) | |||
| { | |||
| @@ -172,7 +172,7 @@ public: | |||
| } | |||
| /** 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 | |||
| { | |||
| return *this = FixedSizeFunction (std::move (other)); | |||
| @@ -70,7 +70,7 @@ struct SIMDRegister | |||
| /** The corresponding primitive integer type, for example, this will be int32_t | |||
| 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 | |||
| @@ -30,33 +30,32 @@ namespace dsp | |||
| namespace SIMDRegister_test_internal | |||
| { | |||
| template <typename type, typename = void> struct RandomPrimitive {}; | |||
| template <typename type> | |||
| struct RandomPrimitive<type, typename std::enable_if<std::is_floating_point<type>::value>::type> | |||
| struct RandomPrimitive | |||
| { | |||
| static type next (Random& random) | |||
| { | |||
| return static_cast<type> (std::is_signed<type>::value ? (random.nextFloat() * 16.0) - 8.0 | |||
| : (random.nextFloat() * 8.0)); | |||
| if constexpr (std::is_floating_point_v<type>) | |||
| { | |||
| return static_cast<type> (std::is_signed_v<type> ? (random.nextFloat() * 16.0) - 8.0 | |||
| : (random.nextFloat() * 8.0)); | |||
| } | |||
| else if constexpr (std::is_integral_v<type>) | |||
| { | |||
| return static_cast<type> (random.nextInt64()); | |||
| } | |||
| } | |||
| }; | |||
| template <typename type> | |||
| struct RandomPrimitive<type, typename std::enable_if<std::is_integral<type>::value>::type> | |||
| struct RandomValue | |||
| { | |||
| static type next (Random& random) | |||
| { | |||
| return static_cast<type> (random.nextInt64()); | |||
| return RandomPrimitive<type>::next (random); | |||
| } | |||
| }; | |||
| template <typename type> | |||
| struct RandomValue | |||
| { | |||
| static type next (Random& random) { return RandomPrimitive<type>::next (random); } | |||
| }; | |||
| template <typename type> | |||
| struct RandomValue<std::complex<type>> | |||
| { | |||
| @@ -756,11 +755,10 @@ public: | |||
| template <typename type> | |||
| static void run (UnitTest& u, Random& random, Tag<type>) | |||
| { | |||
| bool is_signed = std::is_signed<type>::value; | |||
| type array [SIMDRegister<type>::SIMDNumElements]; | |||
| auto value = is_signed ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0) | |||
| : static_cast<type> (random.nextFloat() * 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); | |||
| std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value); | |||
| SIMDRegister<type> a, b; | |||
| @@ -184,7 +184,7 @@ public: | |||
| stereo processing. | |||
| */ | |||
| 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 | |||
| { | |||
| 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<double>> { using type = uint64_t; }; | |||
| 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 <typename Primitive> using MaskType = typename MaskTypeFor<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 <> struct Log2Helper<1> { enum { value = 0 }; }; | |||
| @@ -63,7 +65,7 @@ struct SIMDFallbackOps | |||
| static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value; | |||
| // helper types | |||
| using MaskType = typename SIMDInternal::MaskTypeFor<ScalarType>::type; | |||
| using MaskType = SIMDInternal::MaskType<ScalarType>; | |||
| union UnionType { vSIMDType v; ScalarType s[n]; }; | |||
| union UnionMaskType { vSIMDType v; MaskType m[n]; }; | |||
| @@ -201,126 +201,104 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| template <typename T = InterpolationType> | |||
| typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, SampleType>::type | |||
| interpolateSample (int channel) const | |||
| SampleType interpolateSample (int channel) | |||
| { | |||
| auto index = (readPos[(size_t) channel] + delayInt) % totalSize; | |||
| 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) | |||
| if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::None>) | |||
| { | |||
| index1 %= totalSize; | |||
| index2 %= totalSize; | |||
| auto index = (readPos[(size_t) channel] + delayInt) % totalSize; | |||
| return bufferData.getSample (channel, index); | |||
| } | |||
| else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Linear>) | |||
| { | |||
| auto index1 = readPos[(size_t) channel] + delayInt; | |||
| auto index2 = index1 + 1; | |||
| auto value1 = bufferData.getSample (channel, index1); | |||
| auto value2 = bufferData.getSample (channel, index2); | |||
| return value1 + delayFrac * (value2 - value1); | |||
| } | |||
| if (index2 >= totalSize) | |||
| { | |||
| index1 %= totalSize; | |||
| index2 %= totalSize; | |||
| } | |||
| 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; | |||
| auto value1 = bufferData.getSample (channel, index1); | |||
| auto value2 = bufferData.getSample (channel, index2); | |||
| if (index4 >= totalSize) | |||
| { | |||
| index1 %= totalSize; | |||
| index2 %= totalSize; | |||
| index3 %= totalSize; | |||
| index4 %= totalSize; | |||
| return value1 + delayFrac * (value2 - value1); | |||
| } | |||
| else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>) | |||
| { | |||
| auto index1 = readPos[(size_t) channel] + delayInt; | |||
| auto index2 = index1 + 1; | |||
| auto index3 = index2 + 1; | |||
| auto index4 = index3 + 1; | |||
| auto* samples = bufferData.getReadPointer (channel); | |||
| if (index4 >= totalSize) | |||
| { | |||
| index1 %= totalSize; | |||
| index2 %= totalSize; | |||
| index3 %= totalSize; | |||
| index4 %= totalSize; | |||
| } | |||
| auto value1 = samples[index1]; | |||
| auto value2 = samples[index2]; | |||
| auto value3 = samples[index3]; | |||
| auto value4 = samples[index4]; | |||
| auto* samples = bufferData.getReadPointer (channel); | |||
| auto d1 = delayFrac - 1.f; | |||
| auto d2 = delayFrac - 2.f; | |||
| auto d3 = delayFrac - 3.f; | |||
| auto value1 = samples[index1]; | |||
| auto value2 = samples[index2]; | |||
| auto value3 = samples[index3]; | |||
| auto value4 = samples[index4]; | |||
| 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; | |||
| auto d1 = delayFrac - 1.f; | |||
| auto d2 = delayFrac - 2.f; | |||
| auto d3 = delayFrac - 3.f; | |||
| return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4); | |||
| } | |||
| 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; | |||
| 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; | |||
| index2 %= totalSize; | |||
| 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); | |||
| auto value2 = bufferData.getSample (channel, index2); | |||
| auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]); | |||
| v[(size_t) channel] = output; | |||
| return output; | |||
| } | |||
| if (index2 >= totalSize) | |||
| { | |||
| index1 %= totalSize; | |||
| index2 %= totalSize; | |||
| } | |||
| //============================================================================== | |||
| template <typename T = InterpolationType> | |||
| typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, void>::type | |||
| updateInternalVariables() | |||
| { | |||
| } | |||
| auto value1 = bufferData.getSample (channel, index1); | |||
| auto value2 = bufferData.getSample (channel, index2); | |||
| template <typename T = InterpolationType> | |||
| typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, void>::type | |||
| updateInternalVariables() | |||
| { | |||
| } | |||
| auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]); | |||
| v[(size_t) channel] = output; | |||
| template <typename T = InterpolationType> | |||
| typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, void>::type | |||
| updateInternalVariables() | |||
| { | |||
| if (delayInt >= 1) | |||
| { | |||
| delayFrac++; | |||
| delayInt--; | |||
| return output; | |||
| } | |||
| } | |||
| template <typename T = InterpolationType> | |||
| typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, void>::type | |||
| updateInternalVariables() | |||
| //============================================================================== | |||
| void updateInternalVariables() | |||
| { | |||
| if (delayFrac < (SampleType) 0.618 && delayInt >= 1) | |||
| if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>) | |||
| { | |||
| delayFrac++; | |||
| delayInt--; | |||
| if (delayInt >= 1) | |||
| { | |||
| delayFrac++; | |||
| delayInt--; | |||
| } | |||
| } | |||
| else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>) | |||
| { | |||
| if (delayFrac < (SampleType) 0.618 && delayInt >= 1) | |||
| { | |||
| delayFrac++; | |||
| delayInt--; | |||
| } | |||
| alpha = (1 - delayFrac) / (1 + delayFrac); | |||
| alpha = (1 - delayFrac) / (1 + delayFrac); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| @@ -122,7 +122,7 @@ namespace FIR | |||
| template <typename ProcessContext> | |||
| 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"); | |||
| check(); | |||
| @@ -89,7 +89,7 @@ template <typename SampleType> | |||
| template <typename ProcessContext, bool bypassed> | |||
| 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"); | |||
| check(); | |||
| @@ -42,7 +42,7 @@ namespace detail | |||
| } | |||
| 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> | |||
| constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple) | |||
| @@ -99,23 +99,24 @@ public: | |||
| } | |||
| 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 | |||
| { | |||
| jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels()); | |||
| ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock()); | |||
| replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed); | |||
| proc.process (replacingContext); | |||
| } | |||
| template <typename Context, typename Proc, size_t Ix, std::enable_if_t<detail::useContextDirectly<Context, Ix>, int> = 0> | |||
| 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); | |||
| if constexpr (detail::useContextDirectly<Context, Ix>) | |||
| { | |||
| auto contextCopy = context; | |||
| contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed); | |||
| proc.process (contextCopy); | |||
| } | |||
| else | |||
| { | |||
| jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels()); | |||
| ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock()); | |||
| replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed); | |||
| proc.process (replacingContext); | |||
| } | |||
| } | |||
| std::tuple<Processors...> processors; | |||
| @@ -110,7 +110,7 @@ namespace StateVariableFilter | |||
| template <typename ProcessContext> | |||
| 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"); | |||
| if (context.isBypassed) | |||
| @@ -44,7 +44,7 @@ private: | |||
| class DereferencingIterator | |||
| { | |||
| 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 pointer = value_type*; | |||
| using reference = value_type&; | |||
| @@ -123,7 +123,7 @@ public: | |||
| template <typename OtherType> | |||
| 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), | |||
| (ValueType) ((CommonType) y * (CommonType) multiplier)); | |||
| } | |||
| @@ -132,7 +132,7 @@ public: | |||
| template <typename OtherType> | |||
| 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), | |||
| (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. */ | |||
| using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type; | |||
| using FloatType = TypeHelpers::SmallestFloatType<ValueType>; | |||
| //============================================================================== | |||
| /** Returns the straight-line distance between this point and the origin. */ | |||
| @@ -813,7 +813,7 @@ public: | |||
| */ | |||
| 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 x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y); | |||
| @@ -2811,7 +2811,7 @@ private: | |||
| CombineRgn (rgn, rgn, clipRgn, RGN_AND); | |||
| 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); | |||
| if (res > 0 && res <= sizeof (rgnData)) | |||