Browse Source

Replace BigInteger with a bool array in Synthesizer class

tags/v1.9.11
falkTX 6 years ago
parent
commit
8233f9a987
5 changed files with 10 additions and 373 deletions
  1. +0
    -245
      source/modules/water/maths/BigInteger.cpp
  2. +0
    -118
      source/modules/water/maths/BigInteger.h
  3. +9
    -6
      source/modules/water/synthesisers/Synthesiser.cpp
  4. +1
    -2
      source/modules/water/synthesisers/Synthesiser.h
  5. +0
    -2
      source/modules/water/water.cpp

+ 0
- 245
source/modules/water/maths/BigInteger.cpp View File

@@ -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;
}
}

+ 0
- 118
source/modules/water/maths/BigInteger.h View File

@@ -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

+ 9
- 6
source/modules/water/synthesisers/Synthesiser.cpp View File

@@ -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;
}
}


+ 1
- 2
source/modules/water/synthesisers/Synthesiser.h View File

@@ -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)
};


+ 0
- 2
source/modules/water/water.cpp View File

@@ -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"


Loading…
Cancel
Save