- Library code update

- project update (added Eigen)

git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@94 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
2014-12-20 20:59:48 +00:00
parent 1b4d8e9f54
commit dc5560392f
312 changed files with 6349 additions and 4195 deletions
@@ -25,7 +25,7 @@
void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fff;
char* intData = static_cast <char*> (dest);
char* intData = static_cast<char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
@@ -50,7 +50,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest
void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fff;
char* intData = static_cast <char*> (dest);
char* intData = static_cast<char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
@@ -75,7 +75,7 @@ void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest
void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffff;
char* intData = static_cast <char*> (dest);
char* intData = static_cast<char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
@@ -100,7 +100,7 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest
void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffff;
char* intData = static_cast <char*> (dest);
char* intData = static_cast<char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
@@ -125,7 +125,7 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest
void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffffff;
char* intData = static_cast <char*> (dest);
char* intData = static_cast<char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
@@ -150,7 +150,7 @@ void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest
void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample)
{
const double maxVal = (double) 0x7fffffff;
char* intData = static_cast <char*> (dest);
char* intData = static_cast<char*> (dest);
if (dest != (void*) source || destBytesPerSample <= 4)
{
@@ -176,7 +176,7 @@ void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* de
{
jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
char* d = static_cast <char*> (dest);
char* d = static_cast<char*> (dest);
for (int i = 0; i < numSamples; ++i)
{
@@ -194,7 +194,7 @@ void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* de
{
jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data!
char* d = static_cast <char*> (dest);
char* d = static_cast<char*> (dest);
for (int i = 0; i < numSamples; ++i)
{
@@ -212,7 +212,7 @@ void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* de
void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fff;
const char* intData = static_cast <const char*> (source);
const char* intData = static_cast<const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
@@ -237,7 +237,7 @@ void AudioDataConverters::convertInt16LEToFloat (const void* const source, float
void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fff;
const char* intData = static_cast <const char*> (source);
const char* intData = static_cast<const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
@@ -262,7 +262,7 @@ void AudioDataConverters::convertInt16BEToFloat (const void* const source, float
void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffff;
const char* intData = static_cast <const char*> (source);
const char* intData = static_cast<const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
@@ -287,7 +287,7 @@ void AudioDataConverters::convertInt24LEToFloat (const void* const source, float
void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffff;
const char* intData = static_cast <const char*> (source);
const char* intData = static_cast<const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
@@ -312,7 +312,7 @@ void AudioDataConverters::convertInt24BEToFloat (const void* const source, float
void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffffff;
const char* intData = static_cast <const char*> (source);
const char* intData = static_cast<const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
@@ -337,7 +337,7 @@ void AudioDataConverters::convertInt32LEToFloat (const void* const source, float
void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const float scale = 1.0f / 0x7fffffff;
const char* intData = static_cast <const char*> (source);
const char* intData = static_cast<const char*> (source);
if (source != (void*) dest || srcBytesPerSample >= 4)
{
@@ -361,7 +361,7 @@ void AudioDataConverters::convertInt32BEToFloat (const void* const source, float
void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const char* s = static_cast <const char*> (source);
const char* s = static_cast<const char*> (source);
for (int i = 0; i < numSamples; ++i)
{
@@ -378,7 +378,7 @@ void AudioDataConverters::convertFloat32LEToFloat (const void* const source, flo
void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample)
{
const char* s = static_cast <const char*> (source);
const char* s = static_cast<const char*> (source);
for (int i = 0; i < numSamples; ++i)
{
@@ -91,7 +91,7 @@ AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
allocatedBytes (0)
{
jassert (dataToReferTo != nullptr);
jassert (numChans >= 0);
jassert (numChans >= 0 && numSamples >= 0);
allocateChannels (dataToReferTo, 0);
}
@@ -105,7 +105,7 @@ AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo,
isClear (false)
{
jassert (dataToReferTo != nullptr);
jassert (numChans >= 0);
jassert (numChans >= 0 && startSample >= 0 && numSamples >= 0);
allocateChannels (dataToReferTo, startSample);
}
@@ -114,7 +114,7 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
const int newNumSamples) noexcept
{
jassert (dataToReferTo != nullptr);
jassert (newNumChannels >= 0);
jassert (newNumChannels >= 0 && newNumSamples >= 0);
allocatedBytes = 0;
allocatedData.free();
@@ -128,6 +128,8 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo,
void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset)
{
jassert (offset >= 0);
// (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools)
if (numChannels < (int) numElementsInArray (preallocatedChannelSpace))
{
@@ -163,6 +165,8 @@ AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other)
}
else
{
isClear = false;
for (int i = 0; i < numChannels; ++i)
FloatVectorOperations::copy (channels[i], other.channels[i], size);
}
@@ -24,8 +24,9 @@
namespace FloatVectorHelpers
{
#define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
#define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
#define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest));
#define JUCE_INCREMENT_SRC1_SRC2_DEST dest += (16 / sizeof (*dest)); src1 += (16 / sizeof (*dest)); src2 += (16 / sizeof (*dest));
#define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest));
#if JUCE_USE_SSE_INTRINSICS
static bool sse2Present = false;
@@ -122,6 +123,17 @@ namespace FloatVectorHelpers
} \
JUCE_FINISH_VEC_OP (normalOp)
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
JUCE_BEGIN_VEC_OP \
setupOp \
{ \
Mode::ParallelType (&loadSrc1) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src1) ? Mode::loadA : Mode::loadU; \
Mode::ParallelType (&loadSrc2) (const Mode::Type* v) = FloatVectorHelpers::isAligned (src2) ? Mode::loadA : Mode::loadU; \
void (&storeDst) (Mode::Type* dest, Mode::ParallelType a) = FloatVectorHelpers::isAligned (dest) ? Mode::storeA : Mode::storeU; \
JUCE_VEC_LOOP_TWO_SOURCES (vecOp, loadSrc1, loadSrc2, storeDst, locals, increment); \
} \
JUCE_FINISH_VEC_OP (normalOp)
//==============================================================================
#elif JUCE_USE_ARM_NEON
@@ -193,6 +205,12 @@ namespace FloatVectorHelpers
JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
JUCE_FINISH_VEC_OP (normalOp)
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
JUCE_BEGIN_VEC_OP \
setupOp \
JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
JUCE_FINISH_VEC_OP (normalOp)
//==============================================================================
#else
#define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
@@ -201,6 +219,8 @@ namespace FloatVectorHelpers
#define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \
for (int i = 0; i < num; ++i) normalOp;
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
for (int i = 0; i < num; ++i) normalOp;
#endif
//==============================================================================
@@ -212,10 +232,19 @@ namespace FloatVectorHelpers
increment; \
}
#define JUCE_VEC_LOOP_TWO_SOURCES(vecOp, src1Load, src2Load, dstStore, locals, increment) \
for (int i = 0; i < numLongOps; ++i) \
{ \
locals (src1Load, src2Load); \
dstStore (dest, vecOp); \
increment; \
}
#define JUCE_LOAD_NONE(srcLoad, dstLoad)
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
#define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest);
#define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src);
#define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load) const Mode::ParallelType s1 = src1Load (src1), s2 = src2Load (src2);
#define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src);
#if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
template<int typeSize> struct ModeType { typedef BasicOps32 Mode; };
@@ -229,7 +258,7 @@ namespace FloatVectorHelpers
static Type findMinOrMax (const Type* src, int num, const bool isMinimum) noexcept
{
const int numLongOps = num / Mode::numParallel;
int numLongOps = num / Mode::numParallel;
#if JUCE_USE_SSE_INTRINSICS
if (numLongOps > 1 && isSSE2Available())
@@ -246,7 +275,7 @@ namespace FloatVectorHelpers
if (isMinimum)
{
for (int i = 1; i < numLongOps; ++i)
while (--numLongOps > 0)
{
src += Mode::numParallel;
val = Mode::min (val, Mode::loadA (src));
@@ -254,7 +283,7 @@ namespace FloatVectorHelpers
}
else
{
for (int i = 1; i < numLongOps; ++i)
while (--numLongOps > 0)
{
src += Mode::numParallel;
val = Mode::max (val, Mode::loadA (src));
@@ -268,7 +297,7 @@ namespace FloatVectorHelpers
if (isMinimum)
{
for (int i = 1; i < numLongOps; ++i)
while (--numLongOps > 0)
{
src += Mode::numParallel;
val = Mode::min (val, Mode::loadU (src));
@@ -276,7 +305,7 @@ namespace FloatVectorHelpers
}
else
{
for (int i = 1; i < numLongOps; ++i)
while (--numLongOps > 0)
{
src += Mode::numParallel;
val = Mode::max (val, Mode::loadU (src));
@@ -288,6 +317,7 @@ namespace FloatVectorHelpers
: Mode::max (val);
num &= (Mode::numParallel - 1);
src += Mode::numParallel;
for (int i = 0; i < num; ++i)
result = isMinimum ? jmin (result, src[i])
@@ -302,7 +332,7 @@ namespace FloatVectorHelpers
static Range<Type> findMinAndMax (const Type* src, int num) noexcept
{
const int numLongOps = num / Mode::numParallel;
int numLongOps = num / Mode::numParallel;
#if JUCE_USE_SSE_INTRINSICS
if (numLongOps > 1 && isSSE2Available())
@@ -318,7 +348,7 @@ namespace FloatVectorHelpers
mn = Mode::loadA (src);
mx = mn;
for (int i = 1; i < numLongOps; ++i)
while (--numLongOps > 0)
{
src += Mode::numParallel;
const ParallelType v = Mode::loadA (src);
@@ -332,7 +362,7 @@ namespace FloatVectorHelpers
mn = Mode::loadU (src);
mx = mn;
for (int i = 1; i < numLongOps; ++i)
while (--numLongOps > 0)
{
src += Mode::numParallel;
const ParallelType v = Mode::loadU (src);
@@ -344,7 +374,9 @@ namespace FloatVectorHelpers
Range<Type> result (Mode::min (mn),
Mode::max (mx));
num &= 3;
num &= (Mode::numParallel - 1);
src += Mode::numParallel;
for (int i = 0; i < num; ++i)
result = result.getUnionWith (src[i]);
@@ -409,7 +441,7 @@ void JUCE_CALLTYPE FloatVectorOperations::copy (double* dest, const double* src,
void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmul (src, 1, &multiplier, dest, 1, num);
vDSP_vsmul (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
@@ -420,7 +452,7 @@ void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const f
void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (double* dest, const double* src, double multiplier, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmulD (src, 1, &multiplier, dest, 1, num);
vDSP_vsmulD (src, 1, &multiplier, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
@@ -440,10 +472,32 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int
const Mode::ParallelType amountToAdd = Mode::load1 (amount);)
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float* src, float amount, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType am = Mode::load1 (amount);)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double* src, double amount, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType am = Mode::load1 (amount);)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vadd (src, 1, dest, 1, dest, 1, num);
vDSP_vadd (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
#endif
@@ -452,16 +506,34 @@ void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, in
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vaddD (src, 1, dest, 1, dest, 1, num);
vDSP_vaddD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vadd (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vaddD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsub (src, 1, dest, 1, dest, 1, num);
vDSP_vsub (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
#endif
@@ -470,12 +542,30 @@ void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* sr
void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsubD (src, 1, dest, 1, dest, 1, num);
vDSP_vsubD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsub (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsubD (src2, 1, src1, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier, Mode::add (d, Mode::mul (mult, s)),
@@ -493,7 +583,7 @@ void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const d
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmul (src, 1, dest, 1, dest, 1, num);
vDSP_vmul (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
#endif
@@ -502,16 +592,34 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* sr
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmulD (src, 1, dest, 1, dest, 1, num);
vDSP_vmulD (src, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmul (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmulD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmul (dest, 1, &multiplier, dest, 1, num);
vDSP_vsmul (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST,
const Mode::ParallelType mult = Mode::load1 (multiplier);)
@@ -521,13 +629,27 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplie
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, double multiplier, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vsmulD (dest, 1, &multiplier, dest, 1, num);
vDSP_vsmulD (dest, 1, &multiplier, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST,
const Mode::ParallelType mult = Mode::load1 (multiplier);)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, float multiplier, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType mult = Mode::load1 (multiplier);)
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, double multiplier, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType mult = Mode::load1 (multiplier);)
}
void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
@@ -640,8 +762,8 @@ public:
const int range = random.nextBool() ? 500 : 10;
const int num = random.nextInt (range) + 1;
HeapBlock<ValueType> buffer1 (num + 16), buffer2 (num + 16);
HeapBlock<int> buffer3 (num + 16);
HeapBlock<ValueType> buffer1 ((size_t) num + 16), buffer2 ((size_t) num + 16);
HeapBlock<int> buffer3 ((size_t) num + 16);
#if JUCE_ARM
ValueType* const data1 = buffer1;
@@ -65,18 +65,36 @@ public:
/** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (double* dest, double amountToAdd, int numValues) noexcept;
/** Adds a fixed value to each source value and stores it in the destination array. */
static void JUCE_CALLTYPE add (float* dest, float* src, float amount, int numValues) noexcept;
/** Adds a fixed value to each source value and stores it in the destination array. */
static void JUCE_CALLTYPE add (double* dest, double* src, double amount, int numValues) noexcept;
/** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept;
/** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (double* dest, const double* src, int numValues) noexcept;
/** Adds each source1 value to the corresponding source2 value and stores the result in the destination array. */
static void JUCE_CALLTYPE add (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Adds each source1 value to the corresponding source2 value and stores the result in the destination array. */
static void JUCE_CALLTYPE add (double* dest, const double* src1, const double* src2, int num) noexcept;
/** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept;
/** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (double* dest, const double* src, int numValues) noexcept;
/** Subtracts each source2 value from the corresponding source1 value and stores the result in the destination array. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Subtracts each source2 value from the corresponding source1 value and stores the result in the destination array. */
static void JUCE_CALLTYPE subtract (double* dest, const double* src1, const double* src2, int num) noexcept;
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;
@@ -89,12 +107,24 @@ public:
/** Multiplies the destination values by the source values. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src, int numValues) noexcept;
/** Multiplies each source1 value by the correspinding source2 value, then stores it in the destination array. */
static void JUCE_CALLTYPE multiply (float* dest, const float* src1, const float* src2, int numValues) noexcept;
/** Multiplies each source1 value by the correspinding source2 value, then stores it in the destination array. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src1, const double* src2, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (double* dest, double multiplier, int numValues) noexcept;
/** Multiplies each of the source values by a fixed multiplier and stores the result in the destination array. */
static void JUCE_CALLTYPE multiply (float* dest, const float* src, float multiplier, int num) noexcept;
/** Multiplies each of the source values by a fixed multiplier and stores the result in the destination array. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src, double multiplier, int num) noexcept;
/** Copies a source vector to a destination, negating each value. */
static void JUCE_CALLTYPE negate (float* dest, const float* src, int numValues) noexcept;
@@ -181,7 +181,7 @@ public:
for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
output = allPass[0][j].process (output);
samples[i] = output * wet1 + input * dry;
samples[i] = output * wet1 + samples[i] * dry;
}
}
@@ -57,7 +57,9 @@
#endif
#if (JUCE_MAC || JUCE_IOS) && JUCE_USE_VDSP_FRAMEWORK
#define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers)
#include <Accelerate/Accelerate.h>
#undef Point
#else
#undef JUCE_USE_VDSP_FRAMEWORK
#endif
@@ -1,7 +1,7 @@
{
"id": "juce_audio_basics",
"name": "JUCE audio and midi data classes",
"version": "3.0.5",
"version": "3.0.8",
"description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",
@@ -210,7 +210,7 @@ bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes,
const int itemSize = MidiBufferHelpers::getEventDataSize (data);
numBytes = itemSize;
midiData = data + sizeof (int32) + sizeof (uint16);
data += sizeof (int32) + sizeof (uint16) + itemSize;
data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize;
return true;
}
@@ -223,7 +223,7 @@ bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePositio
samplePosition = MidiBufferHelpers::getEventTime (data);
const int itemSize = MidiBufferHelpers::getEventDataSize (data);
result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition);
data += sizeof (int32) + sizeof (uint16) + itemSize;
data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize;
return true;
}
@@ -186,9 +186,10 @@ public:
/** Retrieves a copy of the next event from the buffer.
@param result on return, this will be the message (the MidiMessage's timestamp
is not set)
@param samplePosition on return, this will be the position of the event
@param result on return, this will be the message. The MidiMessage's timestamp
is set to the same value as samplePosition.
@param samplePosition on return, this will be the position of the event, as a
sample index in the buffer
@returns true if an event was found, or false if the iterator has reached
the end of the buffer
*/
@@ -203,7 +204,8 @@ public:
temporarily until the MidiBuffer is altered.
@param numBytesOfMidiData on return, this is the number of bytes of data used by the
midi message
@param samplePosition on return, this will be the position of the event
@param samplePosition on return, this will be the position of the event, as a
sample index in the buffer
@returns true if an event was found, or false if the iterator has reached
the end of the buffer
*/
@@ -129,7 +129,7 @@ MidiMessage::MidiMessage (const MidiMessage& other)
{
if (other.allocatedData != nullptr)
{
allocatedData.malloc (size);
allocatedData.malloc ((size_t) size);
memcpy (allocatedData, other.allocatedData, (size_t) size);
}
else
@@ -143,7 +143,7 @@ MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp)
{
if (other.allocatedData != nullptr)
{
allocatedData.malloc (size);
allocatedData.malloc ((size_t) size);
memcpy (allocatedData, other.allocatedData, (size_t) size);
}
else
@@ -255,7 +255,7 @@ MidiMessage& MidiMessage::operator= (const MidiMessage& other)
if (other.allocatedData != nullptr)
{
allocatedData.malloc (size);
allocatedData.malloc ((size_t) size);
memcpy (allocatedData, other.allocatedData, (size_t) size);
}
else
@@ -297,7 +297,7 @@ uint8* MidiMessage::allocateSpace (int bytes)
{
if (bytes > 4)
{
allocatedData.malloc (bytes);
allocatedData.malloc ((size_t) bytes);
return allocatedData;
}
@@ -661,7 +661,7 @@ String MidiMessage::getTextFromTextMetaEvent() const
MidiMessage MidiMessage::textMetaEvent (int type, StringRef text)
{
jassert (type > 0 && type < 16)
jassert (type > 0 && type < 16);
MidiMessage result;
@@ -29,6 +29,7 @@ MidiMessageSequence::MidiMessageSequence()
MidiMessageSequence::MidiMessageSequence (const MidiMessageSequence& other)
{
list.addCopiesOf (other.list);
updateMatchedPairs();
}
MidiMessageSequence& MidiMessageSequence::operator= (const MidiMessageSequence& other)
@@ -52,17 +53,17 @@ void MidiMessageSequence::clear()
list.clear();
}
int MidiMessageSequence::getNumEvents() const
int MidiMessageSequence::getNumEvents() const noexcept
{
return list.size();
}
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::getEventPointer (const int index) const
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::getEventPointer (const int index) const noexcept
{
return list [index];
}
double MidiMessageSequence::getTimeOfMatchingKeyUp (const int index) const
double MidiMessageSequence::getTimeOfMatchingKeyUp (const int index) const noexcept
{
if (const MidiEventHolder* const meh = list [index])
if (meh->noteOffObject != nullptr)
@@ -71,7 +72,7 @@ double MidiMessageSequence::getTimeOfMatchingKeyUp (const int index) const
return 0.0;
}
int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const
int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const noexcept
{
if (const MidiEventHolder* const meh = list [index])
return list.indexOf (meh->noteOffObject);
@@ -79,12 +80,12 @@ int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const
return -1;
}
int MidiMessageSequence::getIndexOf (MidiEventHolder* const event) const
int MidiMessageSequence::getIndexOf (MidiEventHolder* const event) const noexcept
{
return list.indexOf (event);
}
int MidiMessageSequence::getNextIndexAtTime (const double timeStamp) const
int MidiMessageSequence::getNextIndexAtTime (const double timeStamp) const noexcept
{
const int numEvents = list.size();
@@ -97,17 +98,17 @@ int MidiMessageSequence::getNextIndexAtTime (const double timeStamp) const
}
//==============================================================================
double MidiMessageSequence::getStartTime() const
double MidiMessageSequence::getStartTime() const noexcept
{
return getEventTime (0);
}
double MidiMessageSequence::getEndTime() const
double MidiMessageSequence::getEndTime() const noexcept
{
return getEventTime (list.size() - 1);
}
double MidiMessageSequence::getEventTime (const int index) const
double MidiMessageSequence::getEventTime (const int index) const noexcept
{
if (const MidiEventHolder* const meh = list [index])
return meh->message.getTimeStamp();
@@ -181,13 +182,13 @@ void MidiMessageSequence::addSequence (const MidiMessageSequence& other,
}
//==============================================================================
void MidiMessageSequence::sort()
void MidiMessageSequence::sort() noexcept
{
MidiMessageSequenceSorter sorter;
list.sort (sorter, true);
}
void MidiMessageSequence::updateMatchedPairs()
void MidiMessageSequence::updateMatchedPairs() noexcept
{
for (int i = 0; i < list.size(); ++i)
{
@@ -226,7 +227,7 @@ void MidiMessageSequence::updateMatchedPairs()
}
}
void MidiMessageSequence::addTimeToMessages (const double delta)
void MidiMessageSequence::addTimeToMessages (const double delta) noexcept
{
for (int i = list.size(); --i >= 0;)
{
@@ -91,47 +91,47 @@ public:
void clear();
/** Returns the number of events in the sequence. */
int getNumEvents() const;
int getNumEvents() const noexcept;
/** Returns a pointer to one of the events. */
MidiEventHolder* getEventPointer (int index) const;
MidiEventHolder* getEventPointer (int index) const noexcept;
/** Returns the time of the note-up that matches the note-on at this index.
If the event at this index isn't a note-on, it'll just return 0.
@see MidiMessageSequence::MidiEventHolder::noteOffObject
*/
double getTimeOfMatchingKeyUp (int index) const;
double getTimeOfMatchingKeyUp (int index) const noexcept;
/** Returns the index of the note-up that matches the note-on at this index.
If the event at this index isn't a note-on, it'll just return -1.
@see MidiMessageSequence::MidiEventHolder::noteOffObject
*/
int getIndexOfMatchingKeyUp (int index) const;
int getIndexOfMatchingKeyUp (int index) const noexcept;
/** Returns the index of an event. */
int getIndexOf (MidiEventHolder* event) const;
int getIndexOf (MidiEventHolder* event) const noexcept;
/** Returns the index of the first event on or after the given timestamp.
If the time is beyond the end of the sequence, this will return the
number of events.
*/
int getNextIndexAtTime (double timeStamp) const;
int getNextIndexAtTime (double timeStamp) const noexcept;
//==============================================================================
/** Returns the timestamp of the first event in the sequence.
@see getEndTime
*/
double getStartTime() const;
double getStartTime() const noexcept;
/** Returns the timestamp of the last event in the sequence.
@see getStartTime
*/
double getEndTime() const;
double getEndTime() const noexcept;
/** Returns the timestamp of the event at a given index.
If the index is out-of-range, this will return 0.0
*/
double getEventTime (int index) const;
double getEventTime (int index) const noexcept;
//==============================================================================
/** Inserts a midi message into the sequence.
@@ -185,13 +185,13 @@ public:
will scan the list and make sure all the note-offs in the MidiEventHolder
structures are pointing at the correct ones.
*/
void updateMatchedPairs();
void updateMatchedPairs() noexcept;
/** Forces a sort of the sequence.
You may need to call this if you've manually modified the timestamps of some
events such that the overall order now needs updating.
*/
void sort();
void sort() noexcept;
//==============================================================================
/** Copies all the messages for a particular midi channel to another sequence.
@@ -224,7 +224,7 @@ public:
/** Adds an offset to the timestamps of all events in the sequence.
@param deltaTime the amount to add to each timestamp.
*/
void addTimeToMessages (double deltaTime);
void addTimeToMessages (double deltaTime) noexcept;
//==============================================================================
/** Scans through the sequence to determine the state of any midi controllers at
@@ -47,23 +47,28 @@ void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputS
ratio = jmax (0.0, samplesInPerOutputSample);
}
void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected,
double sampleRate)
void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate)
{
const SpinLock::ScopedLockType sl (ratioLock);
input->prepareToPlay (samplesPerBlockExpected, sampleRate);
buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32);
buffer.clear();
sampsInBuffer = 0;
bufferPos = 0;
subSampleOffset = 0.0;
filterStates.calloc ((size_t) numChannels);
srcBuffers.calloc ((size_t) numChannels);
destBuffers.calloc ((size_t) numChannels);
createLowPass (ratio);
flushBuffers();
}
void ResamplingAudioSource::flushBuffers()
{
buffer.clear();
bufferPos = 0;
sampsInBuffer = 0;
subSampleOffset = 0.0;
resetFilters();
}
@@ -225,7 +230,8 @@ void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double
void ResamplingAudioSource::resetFilters()
{
filterStates.clear ((size_t) numChannels);
if (filterStates != nullptr)
filterStates.clear ((size_t) numChannels);
}
void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs)
@@ -66,6 +66,9 @@ public:
*/
double getResamplingRatio() const noexcept { return ratio; }
/** Clears any buffers and filters that the resampler is using. */
void flushBuffers();
//==============================================================================
void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override;
void releaseResources() override;
@@ -163,10 +163,7 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu
: numSamples;
if (numThisTime > 0)
{
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime);
}
renderVoices (outputBuffer, startSample, numThisTime);
if (useEvent)
handleMidiEvent (m);
@@ -176,6 +173,12 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu
}
}
void Synthesiser::renderVoices (AudioSampleBuffer& buffer, int startSample, int numSamples)
{
for (int i = voices.size(); --i >= 0;)
voices.getUnchecked (i)->renderNextBlock (buffer, startSample, numSamples);
}
void Synthesiser::handleMidiEvent (const MidiMessage& m)
{
if (m.isNoteOn())
@@ -184,7 +187,7 @@ void Synthesiser::handleMidiEvent (const MidiMessage& m)
}
else if (m.isNoteOff())
{
noteOff (m.getChannel(), m.getNoteNumber(), true);
noteOff (m.getChannel(), m.getNoteNumber(), m.getFloatVelocity(), true);
}
else if (m.isAllNotesOff() || m.isAllSoundOff())
{
@@ -230,10 +233,10 @@ void Synthesiser::noteOn (const int midiChannel,
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& voice->isPlayingChannel (midiChannel))
stopVoice (voice, true);
stopVoice (voice, 1.0f, true);
}
startVoice (findFreeVoice (sound, shouldStealNotes),
startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes),
sound, midiChannel, midiNoteNumber, velocity);
}
}
@@ -248,7 +251,7 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice,
if (voice != nullptr && sound != nullptr)
{
if (voice->currentlyPlayingSound != nullptr)
voice->stopNote (false);
voice->stopNote (0.0f, false);
voice->startNote (midiNoteNumber, velocity, sound,
lastPitchWheelValues [midiChannel - 1]);
@@ -261,11 +264,11 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice,
}
}
void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff)
void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff)
{
jassert (voice != nullptr);
voice->stopNote (allowTailOff);
voice->stopNote (velocity, allowTailOff);
// the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()!
jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0));
@@ -273,6 +276,7 @@ void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff)
void Synthesiser::noteOff (const int midiChannel,
const int midiNoteNumber,
const float velocity,
const bool allowTailOff)
{
const ScopedLock sl (lock);
@@ -291,7 +295,7 @@ void Synthesiser::noteOff (const int midiChannel,
voice->keyIsDown = false;
if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown))
stopVoice (voice, allowTailOff);
stopVoice (voice, velocity, allowTailOff);
}
}
}
@@ -307,7 +311,7 @@ void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff)
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel))
voice->stopNote (allowTailOff);
voice->stopNote (1.0f, allowTailOff);
}
sustainPedalsDown.clear();
@@ -379,7 +383,7 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown)
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown)
stopVoice (voice, true);
stopVoice (voice, 1.0f, true);
}
sustainPedalsDown.clearBit (midiChannel);
@@ -400,7 +404,7 @@ void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
if (isDown)
voice->sostenutoPedalDown = true;
else if (voice->sostenutoPedalDown)
stopVoice (voice, true);
stopVoice (voice, 1.0f, true);
}
}
}
@@ -412,7 +416,9 @@ void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
}
//==============================================================================
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, const bool stealIfNoneAvailable) const
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
int midiChannel, int midiNoteNumber,
const bool stealIfNoneAvailable) const
{
const ScopedLock sl (lock);
@@ -425,25 +431,68 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, con
}
if (stealIfNoneAvailable)
return findVoiceToSteal (soundToPlay);
return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber);
return nullptr;
}
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay) const
struct VoiceAgeSorter
{
// currently this just steals the one that's been playing the longest, but could be made a bit smarter..
SynthesiserVoice* oldest = nullptr;
static int compareElements (SynthesiserVoice* v1, SynthesiserVoice* v2) noexcept
{
return v1->wasStartedBefore (*v2) ? 1 : (v2->wasStartedBefore (*v1) ? -1 : 0);
}
};
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
int /*midiChannel*/, int midiNoteNumber) const
{
SynthesiserVoice* bottom = nullptr;
SynthesiserVoice* top = nullptr;
// this is a list of voices we can steal, sorted by how long they've been running
Array<SynthesiserVoice*> usableVoices;
usableVoices.ensureStorageAllocated (voices.size());
for (int i = 0; i < voices.size(); ++i)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->canPlaySound (soundToPlay)
&& (oldest == nullptr || voice->wasStartedBefore (*oldest)))
oldest = voice;
if (voice->canPlaySound (soundToPlay))
{
VoiceAgeSorter sorter;
usableVoices.addSorted (sorter, voice);
const int note = voice->getCurrentlyPlayingNote();
if (bottom == nullptr || note < bottom->getCurrentlyPlayingNote())
bottom = voice;
if (top == nullptr || note > top->getCurrentlyPlayingNote())
top = voice;
}
}
jassert (oldest != nullptr);
return oldest;
jassert (bottom != nullptr && top != nullptr);
// The oldest note that's playing with the target pitch playing is ideal..
for (int i = 0; i < usableVoices.size(); ++i)
{
SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
return voice;
}
// ..otherwise, look for the oldest note that isn't the top or bottom note..
for (int i = 0; i < usableVoices.size(); ++i)
{
SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
if (voice != bottom && voice != top)
return voice;
}
// ..otherwise, there's only one or two voices to choose from - we'll return the top one..
return top;
}
@@ -55,14 +55,14 @@ public:
The Synthesiser will use this information when deciding which sounds to trigger
for a given note.
*/
virtual bool appliesToNote (const int midiNoteNumber) = 0;
virtual bool appliesToNote (int midiNoteNumber) = 0;
/** Returns true if the sound should be triggered by midi events on a given channel.
The Synthesiser will use this information when deciding which sounds to trigger
for a given note.
*/
virtual bool appliesToChannel (const int midiChannel) = 0;
virtual bool appliesToChannel (int midiChannel) = 0;
/** The class is reference-counted, so this is a handy pointer class for it. */
typedef ReferenceCountedObjectPtr<SynthesiserSound> Ptr;
@@ -127,6 +127,8 @@ public:
This will be called during the rendering callback, so must be fast and thread-safe.
The velocity indicates how quickly the note was released - 0 is slowly, 1 is quickly.
If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all
sound immediately, and must call clearCurrentNote() to reset the state of this voice
and allow the synth to reassign it another sound.
@@ -136,7 +138,7 @@ public:
finishes playing (during the rendering callback), it must make sure that it calls
clearCurrentNote().
*/
virtual void stopNote (bool allowTailOff) = 0;
virtual void stopNote (float velocity, bool allowTailOff) = 0;
/** Called to let the voice know that the pitch wheel has been moved.
This will be called during the rendering callback, so must be fast and thread-safe.
@@ -173,13 +175,6 @@ public:
int startSample,
int numSamples) = 0;
/** Returns true if the voice is currently playing a sound which is mapped to the given
midi channel.
If it's not currently playing, this will return false.
*/
bool isPlayingChannel (int midiChannel) const;
/** Changes the voice's reference sample rate.
The rate is set so that subclasses know the output rate and can set their pitch
@@ -188,7 +183,19 @@ public:
This method is called by the synth, and subclasses can access the current rate with
the currentSampleRate member.
*/
void setCurrentPlaybackSampleRate (double newRate);
virtual void setCurrentPlaybackSampleRate (double newRate);
/** Returns the current target sample rate at which rendering is being done.
Subclasses may need to know this so that they can pitch things correctly.
*/
double getSampleRate() const noexcept { return currentSampleRate; }
/** Returns true if the voice is currently playing a sound which is mapped to the given
midi channel.
If it's not currently playing, this will return false.
*/
bool isPlayingChannel (int midiChannel) const;
/** Returns true if the key that triggered this voice is still held down.
Note that the voice may still be playing after the key was released (e.g because the
@@ -203,13 +210,6 @@ public:
bool wasStartedBefore (const SynthesiserVoice& other) const noexcept;
protected:
//==============================================================================
/** Returns the current target sample rate at which rendering is being done.
This is available for subclasses so they can pitch things correctly.
*/
double getSampleRate() const { return currentSampleRate; }
/** Resets the state of this voice after a sound has finished playing.
The subclass must call this when it finishes playing a note and becomes available
@@ -235,6 +235,11 @@ private:
SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown, sostenutoPedalDown;
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// Note the new parameters for this method.
virtual int stopNote (bool) { return 0; }
#endif
JUCE_LEAK_DETECTOR (SynthesiserVoice)
};
@@ -268,8 +273,7 @@ class JUCE_API Synthesiser
public:
//==============================================================================
/** Creates a new synthesiser.
You'll need to add some sounds and voices before it'll make any sound..
You'll need to add some sounds and voices before it'll make any sound.
*/
Synthesiser();
@@ -365,6 +369,7 @@ public:
*/
virtual void noteOff (int midiChannel,
int midiNoteNumber,
float velocity,
bool allowTailOff);
/** Turns off all notes.
@@ -444,7 +449,7 @@ public:
This value is propagated to the voices so that they can use it to render the correct
pitches.
*/
void setCurrentPlaybackSampleRate (double sampleRate);
virtual void setCurrentPlaybackSampleRate (double sampleRate);
/** Creates the next block of audio output.
@@ -463,6 +468,11 @@ public:
int startSample,
int numSamples);
/** Returns the current target sample rate at which rendering is being done.
Subclasses may need to know this so that they can pitch things correctly.
*/
double getSampleRate() const noexcept { return sampleRate; }
protected:
//==============================================================================
/** This is used to control access to the rendering callback and the note trigger methods. */
@@ -474,21 +484,34 @@ protected:
/** The last pitch-wheel values for each midi channel. */
int lastPitchWheelValues [16];
/** Searches through the voices to find one that's not currently playing, and which
can play the given sound.
/** Renders the voices for the given range.
By default this just calls renderNextBlock() on each voice, but you may need
to override it to handle custom cases.
*/
virtual void renderVoices (AudioSampleBuffer& outputAudio,
int startSample, int numSamples);
/** Searches through the voices to find one that's not currently playing, and
which can play the given sound.
Returns nullptr if all voices are busy and stealing isn't enabled.
This can be overridden to implement custom voice-stealing algorithms.
To implement a custom note-stealing algorithm, you can either override this
method, or (preferably) override findVoiceToSteal().
*/
virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable) const;
int midiChannel,
int midiNoteNumber,
bool stealIfNoneAvailable) const;
/** Chooses a voice that is most suitable for being re-used.
The default method returns the one that has been playing for the longest, but
you may want to override this and do something more cunning instead.
The default method will attempt to find the oldest voice that isn't the
bottom or top note being played. If that's not suitable for your synth,
you can override this method and do something more cunning instead.
*/
virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay) const;
virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay,
int midiChannel,
int midiNoteNumber) const;
/** Starts a specified voice playing a particular sound.
@@ -511,11 +534,14 @@ private:
bool shouldStealNotes;
BigInteger sustainPedalsDown;
void stopVoice (SynthesiserVoice*, bool allowTailOff);
void stopVoice (SynthesiserVoice*, float velocity, bool allowTailOff);
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// Note the new parameters for this method.
// Note the new parameters for these methods.
virtual int findFreeVoice (const bool) const { return 0; }
virtual int noteOff (int, int, int) { return 0; }
virtual int findFreeVoice (SynthesiserSound*, const bool) { return 0; }
virtual int findVoiceToSteal (SynthesiserSound*) const { return 0; }
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser)