@@ -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) | |||
lastPitchWheelValues[i] = 0x2000; | |||
zerostruct(sustainPedalsDown); | |||
} | |||
Synthesiser::~Synthesiser() | |||
@@ -303,6 +305,8 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice, | |||
{ | |||
if (voice != nullptr && sound != nullptr) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,); | |||
if (voice->currentlyPlayingSound != nullptr) | |||
voice->stopNote (0.0f, false); | |||
@@ -334,6 +338,7 @@ void Synthesiser::noteOff (const int midiChannel, | |||
const float velocity, | |||
const bool allowTailOff) | |||
{ | |||
CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,); | |||
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) | |||
{ | |||
for (int i = voices.size(); --i >= 0;) | |||
{ | |||
SynthesiserVoice* const voice = voices.getUnchecked (i); | |||
@@ -370,12 +374,11 @@ void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff) | |||
voice->stopNote (1.0f, allowTailOff); | |||
} | |||
sustainPedalsDown.clear(); | |||
zerostruct(sustainPedalsDown); | |||
} | |||
void Synthesiser::handlePitchWheel (const int midiChannel, const int wheelValue) | |||
{ | |||
for (int i = voices.size(); --i >= 0;) | |||
{ | |||
SynthesiserVoice* const voice = voices.getUnchecked (i); | |||
@@ -434,11 +437,11 @@ void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureVal | |||
void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) | |||
{ | |||
jassert (midiChannel > 0 && midiChannel <= 16); | |||
CARLA_SAFE_ASSERT_RETURN(midiChannel > 0 && midiChannel <= 16,); | |||
if (isDown) | |||
{ | |||
sustainPedalsDown.setBit (midiChannel); | |||
sustainPedalsDown[midiChannel] = true; | |||
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 "../containers/OwnedArray.h" | |||
#include "../containers/ReferenceCountedArray.h" | |||
#include "../maths/BigInteger.h" | |||
#include "CarlaJuceUtils.hpp" | |||
#include "CarlaMutex.hpp" | |||
@@ -613,7 +612,7 @@ private: | |||
int minimumSubBlockSize; | |||
bool subBlockSubdivisionIsStrict; | |||
bool shouldStealNotes; | |||
BigInteger sustainPedalsDown; | |||
bool sustainPedalsDown[17]; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser) | |||
}; | |||
@@ -45,8 +45,6 @@ HINSTANCE water_getCurrentModuleInstanceHandle() noexcept | |||
#include "files/FileOutputStream.cpp" | |||
#include "files/TemporaryFile.cpp" | |||
#include "maths/BigInteger.cpp" | |||
#include "maths/Random.cpp" | |||
#include "memory/MemoryBlock.cpp" | |||