@@ -1,245 +0,0 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the JUCE library. | |||||
Copyright (c) 2016 ROLI Ltd. | |||||
Copyright (C) 2018 Filipe Coelho <falktx@falktx.com> | |||||
Permission is granted to use this software under the terms of the ISC license | |||||
http://www.isc.org/downloads/software-support-policy/isc-license/ | |||||
Permission to use, copy, modify, and/or distribute this software for any | |||||
purpose with or without fee is hereby granted, provided that the above | |||||
copyright notice and this permission notice appear in all copies. | |||||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||||
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||||
OF THIS SOFTWARE. | |||||
============================================================================== | |||||
*/ | |||||
#include "BigInteger.h" | |||||
namespace water | |||||
{ | |||||
inline uint32 bitToMask (const int bit) noexcept { return (uint32) 1 << (bit & 31); } | |||||
inline size_t bitToIndex (const int bit) noexcept { return (size_t) (bit >> 5); } | |||||
inline size_t sizeNeededToHold (int highestBit) noexcept { return (size_t) (highestBit >> 5) + 1; } | |||||
int findHighestSetBit (uint32 n) noexcept | |||||
{ | |||||
jassert (n != 0); // (the built-in functions may not work for n = 0) | |||||
#if defined(__GNUC__) || defined(__clang__) | |||||
return 31 - __builtin_clz (n); | |||||
#elif _MSVC_VER | |||||
unsigned long highest; | |||||
_BitScanReverse (&highest, n); | |||||
return (int) highest; | |||||
#else | |||||
n |= (n >> 1); | |||||
n |= (n >> 2); | |||||
n |= (n >> 4); | |||||
n |= (n >> 8); | |||||
n |= (n >> 16); | |||||
return countNumberOfBits (n >> 1); | |||||
#endif | |||||
} | |||||
//============================================================================== | |||||
BigInteger::BigInteger() noexcept | |||||
: allocatedSize (numPreallocatedInts), | |||||
highestBit (-1) | |||||
{ | |||||
for (int i = 0; i < numPreallocatedInts; ++i) | |||||
preallocated[i] = 0; | |||||
} | |||||
BigInteger::BigInteger (const int32 value) noexcept | |||||
: allocatedSize (numPreallocatedInts), | |||||
highestBit (31) | |||||
{ | |||||
preallocated[0] = (uint32) std::abs (value); | |||||
for (int i = 1; i < numPreallocatedInts; ++i) | |||||
preallocated[i] = 0; | |||||
highestBit = getHighestBit(); | |||||
} | |||||
BigInteger::BigInteger (const uint32 value) noexcept | |||||
: allocatedSize (numPreallocatedInts), | |||||
highestBit (31) | |||||
{ | |||||
preallocated[0] = value; | |||||
for (int i = 1; i < numPreallocatedInts; ++i) | |||||
preallocated[i] = 0; | |||||
highestBit = getHighestBit(); | |||||
} | |||||
BigInteger::BigInteger (int64 value) noexcept | |||||
: allocatedSize (numPreallocatedInts), | |||||
highestBit (63) | |||||
{ | |||||
if (value < 0) | |||||
value = -value; | |||||
preallocated[0] = (uint32) value; | |||||
preallocated[1] = (uint32) (value >> 32); | |||||
for (int i = 2; i < numPreallocatedInts; ++i) | |||||
preallocated[i] = 0; | |||||
highestBit = getHighestBit(); | |||||
} | |||||
#if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS | |||||
BigInteger::BigInteger (BigInteger&& other) noexcept | |||||
: heapAllocation (static_cast<HeapBlock<uint32>&&> (other.heapAllocation)), | |||||
allocatedSize (other.allocatedSize), | |||||
highestBit (other.highestBit) | |||||
{ | |||||
std::memcpy (preallocated, other.preallocated, sizeof (preallocated)); | |||||
} | |||||
BigInteger& BigInteger::operator= (BigInteger&& other) noexcept | |||||
{ | |||||
heapAllocation = static_cast<HeapBlock<uint32>&&> (other.heapAllocation); | |||||
std::memcpy (preallocated, other.preallocated, sizeof (preallocated)); | |||||
allocatedSize = other.allocatedSize; | |||||
highestBit = other.highestBit; | |||||
return *this; | |||||
} | |||||
#endif | |||||
BigInteger::~BigInteger() noexcept | |||||
{ | |||||
} | |||||
uint32* BigInteger::getValues() const noexcept | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(heapAllocation != nullptr || allocatedSize <= numPreallocatedInts, nullptr); | |||||
return heapAllocation != nullptr ? heapAllocation | |||||
: (uint32*) preallocated; | |||||
} | |||||
uint32* BigInteger::ensureSize (const size_t numVals) noexcept | |||||
{ | |||||
if (numVals <= allocatedSize) | |||||
return getValues(); | |||||
size_t oldSize = allocatedSize; | |||||
allocatedSize = ((numVals + 2) * 3) / 2; | |||||
if (heapAllocation == nullptr) | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(heapAllocation.calloc (allocatedSize), nullptr); | |||||
std::memcpy (heapAllocation, preallocated, sizeof (uint32) * numPreallocatedInts); | |||||
} | |||||
else | |||||
{ | |||||
CARLA_SAFE_ASSERT_RETURN(heapAllocation.realloc (allocatedSize), nullptr); | |||||
for (uint32* values = heapAllocation; oldSize < allocatedSize; ++oldSize) | |||||
values[oldSize] = 0; | |||||
} | |||||
return heapAllocation; | |||||
} | |||||
//============================================================================== | |||||
bool BigInteger::operator[] (const int bit) const noexcept | |||||
{ | |||||
if (bit < 0 || bit > highestBit) | |||||
return false; | |||||
if (const uint32* const values = getValues()) | |||||
return (values [bitToIndex (bit)] & bitToMask (bit)) != 0; | |||||
return false; | |||||
} | |||||
//============================================================================== | |||||
void BigInteger::clear() noexcept | |||||
{ | |||||
heapAllocation.free(); | |||||
allocatedSize = numPreallocatedInts; | |||||
highestBit = -1; | |||||
for (int i = 0; i < numPreallocatedInts; ++i) | |||||
preallocated[i] = 0; | |||||
} | |||||
bool BigInteger::setBit (const int bit) noexcept | |||||
{ | |||||
if (bit < 0) | |||||
return false; | |||||
CARLA_SAFE_ASSERT_RETURN(bit >= 0, false); | |||||
if (bit > highestBit) | |||||
{ | |||||
if (ensureSize (sizeNeededToHold (bit)) == nullptr) | |||||
return false; | |||||
highestBit = bit; | |||||
} | |||||
if (uint32* const values = getValues()) | |||||
return values [bitToIndex (bit)] |= bitToMask (bit); | |||||
return false; | |||||
} | |||||
bool BigInteger::setBit (const int bit, const bool shouldBeSet) noexcept | |||||
{ | |||||
if (shouldBeSet) | |||||
{ | |||||
return setBit (bit); | |||||
} | |||||
else | |||||
{ | |||||
clearBit (bit); | |||||
return true; | |||||
} | |||||
} | |||||
bool BigInteger::clearBit (const int bit) noexcept | |||||
{ | |||||
if (bit < 0 || bit > highestBit) | |||||
return false; | |||||
uint32* const values = getValues(); | |||||
CARLA_SAFE_ASSERT_RETURN(values != nullptr, false); | |||||
values [bitToIndex (bit)] &= ~bitToMask (bit); | |||||
if (bit == highestBit) | |||||
highestBit = getHighestBit(); | |||||
return true; | |||||
} | |||||
int BigInteger::getHighestBit() const noexcept | |||||
{ | |||||
const uint32* values = getValues(); | |||||
CARLA_SAFE_ASSERT_RETURN(values != nullptr, -1); | |||||
for (int i = (int) bitToIndex (highestBit); i >= 0; --i) | |||||
if (uint32 n = values[i]) | |||||
return findHighestSetBit (n) + (i << 5); | |||||
return -1; | |||||
} | |||||
} |
@@ -1,118 +0,0 @@ | |||||
/* | |||||
============================================================================== | |||||
This file is part of the Water library. | |||||
Copyright (c) 2016 ROLI Ltd. | |||||
Copyright (C) 2018 Filipe Coelho <falktx@falktx.com> | |||||
Permission is granted to use this software under the terms of the ISC license | |||||
http://www.isc.org/downloads/software-support-policy/isc-license/ | |||||
Permission to use, copy, modify, and/or distribute this software for any | |||||
purpose with or without fee is hereby granted, provided that the above | |||||
copyright notice and this permission notice appear in all copies. | |||||
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||||
FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||||
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||||
USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||||
OF THIS SOFTWARE. | |||||
============================================================================== | |||||
*/ | |||||
#ifndef WATER_BIGINTEGER_H_INCLUDED | |||||
#define WATER_BIGINTEGER_H_INCLUDED | |||||
#include "../memory/HeapBlock.h" | |||||
#include "CarlaJuceUtils.hpp" | |||||
namespace water { | |||||
//============================================================================== | |||||
/** | |||||
An arbitrarily large integer class. | |||||
A BigInteger can be used in a similar way to a normal integer, but has no size | |||||
limit (except for memory and performance constraints). | |||||
Negative values are possible, but the value isn't stored as 2s-complement, so | |||||
be careful if you use negative values and look at the values of individual bits. | |||||
*/ | |||||
class BigInteger | |||||
{ | |||||
public: | |||||
//============================================================================== | |||||
/** Creates an empty BigInteger */ | |||||
BigInteger() noexcept; | |||||
/** Creates a BigInteger containing an integer value in its low bits. | |||||
The low 32 bits of the number are initialised with this value. | |||||
*/ | |||||
BigInteger (uint32 value) noexcept; | |||||
/** Creates a BigInteger containing an integer value in its low bits. | |||||
The low 32 bits of the number are initialised with the absolute value | |||||
passed in, and its sign is set to reflect the sign of the number. | |||||
*/ | |||||
BigInteger (int32 value) noexcept; | |||||
/** Creates a BigInteger containing an integer value in its low bits. | |||||
The low 64 bits of the number are initialised with the absolute value | |||||
passed in, and its sign is set to reflect the sign of the number. | |||||
*/ | |||||
BigInteger (int64 value) noexcept; | |||||
#if WATER_COMPILER_SUPPORTS_MOVE_SEMANTICS | |||||
BigInteger (BigInteger&&) noexcept; | |||||
BigInteger& operator= (BigInteger&&) noexcept; | |||||
#endif | |||||
/** Destructor. */ | |||||
~BigInteger() noexcept; | |||||
//============================================================================== | |||||
/** Returns the value of a specified bit in the number. | |||||
If the index is out-of-range, the result will be false. | |||||
*/ | |||||
bool operator[] (int bit) const noexcept; | |||||
//============================================================================== | |||||
/** Resets the value to 0. */ | |||||
void clear() noexcept; | |||||
/** Clears a particular bit in the number. */ | |||||
bool clearBit (int bitNumber) noexcept; | |||||
/** Sets a specified bit to 1. */ | |||||
bool setBit (int bitNumber) noexcept; | |||||
/** Sets or clears a specified bit. */ | |||||
bool setBit (int bitNumber, bool shouldBeSet) noexcept; | |||||
//============================================================================== | |||||
/** Returns the index of the highest set bit in the number. | |||||
If the value is zero, this will return -1. | |||||
*/ | |||||
int getHighestBit() const noexcept; | |||||
private: | |||||
//============================================================================== | |||||
enum { numPreallocatedInts = 4 }; | |||||
HeapBlock<uint32> heapAllocation; | |||||
uint32 preallocated[numPreallocatedInts]; | |||||
size_t allocatedSize; | |||||
int highestBit; | |||||
uint32* getValues() const noexcept; | |||||
uint32* ensureSize (size_t) noexcept; | |||||
CARLA_LEAK_DETECTOR (BigInteger) | |||||
}; | |||||
} | |||||
#endif // WATER_BIGINTEGER_H_INCLUDED |
@@ -92,6 +92,8 @@ Synthesiser::Synthesiser() | |||||
{ | { | ||||
for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i) | for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i) | ||||
lastPitchWheelValues[i] = 0x2000; | lastPitchWheelValues[i] = 0x2000; | ||||
zerostruct(sustainPedalsDown); | |||||
} | } | ||||
Synthesiser::~Synthesiser() | Synthesiser::~Synthesiser() | ||||
@@ -303,6 +305,8 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice, | |||||
{ | { | ||||
if (voice != nullptr && sound != nullptr) | if (voice != nullptr && sound != nullptr) | ||||
{ | { | ||||
CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,); | |||||
if (voice->currentlyPlayingSound != nullptr) | if (voice->currentlyPlayingSound != nullptr) | ||||
voice->stopNote (0.0f, false); | voice->stopNote (0.0f, false); | ||||
@@ -334,6 +338,7 @@ void Synthesiser::noteOff (const int midiChannel, | |||||
const float velocity, | const float velocity, | ||||
const bool allowTailOff) | const bool allowTailOff) | ||||
{ | { | ||||
CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,); | |||||
for (int i = voices.size(); --i >= 0;) | for (int i = voices.size(); --i >= 0;) | ||||
{ | { | ||||
@@ -361,7 +366,6 @@ void Synthesiser::noteOff (const int midiChannel, | |||||
void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff) | void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff) | ||||
{ | { | ||||
for (int i = voices.size(); --i >= 0;) | for (int i = voices.size(); --i >= 0;) | ||||
{ | { | ||||
SynthesiserVoice* const voice = voices.getUnchecked (i); | SynthesiserVoice* const voice = voices.getUnchecked (i); | ||||
@@ -370,12 +374,11 @@ void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff) | |||||
voice->stopNote (1.0f, allowTailOff); | voice->stopNote (1.0f, allowTailOff); | ||||
} | } | ||||
sustainPedalsDown.clear(); | |||||
zerostruct(sustainPedalsDown); | |||||
} | } | ||||
void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue) | void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue) | ||||
{ | { | ||||
for (int i = voices.size(); --i >= 0;) | for (int i = voices.size(); --i >= 0;) | ||||
{ | { | ||||
SynthesiserVoice* const voice = voices.getUnchecked (i); | SynthesiserVoice* const voice = voices.getUnchecked (i); | ||||
@@ -434,11 +437,11 @@ void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureVal | |||||
void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) | void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) | ||||
{ | { | ||||
jassert (midiChannel > 0 && midiChannel <= 16); | |||||
CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,); | |||||
if (isDown) | if (isDown) | ||||
{ | { | ||||
sustainPedalsDown.setBit (midiChannel); | |||||
sustainPedalsDown[midiChannel] = true; | |||||
for (int i = voices.size(); --i >= 0;) | for (int i = voices.size(); --i >= 0;) | ||||
{ | { | ||||
@@ -463,7 +466,7 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) | |||||
} | } | ||||
} | } | ||||
sustainPedalsDown.clearBit (midiChannel); | |||||
sustainPedalsDown[midiChannel] = false; | |||||
} | } | ||||
} | } | ||||
@@ -29,7 +29,6 @@ | |||||
#include "../buffers/AudioSampleBuffer.h" | #include "../buffers/AudioSampleBuffer.h" | ||||
#include "../containers/OwnedArray.h" | #include "../containers/OwnedArray.h" | ||||
#include "../containers/ReferenceCountedArray.h" | #include "../containers/ReferenceCountedArray.h" | ||||
#include "../maths/BigInteger.h" | |||||
#include "CarlaJuceUtils.hpp" | #include "CarlaJuceUtils.hpp" | ||||
#include "CarlaMutex.hpp" | #include "CarlaMutex.hpp" | ||||
@@ -613,7 +612,7 @@ private: | |||||
int minimumSubBlockSize; | int minimumSubBlockSize; | ||||
bool subBlockSubdivisionIsStrict; | bool subBlockSubdivisionIsStrict; | ||||
bool shouldStealNotes; | bool shouldStealNotes; | ||||
BigInteger sustainPedalsDown; | |||||
bool sustainPedalsDown[17]; | |||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser) | ||||
}; | }; | ||||
@@ -45,8 +45,6 @@ HINSTANCE water_getCurrentModuleInstanceHandle() noexcept | |||||
#include "files/FileOutputStream.cpp" | #include "files/FileOutputStream.cpp" | ||||
#include "files/TemporaryFile.cpp" | #include "files/TemporaryFile.cpp" | ||||
#include "maths/BigInteger.cpp" | |||||
#include "maths/Random.cpp" | #include "maths/Random.cpp" | ||||
#include "memory/MemoryBlock.cpp" | #include "memory/MemoryBlock.cpp" | ||||