Browse Source

Update juce (no patches)

tags/2018-04-16
falkTX 8 years ago
parent
commit
794896deb2
100 changed files with 3026 additions and 2526 deletions
  1. +2
    -2
      .gitignore
  2. +0
    -16
      libs/juce/patches/linux-vst-reparent.patch
  3. +12
    -0
      libs/juce/patches/vst3-less-strict.patch
  4. +6
    -0
      libs/juce/source/README.txt
  5. +22
    -20
      libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h
  6. +154
    -4
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  7. +36
    -0
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  8. +277
    -0
      libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.cpp
  9. +92
    -0
      libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.h
  10. +3
    -3
      libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilter.cpp
  11. +0
    -239
      libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilterOld.cpp
  12. +0
    -148
      libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilterOld.h
  13. +8
    -2
      libs/juce/source/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp
  14. +92
    -43
      libs/juce/source/modules/juce_audio_basics/effects/juce_Reverb.h
  15. +1
    -1
      libs/juce/source/modules/juce_audio_basics/juce_audio_basics.cpp
  16. +4
    -1
      libs/juce/source/modules/juce_audio_basics/juce_audio_basics.h
  17. +1
    -1
      libs/juce/source/modules/juce_audio_basics/juce_module_info
  18. +15
    -21
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp
  19. +1
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h
  20. +9
    -7
      libs/juce/source/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp
  21. +21
    -13
      libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  22. +13
    -7
      libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  23. +18
    -13
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
  24. +0
    -1
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
  25. +1
    -1
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp
  26. +1
    -1
      libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h
  27. +1
    -1
      libs/juce/source/modules/juce_audio_devices/juce_audio_devices.cpp
  28. +10
    -1
      libs/juce/source/modules/juce_audio_devices/juce_audio_devices.h
  29. +1
    -1
      libs/juce/source/modules/juce_audio_devices/juce_module_info
  30. +6
    -8
      libs/juce/source/modules/juce_audio_devices/midi_io/juce_MidiInput.h
  31. +12
    -17
      libs/juce/source/modules/juce_audio_devices/midi_io/juce_MidiOutput.h
  32. +6
    -6
      libs/juce/source/modules/juce_audio_devices/native/juce_android_OpenSL.cpp
  33. +21
    -7
      libs/juce/source/modules/juce_audio_devices/native/juce_linux_ALSA.cpp
  34. +12
    -3
      libs/juce/source/modules/juce_audio_devices/native/juce_linux_Midi.cpp
  35. +1
    -1
      libs/juce/source/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
  36. +65
    -49
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
  37. +1
    -1
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp
  38. +324
    -140
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
  39. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/all.h
  40. +2
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/alloc.h
  41. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/assert.h
  42. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/callback.h
  43. +20
    -15
      libs/juce/source/modules/juce_audio_formats/codecs/flac/compat.h
  44. +28
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/endswap.h
  45. +3
    -3
      libs/juce/source/modules/juce_audio_formats/codecs/flac/export.h
  46. +4
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/format.h
  47. +2
    -3
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c
  48. +6
    -10
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c
  49. +5
    -31
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c
  50. +338
    -267
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c
  51. +2
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c
  52. +3
    -16
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c
  53. +2
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/float.c
  54. +3
    -8
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/format.c
  55. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h
  56. +48
    -33
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h
  57. +2
    -11
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitreader.h
  58. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitwriter.h
  59. +31
    -21
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/cpu.h
  60. +2
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/crc.h
  61. +14
    -5
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/fixed.h
  62. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/float.h
  63. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/format.h
  64. +37
    -6
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/lpc.h
  65. +7
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/md5.h
  66. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/memory.h
  67. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h
  68. +67
    -0
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder.h
  69. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder_framing.h
  70. +3
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/window.h
  71. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/all.h
  72. +2
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_decoder.h
  73. +8
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_encoder.h
  74. +17
    -13
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/lpc_flac.c
  75. +203
    -106
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/md5.c
  76. +8
    -21
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/memory.c
  77. +123
    -100
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c
  78. +245
    -54
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder.c
  79. +2
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder_framing.c
  80. +68
    -13
      libs/juce/source/modules/juce_audio_formats/codecs/flac/libFLAC/window_flac.c
  81. +2
    -2
      libs/juce/source/modules/juce_audio_formats/codecs/flac/metadata.h
  82. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/ordinals.h
  83. +1
    -1
      libs/juce/source/modules/juce_audio_formats/codecs/flac/stream_decoder.h
  84. +45
    -24
      libs/juce/source/modules/juce_audio_formats/codecs/flac/stream_encoder.h
  85. +69
    -0
      libs/juce/source/modules/juce_audio_formats/codecs/flac/win_utf8_io.h
  86. +118
    -56
      libs/juce/source/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp
  87. +9
    -9
      libs/juce/source/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp
  88. +41
    -17
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
  89. +13
    -11
      libs/juce/source/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp
  90. +3
    -3
      libs/juce/source/modules/juce_audio_formats/format/juce_AudioFormatReader.h
  91. +2
    -9
      libs/juce/source/modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp
  92. +1
    -2
      libs/juce/source/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h
  93. +9
    -3
      libs/juce/source/modules/juce_audio_formats/format/juce_MemoryMappedAudioFormatReader.h
  94. +1
    -1
      libs/juce/source/modules/juce_audio_formats/juce_module_info
  95. +1
    -1
      libs/juce/source/modules/juce_audio_formats/sampler/juce_Sampler.cpp
  96. +14
    -4
      libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  97. +131
    -62
      libs/juce/source/modules/juce_audio_plugin_client/AU/juce_AU_Wrapper.mm
  98. +0
    -83
      libs/juce/source/modules/juce_audio_plugin_client/LV2/base64/Base64.cpp
  99. +0
    -446
      libs/juce/source/modules/juce_audio_plugin_client/LV2/includes/atom-util.h
  100. +0
    -246
      libs/juce/source/modules/juce_audio_plugin_client/LV2/includes/atom.h

+ 2
- 2
.gitignore View File

@@ -38,8 +38,10 @@ _old
ports/_todo

libs/juce/source/.gitignore
libs/juce/source/ChangeList.txt
libs/juce/source/amalgamation/
libs/juce/source/docs/
libs/juce/source/examples/
libs/juce/source/extras/
libs/juce/source/juce.h
libs/juce/source/juce_amalgamated.cpp
@@ -47,7 +49,5 @@ libs/juce/source/juce_amalgamated.h
libs/juce/source/juce_amalgamated.mm
libs/juce/source/modules/juce_box2d/
libs/juce/source/modules/juce_browser_plugin_client/
libs/juce/source/modules/juce_cryptography/
libs/juce/source/modules/juce_opengl/
libs/juce/source/modules/juce_tracktion_marketplace/
libs/juce/source/modules/juce_video/

+ 0
- 16
libs/juce/patches/linux-vst-reparent.patch View File

@@ -1,16 +0,0 @@
diff --git a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp b/libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
index b88a3b2..d057fb0 100644
--- a/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
+++ b/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
@@ -1180,8 +1180,10 @@ public:
editorComp->addToDesktop (0, ptr);
hostWindow = (HWND) ptr;
#elif JUCE_LINUX
- editorComp->addToDesktop (0, ptr);
+ editorComp->addToDesktop (0);
hostWindow = (Window) ptr;
+ Window editorWnd = (Window) editorComp->getWindowHandle();
+ XReparentWindow (display, editorWnd, hostWindow, 0, 0);
#else
hostWindow = attachComponentToWindowRef (editorComp, ptr, useNSView);
#endif

+ 12
- 0
libs/juce/patches/vst3-less-strict.patch View File

@@ -0,0 +1,12 @@
--- a/source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
+++ b/source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
@@ -1403,7 +1403,8 @@ class VST3ModuleHandle : public ReferenceCountedObject
const Result result (finder.findDescriptionsAndPerform (f));
- if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString())
+ if (result.getErrorMessage() == MatchingDescriptionFinder::getSuccessString() ||
+ result.getErrorMessage().isEmpty())
{
name = description.name;
return true;

+ 6
- 0
libs/juce/source/README.txt View File

@@ -7,5 +7,11 @@ It contains pretty much everything you're likely to need to create
most applications, and is particularly well-suited for building
highly-customised GUIs, and for handling graphics and sound.

Most JUCE modules are shared under the GNU Public Licence
(GPLv2, v3, and the AGPLv3). This means that the code can
be freely copied and distributed, and costs nothing to use
in other GPL applications. One module (the juce_core module)
is permissively licensed under the ISC.

For more information, visit the website:
http://www.juce.com

+ 22
- 20
libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h View File

@@ -487,13 +487,10 @@ public:
}
/** Scans a block of data, returning the lowest and highest levels as floats */
void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept
Range<float> findMinAndMax (size_t numSamples) const noexcept
{
if (numSamples == 0)
{
minValue = maxValue = 0;
return;
}
return Range<float>();
Pointer dest (*this);
@@ -512,27 +509,32 @@ public:
if (v < mn) mn = v;
}
minValue = mn;
maxValue = mx;
return Range<float> (mn, mx);
}
else
int32 mn = dest.getAsInt32();
dest.advance();
int32 mx = mn;
while (--numSamples > 0)
{
int32 mn = dest.getAsInt32();
const int v = dest.getAsInt32();
dest.advance();
int32 mx = mn;
while (--numSamples > 0)
{
const int v = dest.getAsInt32();
dest.advance();
if (mx < v) mx = v;
if (v < mn) mn = v;
}
if (mx < v) mx = v;
if (v < mn) mn = v;
}
return Range<float> (mn * (float) (1.0 / (1.0 + Int32::maxValue)),
mx * (float) (1.0 / (1.0 + Int32::maxValue)));
}
minValue = mn * (float) (1.0 / (1.0 + Int32::maxValue));
maxValue = mx * (float) (1.0 / (1.0 + Int32::maxValue));
}
/** Scans a block of data, returning the lowest and highest levels as floats */
void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept
{
Range<float> r (findMinAndMax (numSamples));
minValue = r.getStart();
maxValue = r.getEnd();
}
/** Returns true if the pointer is using a floating-point format. */


+ 154
- 4
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp View File

@@ -134,6 +134,19 @@ namespace FloatVectorHelpers
} \
JUCE_FINISH_VEC_OP (normalOp)
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_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; \
Mode::ParallelType (&loadDst) (const Mode::Type* v) = FloatVectorHelpers::isAligned (dest) ? Mode::loadA : Mode::loadU; \
void (&storeDst) (Mode::Type* dest, Mode::ParallelType a) = FloatVectorHelpers::isAligned (dest) ? Mode::storeA : Mode::storeU; \
JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, loadSrc1, loadSrc2, loadDst, storeDst, locals, increment); \
} \
JUCE_FINISH_VEC_OP (normalOp)
//==============================================================================
#elif JUCE_USE_ARM_NEON
@@ -211,6 +224,13 @@ namespace FloatVectorHelpers
JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
JUCE_FINISH_VEC_OP (normalOp)
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
JUCE_BEGIN_VEC_OP \
setupOp \
JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \
JUCE_FINISH_VEC_OP (normalOp)
//==============================================================================
#else
#define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \
@@ -221,6 +241,10 @@ namespace FloatVectorHelpers
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \
for (int i = 0; i < num; ++i) normalOp;
#define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \
for (int i = 0; i < num; ++i) normalOp;
#endif
//==============================================================================
@@ -240,11 +264,20 @@ namespace FloatVectorHelpers
increment; \
}
#define JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD(vecOp, src1Load, src2Load, dstLoad, dstStore, locals, increment) \
for (int i = 0; i < numLongOps; ++i) \
{ \
locals (src1Load, src2Load, dstLoad); \
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_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);
#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_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad) const Mode::ParallelType d = dstLoad (dest), 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; };
@@ -580,6 +613,28 @@ void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const d
const Mode::ParallelType mult = Mode::load1 (multiplier);)
}
void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vma ((float*) src1, 1, (float*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i], Mode::add (d, Mode::mul (s1, s2)),
JUCE_LOAD_SRC1_SRC2_DEST,
JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmaD ((double*) src1, 1, (double*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i], Mode::add (d, Mode::mul (s1, s2)),
JUCE_LOAD_SRC1_SRC2_DEST,
JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
@@ -682,6 +737,96 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::min (float* dest, const float* src, float comp, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp), Mode::min (s, cmp),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType cmp = Mode::load1 (comp);)
}
void JUCE_CALLTYPE FloatVectorOperations::min (double* dest, const double* src, double comp, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp), Mode::min (s, cmp),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType cmp = Mode::load1 (comp);)
}
void JUCE_CALLTYPE FloatVectorOperations::min (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmin ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]), Mode::min (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::min (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vminD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]), Mode::min (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::max (float* dest, const float* src, float comp, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp), Mode::max (s, cmp),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType cmp = Mode::load1 (comp);)
}
void JUCE_CALLTYPE FloatVectorOperations::max (double* dest, const double* src, double comp, int num) noexcept
{
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp), Mode::max (s, cmp),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType cmp = Mode::load1 (comp);)
}
void JUCE_CALLTYPE FloatVectorOperations::max (float* dest, const float* src1, const float* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmax ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]), Mode::max (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::max (double* dest, const double* src1, const double* src2, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vmaxD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]), Mode::max (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, )
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::clip (float* dest, const float* src, float low, float high, int num) noexcept
{
jassert(high >= low);
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vclip ((float*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low), Mode::max (Mode::min (s, hi), lo),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType lo = Mode::load1 (low); const Mode::ParallelType hi = Mode::load1 (high);)
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::clip (double* dest, const double* src, double low, double high, int num) noexcept
{
jassert(high >= low);
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vclipD ((double*) src, 1, &low, &high, dest, 1, (vDSP_Length) num);
#else
JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low), Mode::max (Mode::min (s, hi), lo),
JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST,
const Mode::ParallelType lo = Mode::load1 (low); const Mode::ParallelType hi = Mode::load1 (high);)
#endif
}
Range<float> JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num) noexcept
{
#if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON
@@ -823,6 +968,11 @@ public:
fillRandomly (random, int1, num);
doConversionTest (u, data1, data2, int1, num);
FloatVectorOperations::fill (data1, (ValueType) 2, num);
FloatVectorOperations::fill (data2, (ValueType) 3, num);
FloatVectorOperations::addWithMultiply (data1, data1, data2, num);
u.expect (areAllValuesEqual (data1, num, (ValueType) 8));
}
static void doConversionTest (UnitTest& u, float* data1, float* data2, int* const int1, int num)


+ 36
- 0
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h View File

@@ -101,6 +101,12 @@ public:
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (double* dest, const double* src, double multiplier, int numValues) noexcept;
/** Multiplies each source1 value by the corresponding source2 value, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Multiplies each source1 value by the corresponding source2 value, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (double* dest, const double* src1, const double* src2, int num) noexcept;
/** Multiplies the destination values by the source values. */
static void JUCE_CALLTYPE multiply (float* dest, const float* src, int numValues) noexcept;
@@ -134,6 +140,36 @@ public:
/** Converts a stream of integers to floats, multiplying each one by the given multiplier. */
static void JUCE_CALLTYPE convertFixedToFloat (float* dest, const int* src, float multiplier, int numValues) noexcept;
/** Each element of dest will be the minimum of the corresponding element of the source array and the given comp value. */
static void JUCE_CALLTYPE min (float* dest, const float* src, float comp, int num) noexcept;
/** Each element of dest will be the minimum of the corresponding element of the source array and the given comp value. */
static void JUCE_CALLTYPE min (double* dest, const double* src, double comp, int num) noexcept;
/** Each element of dest will be the minimum of the corresponding source1 and source2 values. */
static void JUCE_CALLTYPE min (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Each element of dest will be the minimum of the corresponding source1 and source2 values. */
static void JUCE_CALLTYPE min (double* dest, const double* src1, const double* src2, int num) noexcept;
/** Each element of dest will be the maximum of the corresponding element of the source array and the given comp value. */
static void JUCE_CALLTYPE max (float* dest, const float* src, float comp, int num) noexcept;
/** Each element of dest will be the maximum of the corresponding element of the source array and the given comp value. */
static void JUCE_CALLTYPE max (double* dest, const double* src, double comp, int num) noexcept;
/** Each element of dest will be the maximum of the corresponding source1 and source2 values. */
static void JUCE_CALLTYPE max (float* dest, const float* src1, const float* src2, int num) noexcept;
/** Each element of dest will be the maximum of the corresponding source1 and source2 values. */
static void JUCE_CALLTYPE max (double* dest, const double* src1, const double* src2, int num) noexcept;
/** Each element of dest is calculated by hard clipping the corresponding src element so that it is in the range specified by the arguments low and high. */
static void JUCE_CALLTYPE clip (float* dest, const float* src, float low, float high, int num) noexcept;
/** Each element of dest is calculated by hard clipping the corresponding src element so that it is in the range specified by the arguments low and high. */
static void JUCE_CALLTYPE clip (double* dest, const double* src, double low, double high, int num) noexcept;
/** Finds the miniumum and maximum values in the given array. */
static Range<float> JUCE_CALLTYPE findMinAndMax (const float* src, int numValues) noexcept;


+ 277
- 0
libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.cpp View File

@@ -0,0 +1,277 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
// (For the moment, we'll implement a few local operators for this complex class - one
// day we'll probably either have a juce complex class, or use the C++11 one)
static FFT::Complex operator+ (FFT::Complex a, FFT::Complex b) noexcept { FFT::Complex c = { a.r + b.r, a.i + b.i }; return c; }
static FFT::Complex operator- (FFT::Complex a, FFT::Complex b) noexcept { FFT::Complex c = { a.r - b.r, a.i - b.i }; return c; }
static FFT::Complex operator* (FFT::Complex a, FFT::Complex b) noexcept { FFT::Complex c = { a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r }; return c; }
static FFT::Complex& operator+= (FFT::Complex& a, FFT::Complex b) noexcept { a.r += b.r; a.i += b.i; return a; }
//==============================================================================
struct FFT::FFTConfig
{
FFTConfig (int sizeOfFFT, bool isInverse)
: fftSize (sizeOfFFT), inverse (isInverse), twiddleTable ((size_t) sizeOfFFT)
{
for (int i = 0; i < fftSize; ++i)
{
const double phase = (isInverse ? 2.0 : -2.0) * double_Pi * i / fftSize;
twiddleTable[i].r = (float) cos (phase);
twiddleTable[i].i = (float) sin (phase);
}
const int root = (int) std::sqrt ((double) fftSize);
int divisor = 4, n = fftSize;
for (int i = 0; i < numElementsInArray (factors); ++i)
{
while ((n % divisor) != 0)
{
if (divisor == 2) divisor = 3;
else if (divisor == 4) divisor = 2;
else divisor += 2;
if (divisor > root)
divisor = n;
}
n /= divisor;
jassert (divisor == 1 || divisor == 2 || divisor == 4);
factors[i].radix = divisor;
factors[i].length = n;
}
}
void perform (const Complex* input, Complex* output) const noexcept
{
perform (input, output, 1, 1, factors);
}
const int fftSize;
const bool inverse;
struct Factor { int radix, length; };
Factor factors[32];
HeapBlock<Complex> twiddleTable;
void perform (const Complex* input, Complex* output, const int stride, const int strideIn, const Factor* facs) const noexcept
{
const Factor factor (*facs++);
Complex* const originalOutput = output;
const Complex* const outputEnd = output + factor.radix * factor.length;
if (stride == 1 && factor.radix <= 5)
{
for (int i = 0; i < factor.radix; ++i)
perform (input + stride * strideIn * i, output + i * factor.length, stride * factor.radix, strideIn, facs);
butterfly (factor, output, stride);
return;
}
if (factor.length == 1)
{
do
{
*output++ = *input;
input += stride * strideIn;
}
while (output < outputEnd);
}
else
{
do
{
perform (input, output, stride * factor.radix, strideIn, facs);
input += stride * strideIn;
output += factor.length;
}
while (output < outputEnd);
}
butterfly (factor, originalOutput, stride);
}
void butterfly (const Factor factor, Complex* data, const int stride) const noexcept
{
switch (factor.radix)
{
case 1: break;
case 2: butterfly2 (data, stride, factor.length); return;
case 4: butterfly4 (data, stride, factor.length); return;
default: jassertfalse; break;
}
Complex* scratch = static_cast<Complex*> (alloca (sizeof (Complex) * (size_t) factor.radix));
for (int i = 0; i < factor.length; ++i)
{
for (int k = i, q1 = 0; q1 < factor.radix; ++q1)
{
scratch[q1] = data[k];
k += factor.length;
}
for (int k = i, q1 = 0; q1 < factor.radix; ++q1)
{
int twiddleIndex = 0;
data[k] = scratch[0];
for (int q = 1; q < factor.radix; ++q)
{
twiddleIndex += stride * k;
if (twiddleIndex >= fftSize)
twiddleIndex -= fftSize;
data[k] += scratch[q] * twiddleTable[twiddleIndex];
}
k += factor.length;
}
}
}
void butterfly2 (Complex* data, const int stride, const int length) const noexcept
{
Complex* dataEnd = data + length;
const Complex* tw = twiddleTable;
for (int i = length; --i >= 0;)
{
const Complex s (*dataEnd * *tw);
tw += stride;
*dataEnd++ = *data - s;
*data++ += s;
}
}
void butterfly4 (Complex* data, const int stride, const int length) const noexcept
{
const int lengthX2 = length * 2;
const int lengthX3 = length * 3;
const Complex* twiddle1 = twiddleTable;
const Complex* twiddle2 = twiddle1;
const Complex* twiddle3 = twiddle1;
for (int i = length; --i >= 0;)
{
const Complex s0 = data[length] * *twiddle1;
const Complex s1 = data[lengthX2] * *twiddle2;
const Complex s2 = data[lengthX3] * *twiddle3;
const Complex s3 = s0 + s2;
const Complex s4 = s0 - s2;
const Complex s5 = *data - s1;
*data += s1;
data[lengthX2] = *data - s3;
twiddle1 += stride;
twiddle2 += stride * 2;
twiddle3 += stride * 3;
*data += s3;
if (inverse)
{
data[length].r = s5.r - s4.i;
data[length].i = s5.i + s4.r;
data[lengthX3].r = s5.r + s4.i;
data[lengthX3].i = s5.i - s4.r;
}
else
{
data[length].r = s5.r + s4.i;
data[length].i = s5.i - s4.r;
data[lengthX3].r = s5.r - s4.i;
data[lengthX3].i = s5.i + s4.r;
}
++data;
}
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFTConfig)
};
//==============================================================================
FFT::FFT (int order, bool inverse) : config (new FFTConfig (1 << order, inverse)), size (1 << order) {}
FFT::~FFT() {}
void FFT::perform (const Complex* const input, Complex* const output) const noexcept
{
config->perform (input, output);
}
void FFT::performRealOnlyForwardTransform (float* d) const noexcept
{
// This can only be called on an FFT object that was created to do forward transforms.
jassert (! config->inverse);
Complex* const scratch = static_cast<Complex*> (alloca (16 + sizeof (Complex) * (size_t) size));
for (int i = 0; i < size; ++i)
{
scratch[i].r = d[i];
scratch[i].i = 0;
}
perform (scratch, reinterpret_cast<Complex*> (d));
}
void FFT::performRealOnlyInverseTransform (float* d) const noexcept
{
// This can only be called on an FFT object that was created to do inverse transforms.
jassert (config->inverse);
Complex* const scratch = static_cast<Complex*> (alloca (16 + sizeof (Complex) * (size_t) size));
perform (reinterpret_cast<const Complex*> (d), scratch);
const float scaleFactor = 1.0f / size;
for (int i = 0; i < size; ++i)
{
d[i] = scratch[i].r * scaleFactor;
d[i + size] = scratch[i].i * scaleFactor;
}
}
void FFT::performFrequencyOnlyForwardTransform (float* d) const noexcept
{
performRealOnlyForwardTransform (d);
const int twiceSize = size * 2;
for (int i = 0; i < twiceSize; i += 2)
{
d[i / 2] = juce_hypot (d[i], d[i + 1]);
if (i >= size)
{
d[i] = 0;
d[i + 1] = 0;
}
}
}

+ 92
- 0
libs/juce/source/modules/juce_audio_basics/effects/juce_FFT.h View File

@@ -0,0 +1,92 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
/**
A very minimal FFT class.
This is only a simple low-footprint implementation and isn't tuned for speed - it may
be useful for simple applications where one of the more complex FFT libraries would be
overkill. (But in the future it may end up becoming optimised of course...)
The FFT class itself contains lookup tables, so there's some overhead in creating
one, you should create and cache an FFT object for each size/direction of transform
that you need, and re-use them to perform the actual operation.
*/
class JUCE_API FFT
{
public:
/** Initialises an object for performing either a forward or inverse FFT with the given size.
The the number of points the FFT will operate on will be 2 ^ order.
*/
FFT (int order, bool isInverse);
/** Destructor. */
~FFT();
/** A complex number, for the purposes of the FFT class. */
struct Complex
{
float r; /**< Real part. */
float i; /**< Imaginary part. */
};
/** Performs an out-of-place FFT, either forward or inverse depending on the mode
that was passed to this object's constructor.
The arrays must contain at least getSize() elements.
*/
void perform (const Complex* input, Complex* output) const noexcept;
/** Performs an in-place forward transform on a block of real data.
The size of the array passed in must be 2 * getSize(), and the first half
should contain your raw input sample data. On return, the array will contain
complex frequency + phase data, and can be passed to performRealOnlyInverseTransform()
in order to convert it back to reals.
*/
void performRealOnlyForwardTransform (float* inputOutputData) const noexcept;
/** Performs a reverse operation to data created in performRealOnlyForwardTransform().
The size of the array passed in must be 2 * getSize(), containing complex
frequency and phase data. On return, the first half of the array will contain
the reconstituted samples.
*/
void performRealOnlyInverseTransform (float* inputOutputData) const noexcept;
/** Takes an array and simply transforms it to the frequency spectrum.
This may be handy for things like frequency displays or analysis.
*/
void performFrequencyOnlyForwardTransform (float* inputOutputData) const noexcept;
/** Returns the number of data points that this FFT was created to work with. */
int getSize() const noexcept { return size; }
private:
struct FFTConfig;
ScopedPointer<FFTConfig> config;
const int size;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFT)
};

+ 3
- 3
libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilter.cpp View File

@@ -23,7 +23,7 @@
*/
#if JUCE_INTEL
#define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0;
#define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8f || n > 1.0e-8f)) n = 0;
#else
#define JUCE_SNAP_TO_ZERO(n)
#endif
@@ -64,7 +64,7 @@ IIRCoefficients IIRCoefficients::makeLowPass (const double sampleRate,
{
jassert (sampleRate > 0);
const double n = 1.0 / tan (double_Pi * frequency / sampleRate);
const double n = 1.0 / std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
@@ -79,7 +79,7 @@ IIRCoefficients IIRCoefficients::makeLowPass (const double sampleRate,
IIRCoefficients IIRCoefficients::makeHighPass (const double sampleRate,
const double frequency) noexcept
{
const double n = tan (double_Pi * frequency / sampleRate);
const double n = std::tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);


+ 0
- 239
libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilterOld.cpp View File

@@ -1,239 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#if JUCE_INTEL
#define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0;
#else
#define JUCE_SNAP_TO_ZERO(n)
#endif
//==============================================================================
IIRFilterOld::IIRFilterOld()
: active (false), v1 (0), v2 (0)
{
zeromem (coefficients, sizeof (coefficients));
}
IIRFilterOld::IIRFilterOld (const IIRFilterOld& other)
: active (other.active), v1 (0), v2 (0)
{
const SpinLock::ScopedLockType sl (other.processLock);
memcpy (coefficients, other.coefficients, sizeof (coefficients));
}
IIRFilterOld::~IIRFilterOld()
{
}
//==============================================================================
void IIRFilterOld::reset() noexcept
{
const SpinLock::ScopedLockType sl (processLock);
v1 = v2 = 0;
}
float IIRFilterOld::processSingleSampleRaw (const float in) noexcept
{
float out = coefficients[0] * in + v1;
JUCE_SNAP_TO_ZERO (out);
v1 = coefficients[1] * in - coefficients[3] * out + v2;
v2 = coefficients[2] * in - coefficients[4] * out;
return out;
}
void IIRFilterOld::processSamples (float* const samples,
const int numSamples) noexcept
{
const SpinLock::ScopedLockType sl (processLock);
if (active)
{
const float c0 = coefficients[0];
const float c1 = coefficients[1];
const float c2 = coefficients[2];
const float c3 = coefficients[3];
const float c4 = coefficients[4];
float lv1 = v1, lv2 = v2;
for (int i = 0; i < numSamples; ++i)
{
const float in = samples[i];
const float out = c0 * in + lv1;
samples[i] = out;
lv1 = c1 * in - c3 * out + lv2;
lv2 = c2 * in - c4 * out;
}
JUCE_SNAP_TO_ZERO (lv1); v1 = lv1;
JUCE_SNAP_TO_ZERO (lv2); v2 = lv2;
}
}
//==============================================================================
void IIRFilterOld::makeLowPass (const double sampleRate,
const double frequency) noexcept
{
jassert (sampleRate > 0);
const double n = 1.0 / tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
setCoefficients (c1,
c1 * 2.0f,
c1,
1.0,
c1 * 2.0 * (1.0 - nSquared),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
}
void IIRFilterOld::makeHighPass (const double sampleRate,
const double frequency) noexcept
{
const double n = tan (double_Pi * frequency / sampleRate);
const double nSquared = n * n;
const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared);
setCoefficients (c1,
c1 * -2.0f,
c1,
1.0,
c1 * 2.0 * (nSquared - 1.0),
c1 * (1.0 - std::sqrt (2.0) * n + nSquared));
}
void IIRFilterOld::makeLowShelf (const double sampleRate,
const double cutOffFrequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
const double A = jmax (0.0f, gainFactor);
const double aminus1 = A - 1.0;
const double aplus1 = A + 1.0;
const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate;
const double coso = std::cos (omega);
const double beta = std::sin (omega) * std::sqrt (A) / Q;
const double aminus1TimesCoso = aminus1 * coso;
setCoefficients (A * (aplus1 - aminus1TimesCoso + beta),
A * 2.0 * (aminus1 - aplus1 * coso),
A * (aplus1 - aminus1TimesCoso - beta),
aplus1 + aminus1TimesCoso + beta,
-2.0 * (aminus1 + aplus1 * coso),
aplus1 + aminus1TimesCoso - beta);
}
void IIRFilterOld::makeHighShelf (const double sampleRate,
const double cutOffFrequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
const double A = jmax (0.0f, gainFactor);
const double aminus1 = A - 1.0;
const double aplus1 = A + 1.0;
const double omega = (double_Pi * 2.0 * jmax (cutOffFrequency, 2.0)) / sampleRate;
const double coso = std::cos (omega);
const double beta = std::sin (omega) * std::sqrt (A) / Q;
const double aminus1TimesCoso = aminus1 * coso;
setCoefficients (A * (aplus1 + aminus1TimesCoso + beta),
A * -2.0 * (aminus1 + aplus1 * coso),
A * (aplus1 + aminus1TimesCoso - beta),
aplus1 - aminus1TimesCoso + beta,
2.0 * (aminus1 - aplus1 * coso),
aplus1 - aminus1TimesCoso - beta);
}
void IIRFilterOld::makeBandPass (const double sampleRate,
const double centreFrequency,
const double Q,
const float gainFactor) noexcept
{
jassert (sampleRate > 0);
jassert (Q > 0);
const double A = jmax (0.0f, gainFactor);
const double omega = (double_Pi * 2.0 * jmax (centreFrequency, 2.0)) / sampleRate;
const double alpha = 0.5 * std::sin (omega) / Q;
const double c2 = -2.0 * std::cos (omega);
const double alphaTimesA = alpha * A;
const double alphaOverA = alpha / A;
setCoefficients (1.0 + alphaTimesA,
c2,
1.0 - alphaTimesA,
1.0 + alphaOverA,
c2,
1.0 - alphaOverA);
}
void IIRFilterOld::makeInactive() noexcept
{
const SpinLock::ScopedLockType sl (processLock);
active = false;
}
//==============================================================================
void IIRFilterOld::copyCoefficientsFrom (const IIRFilterOld& other) noexcept
{
const SpinLock::ScopedLockType sl (processLock);
memcpy (coefficients, other.coefficients, sizeof (coefficients));
active = other.active;
}
//==============================================================================
void IIRFilterOld::setCoefficients (double c1, double c2, double c3,
double c4, double c5, double c6) noexcept
{
const double a = 1.0 / c4;
c1 *= a;
c2 *= a;
c3 *= a;
c5 *= a;
c6 *= a;
const SpinLock::ScopedLockType sl (processLock);
coefficients[0] = (float) c1;
coefficients[1] = (float) c2;
coefficients[2] = (float) c3;
coefficients[3] = (float) c5;
coefficients[4] = (float) c6;
active = true;
}
#undef JUCE_SNAP_TO_ZERO

+ 0
- 148
libs/juce/source/modules/juce_audio_basics/effects/juce_IIRFilterOld.h View File

@@ -1,148 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef __JUCE_IIRFILTER_OLD_JUCEHEADER__
#define __JUCE_IIRFILTER_OLD_JUCEHEADER__
//==============================================================================
/**
An IIR filter that can perform low, high, or band-pass filtering on an
audio signal.
@see IIRFilterAudioSource
*/
class JUCE_API IIRFilterOld
{
public:
//==============================================================================
/** Creates a filter.
Initially the filter is inactive, so will have no effect on samples that
you process with it. Use the appropriate method to turn it into the type
of filter needed.
*/
IIRFilterOld();
/** Creates a copy of another filter. */
IIRFilterOld (const IIRFilterOld& other);
/** Destructor. */
~IIRFilterOld();
//==============================================================================
/** Resets the filter's processing pipeline, ready to start a new stream of data.
Note that this clears the processing state, but the type of filter and
its coefficients aren't changed. To put a filter into an inactive state, use
the makeInactive() method.
*/
void reset() noexcept;
/** Performs the filter operation on the given set of samples.
*/
void processSamples (float* samples,
int numSamples) noexcept;
/** Processes a single sample, without any locking or checking.
Use this if you need fast processing of a single value, but be aware that
this isn't thread-safe in the way that processSamples() is.
*/
float processSingleSampleRaw (float sample) noexcept;
//==============================================================================
/** Sets the filter up to act as a low-pass filter.
*/
void makeLowPass (double sampleRate,
double frequency) noexcept;
/** Sets the filter up to act as a high-pass filter.
*/
void makeHighPass (double sampleRate,
double frequency) noexcept;
//==============================================================================
/** Sets the filter up to act as a low-pass shelf filter with variable Q and gain.
The gain is a scale factor that the low frequencies are multiplied by, so values
greater than 1.0 will boost the low frequencies, values less than 1.0 will
attenuate them.
*/
void makeLowShelf (double sampleRate,
double cutOffFrequency,
double Q,
float gainFactor) noexcept;
/** Sets the filter up to act as a high-pass shelf filter with variable Q and gain.
The gain is a scale factor that the high frequencies are multiplied by, so values
greater than 1.0 will boost the high frequencies, values less than 1.0 will
attenuate them.
*/
void makeHighShelf (double sampleRate,
double cutOffFrequency,
double Q,
float gainFactor) noexcept;
/** Sets the filter up to act as a band pass filter centred around a
frequency, with a variable Q and gain.
The gain is a scale factor that the centre frequencies are multiplied by, so
values greater than 1.0 will boost the centre frequencies, values less than
1.0 will attenuate them.
*/
void makeBandPass (double sampleRate,
double centreFrequency,
double Q,
float gainFactor) noexcept;
/** Clears the filter's coefficients so that it becomes inactive.
*/
void makeInactive() noexcept;
//==============================================================================
/** Makes this filter duplicate the set-up of another one.
*/
void copyCoefficientsFrom (const IIRFilterOld& other) noexcept;
protected:
//==============================================================================
SpinLock processLock;
void setCoefficients (double c1, double c2, double c3,
double c4, double c5, double c6) noexcept;
bool active;
float coefficients[5];
float v1, v2;
// (use the copyCoefficientsFrom() method instead of this operator)
IIRFilterOld& operator= (const IIRFilterOld&);
JUCE_LEAK_DETECTOR (IIRFilterOld)
};
#endif // __JUCE_IIRFILTER_OLD_JUCEHEADER__

+ 8
- 2
libs/juce/source/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp View File

@@ -87,7 +87,10 @@ int LagrangeInterpolator::process (const double actualRatio, const float* in,
if (numOut >= 4)
{
memcpy (lastInputSamples, in + (numOut - 4), 4 * sizeof (float));
const float* end = in + numOut;
for (int i = 0; i < 4; ++i)
lastInputSamples[i] = *--end;
}
else
{
@@ -152,7 +155,10 @@ int LagrangeInterpolator::processAdding (const double actualRatio, const float*
if (numOut >= 4)
{
memcpy (lastInputSamples, in + (numOut - 4), 4 * sizeof (float));
const float* end = in + numOut;
for (int i = 0; i < 4; ++i)
lastInputSamples[i] = *--end;
}
else
{


+ 92
- 43
libs/juce/source/modules/juce_audio_basics/effects/juce_Reverb.h View File

@@ -82,12 +82,13 @@ public:
const float dryScaleFactor = 2.0f;
const float wet = newParams.wetLevel * wetScaleFactor;
wet1 = wet * (newParams.width * 0.5f + 0.5f);
wet2 = wet * (1.0f - newParams.width) * 0.5f;
dry = newParams.dryLevel * dryScaleFactor;
dryGain.setValue (newParams.dryLevel * dryScaleFactor);
wetGain1.setValue (0.5f * wet * (1.0f + newParams.width));
wetGain2.setValue (0.5f * wet * (1.0f - newParams.width));
gain = isFrozen (newParams.freezeMode) ? 0.0f : 0.015f;
parameters = newParams;
shouldUpdateDamping = true;
updateDamping();
}
//==============================================================================
@@ -115,7 +116,12 @@ public:
allPass[1][i].setSize ((intSampleRate * (allPassTunings[i] + stereoSpread)) / 44100);
}
shouldUpdateDamping = true;
const double smoothTime = 0.01;
damping .reset (sampleRate, smoothTime);
feedback.reset (sampleRate, smoothTime);
dryGain .reset (sampleRate, smoothTime);
wetGain1.reset (sampleRate, smoothTime);
wetGain2.reset (sampleRate, smoothTime);
}
/** Clears the reverb's buffers. */
@@ -137,18 +143,18 @@ public:
{
jassert (left != nullptr && right != nullptr);
if (shouldUpdateDamping)
updateDamping();
for (int i = 0; i < numSamples; ++i)
{
const float input = (left[i] + right[i]) * gain;
float outL = 0, outR = 0;
const float damp = damping.getNextValue();
const float feedbck = feedback.getNextValue();
for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel
{
outL += comb[0][j].process (input);
outR += comb[1][j].process (input);
outL += comb[0][j].process (input, damp, feedbck);
outR += comb[1][j].process (input, damp, feedbck);
}
for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
@@ -157,6 +163,10 @@ public:
outR = allPass[1][j].process (outR);
}
const float dry = dryGain.getNextValue();
const float wet1 = wetGain1.getNextValue();
const float wet2 = wetGain2.getNextValue();
left[i] = outL * wet1 + outR * wet2 + left[i] * dry;
right[i] = outR * wet1 + outL * wet2 + right[i] * dry;
}
@@ -167,32 +177,30 @@ public:
{
jassert (samples != nullptr);
if (shouldUpdateDamping)
updateDamping();
for (int i = 0; i < numSamples; ++i)
{
const float input = samples[i] * gain;
float output = 0;
const float damp = damping.getNextValue();
const float feedbck = feedback.getNextValue();
for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel
output += comb[0][j].process (input);
output += comb[0][j].process (input, damp, feedbck);
for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series
output = allPass[0][j].process (output);
const float dry = dryGain.getNextValue();
const float wet1 = wetGain1.getNextValue();
samples[i] = output * wet1 + samples[i] * dry;
}
}
private:
//==============================================================================
Parameters parameters;
volatile bool shouldUpdateDamping;
float gain, wet1, wet2, dry;
inline static bool isFrozen (const float freezeMode) noexcept { return freezeMode >= 0.5f; }
static bool isFrozen (const float freezeMode) noexcept { return freezeMode >= 0.5f; }
void updateDamping() noexcept
{
@@ -200,8 +208,6 @@ private:
const float roomOffset = 0.7f;
const float dampScaleFactor = 0.4f;
shouldUpdateDamping = false;
if (isFrozen (parameters.freezeMode))
setDamping (0.0f, 1.0f);
else
@@ -211,19 +217,15 @@ private:
void setDamping (const float dampingToUse, const float roomSizeToUse) noexcept
{
for (int j = 0; j < numChannels; ++j)
for (int i = numCombs; --i >= 0;)
comb[j][i].setFeedbackAndDamp (roomSizeToUse, dampingToUse);
damping.setValue (dampingToUse);
feedback.setValue (roomSizeToUse);
}
//==============================================================================
class CombFilter
{
public:
CombFilter() noexcept
: bufferSize (0), bufferIndex (0),
feedback (0), last (0), damp1 (0), damp2 (0)
{}
CombFilter() noexcept : bufferSize (0), bufferIndex (0), last (0) {}
void setSize (const int size)
{
@@ -243,22 +245,15 @@ private:
buffer.clear ((size_t) bufferSize);
}
void setFeedbackAndDamp (const float f, const float d) noexcept
{
damp1 = d;
damp2 = 1.0f - d;
feedback = f;
}
inline float process (const float input) noexcept
float process (const float input, const float damp, const float feedbackLevel) noexcept
{
const float output = buffer [bufferIndex];
last = (output * damp2) + (last * damp1);
const float output = buffer[bufferIndex];
last = (output * (1.0f - damp)) + (last * damp);
JUCE_UNDENORMALISE (last);
float temp = input + (last * feedback);
float temp = input + (last * feedbackLevel);
JUCE_UNDENORMALISE (temp);
buffer [bufferIndex] = temp;
buffer[bufferIndex] = temp;
bufferIndex = (bufferIndex + 1) % bufferSize;
return output;
}
@@ -266,7 +261,7 @@ private:
private:
HeapBlock<float> buffer;
int bufferSize, bufferIndex;
float feedback, last, damp1, damp2;
float last;
JUCE_DECLARE_NON_COPYABLE (CombFilter)
};
@@ -294,7 +289,7 @@ private:
buffer.clear ((size_t) bufferSize);
}
inline float process (const float input) noexcept
float process (const float input) noexcept
{
const float bufferedValue = buffer [bufferIndex];
float temp = input + (bufferedValue * 0.5f);
@@ -311,11 +306,65 @@ private:
JUCE_DECLARE_NON_COPYABLE (AllPassFilter)
};
//==============================================================================
class LinearSmoothedValue
{
public:
LinearSmoothedValue() noexcept
: currentValue (0), target (0), step (0), countdown (0), stepsToTarget (0)
{
}
void reset (double sampleRate, double fadeLengthSeconds) noexcept
{
jassert (sampleRate > 0 && fadeLengthSeconds >= 0);
stepsToTarget = (int) std::floor (fadeLengthSeconds * sampleRate);
currentValue = target;
countdown = 0;
}
void setValue (float newValue) noexcept
{
if (target != newValue)
{
target = newValue;
countdown = stepsToTarget;
if (countdown <= 0)
currentValue = target;
else
step = (target - currentValue) / countdown;
}
}
float getNextValue() noexcept
{
if (countdown <= 0)
return target;
--countdown;
currentValue += step;
return currentValue;
}
private:
float currentValue, target, step;
int countdown, stepsToTarget;
JUCE_DECLARE_NON_COPYABLE (LinearSmoothedValue)
};
//==============================================================================
enum { numCombs = 8, numAllPasses = 4, numChannels = 2 };
Parameters parameters;
float gain;
CombFilter comb [numChannels][numCombs];
AllPassFilter allPass [numChannels][numAllPasses];
LinearSmoothedValue damping, feedback, dryGain, wetGain1, wetGain2;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Reverb)
};


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/juce_audio_basics.cpp View File

@@ -76,8 +76,8 @@ namespace juce
#include "buffers/juce_AudioSampleBuffer.cpp"
#include "buffers/juce_FloatVectorOperations.cpp"
#include "effects/juce_IIRFilter.cpp"
#include "effects/juce_IIRFilterOld.cpp"
#include "effects/juce_LagrangeInterpolator.cpp"
#include "effects/juce_FFT.cpp"
#include "midi/juce_MidiBuffer.cpp"
#include "midi/juce_MidiFile.cpp"
#include "midi/juce_MidiKeyboardState.cpp"


+ 4
- 1
libs/juce/source/modules/juce_audio_basics/juce_audio_basics.h View File

@@ -31,13 +31,16 @@
namespace juce
{
#undef Complex // apparently some C libraries actually define these symbols (!)
#undef Factor
#include "buffers/juce_AudioDataConverters.h"
#include "buffers/juce_AudioSampleBuffer.h"
#include "buffers/juce_FloatVectorOperations.h"
#include "effects/juce_Decibels.h"
#include "effects/juce_IIRFilter.h"
#include "effects/juce_IIRFilterOld.h"
#include "effects/juce_LagrangeInterpolator.h"
#include "effects/juce_FFT.h"
#include "effects/juce_Reverb.h"
#include "midi/juce_MidiMessage.h"
#include "midi/juce_MidiBuffer.h"


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_audio_basics",
"name": "JUCE audio and midi data classes",
"version": "3.0.8",
"version": "3.1.1",
"description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 15
- 21
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp View File

@@ -276,14 +276,11 @@ void MidiMessageSequence::deleteSysExMessages()
}
//==============================================================================
void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber,
const double time,
OwnedArray<MidiMessage>& dest)
void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber, const double time, Array<MidiMessage>& dest)
{
bool doneProg = false;
bool donePitchWheel = false;
Array<int> doneControllers;
doneControllers.ensureStorageAllocated (32);
bool doneControllers[128] = { 0 };
for (int i = list.size(); --i >= 0;)
{
@@ -291,28 +288,25 @@ void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumbe
if (mm.isForChannel (channelNumber) && mm.getTimeStamp() <= time)
{
if (mm.isProgramChange())
if (mm.isProgramChange() && ! doneProg)
{
if (! doneProg)
{
dest.add (new MidiMessage (mm, 0.0));
doneProg = true;
}
doneProg = true;
dest.add (MidiMessage (mm, 0.0));
}
else if (mm.isController())
else if (mm.isPitchWheel() && ! donePitchWheel)
{
if (! doneControllers.contains (mm.getControllerNumber()))
{
dest.add (new MidiMessage (mm, 0.0));
doneControllers.add (mm.getControllerNumber());
}
donePitchWheel = true;
dest.add (MidiMessage (mm, 0.0));
}
else if (mm.isPitchWheel())
else if (mm.isController())
{
if (! donePitchWheel)
const int controllerNumber = mm.getControllerNumber();
jassert (isPositiveAndBelow (controllerNumber, 128));
if (! doneControllers[controllerNumber])
{
dest.add (new MidiMessage (mm, 0.0));
donePitchWheel = true;
doneControllers[controllerNumber] = true;
dest.add (MidiMessage (mm, 0.0));
}
}
}


+ 1
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h View File

@@ -247,7 +247,7 @@ public:
state at the required time.
*/
void createControllerUpdatesForTime (int channelNumber, double time,
OwnedArray<MidiMessage>& resultMessages);
Array<MidiMessage>& resultMessages);
//==============================================================================
/** Swaps this sequence with another one. */


+ 9
- 7
libs/juce/source/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp View File

@@ -24,14 +24,14 @@
ResamplingAudioSource::ResamplingAudioSource (AudioSource* const inputSource,
const bool deleteInputWhenDeleted,
const int numChannels_)
const int channels)
: input (inputSource, deleteInputWhenDeleted),
ratio (1.0),
lastRatio (1.0),
bufferPos (0),
sampsInBuffer (0),
subSampleOffset (0),
numChannels (numChannels_)
numChannels (channels)
{
jassert (input != nullptr);
zeromem (coefficients, sizeof (coefficients));
@@ -51,9 +51,10 @@ void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, double s
{
const SpinLock::ScopedLockType sl (ratioLock);
input->prepareToPlay (samplesPerBlockExpected, sampleRate);
const int scaledBlockSize = roundToInt (samplesPerBlockExpected * ratio);
input->prepareToPlay (scaledBlockSize, sampleRate * ratio);
buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32);
buffer.setSize (numChannels, scaledBlockSize + 32);
filterStates.calloc ((size_t) numChannels);
srcBuffers.calloc ((size_t) numChannels);
@@ -93,7 +94,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
lastRatio = localRatio;
}
const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 2;
const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 3;
int bufferSize = buffer.getNumSamples();
@@ -138,8 +139,11 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
}
int nextPos = (bufferPos + 1) % bufferSize;
for (int m = info.numSamples; --m >= 0;)
{
jassert (sampsInBuffer > 0 && nextPos != endOfBufferPos);
const float alpha = (float) subSampleOffset;
for (int channel = 0; channel < channelsToProcess; ++channel)
@@ -148,8 +152,6 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
subSampleOffset += localRatio;
jassert (sampsInBuffer > 0);
while (subSampleOffset >= 1.0)
{
if (++bufferPos >= bufferSize)


+ 21
- 13
libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp View File

@@ -29,6 +29,7 @@ SynthesiserSound::~SynthesiserSound() {}
SynthesiserVoice::SynthesiserVoice()
: currentSampleRate (44100.0),
currentlyPlayingNote (-1),
currentPlayingMidiChannel (0),
noteOnTime (0),
keyIsDown (false),
sostenutoPedalDown (false)
@@ -41,8 +42,7 @@ SynthesiserVoice::~SynthesiserVoice()
bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const
{
return currentlyPlayingSound != nullptr
&& currentlyPlayingSound->appliesToChannel (midiChannel);
return currentPlayingMidiChannel == midiChannel;
}
void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate)
@@ -50,10 +50,16 @@ void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate)
currentSampleRate = newRate;
}
bool SynthesiserVoice::isVoiceActive() const
{
return getCurrentlyPlayingNote() >= 0;
}
void SynthesiserVoice::clearCurrentNote()
{
currentlyPlayingNote = -1;
currentlyPlayingSound = nullptr;
currentPlayingMidiChannel = 0;
}
void SynthesiserVoice::aftertouchChanged (int) {}
@@ -253,14 +259,15 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice,
if (voice->currentlyPlayingSound != nullptr)
voice->stopNote (0.0f, false);
voice->startNote (midiNoteNumber, velocity, sound,
lastPitchWheelValues [midiChannel - 1]);
voice->currentlyPlayingNote = midiNoteNumber;
voice->currentPlayingMidiChannel = midiChannel;
voice->noteOnTime = ++lastNoteOnCounter;
voice->currentlyPlayingSound = sound;
voice->keyIsDown = true;
voice->sostenutoPedalDown = false;
voice->startNote (midiNoteNumber, velocity, sound,
lastPitchWheelValues [midiChannel - 1]);
}
}
@@ -285,7 +292,8 @@ void Synthesiser::noteOff (const int midiChannel,
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() == midiNoteNumber)
if (voice->getCurrentlyPlayingNote() == midiNoteNumber
&& voice->isPlayingChannel (midiChannel))
{
if (SynthesiserSound* const sound = voice->getCurrentlyPlayingSound())
{
@@ -426,7 +434,7 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->getCurrentlyPlayingNote() < 0 && voice->canPlaySound (soundToPlay))
if ((! voice->isVoiceActive()) && voice->canPlaySound (soundToPlay))
return voice;
}
@@ -440,7 +448,7 @@ struct VoiceAgeSorter
{
static int compareElements (SynthesiserVoice* v1, SynthesiserVoice* v2) noexcept
{
return v1->wasStartedBefore (*v2) ? 1 : (v2->wasStartedBefore (*v1) ? -1 : 0);
return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0);
}
};
@@ -473,10 +481,10 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
}
}
jassert (bottom != nullptr && top != nullptr);
const int stealableVoiceRange = usableVoices.size() - 6;
// The oldest note that's playing with the target pitch playing is ideal..
for (int i = 0; i < usableVoices.size(); ++i)
for (int i = 0; i < stealableVoiceRange; ++i)
{
SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
@@ -485,7 +493,7 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
}
// ..otherwise, look for the oldest note that isn't the top or bottom note..
for (int i = 0; i < usableVoices.size(); ++i)
for (int i = 0; i < stealableVoiceRange; ++i)
{
SynthesiserVoice* const voice = usableVoices.getUnchecked (i);
@@ -493,6 +501,6 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
return voice;
}
// ..otherwise, there's only one or two voices to choose from - we'll return the top one..
return top;
// ..otherwise, there's only one or two voices to choose from - we'll return the oldest one..
return usableVoices.getFirst();
}

+ 13
- 7
libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h View File

@@ -140,6 +140,12 @@ public:
*/
virtual void stopNote (float velocity, bool allowTailOff) = 0;
/** Returns true if this voice is currently busy playing a sound.
By default this just checks the getCurrentlyPlayingNote() value, but can
be overridden for more advanced checking.
*/
virtual bool isVoiceActive() const;
/** 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.
*/
@@ -185,17 +191,17 @@ public:
*/
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;
virtual bool isPlayingChannel (int midiChannel) const;
/** 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 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
@@ -230,7 +236,7 @@ private:
friend class Synthesiser;
double currentSampleRate;
int currentlyPlayingNote;
int currentlyPlayingNote, currentPlayingMidiChannel;
uint32 noteOnTime;
SynthesiserSound::Ptr currentlyPlayingSound;
bool keyIsDown, sostenutoPedalDown;


+ 18
- 13
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp View File

@@ -92,7 +92,6 @@ AudioDeviceManager::AudioDeviceManager()
: numInputChansNeeded (0),
numOutputChansNeeded (2),
listNeedsScanning (true),
useInputNames (false),
inputLevel (0),
testSoundPosition (0),
cpuUsageMs (0),
@@ -154,13 +153,14 @@ static void addIfNotNull (OwnedArray<AudioIODeviceType>& list, AudioIODeviceType
void AudioDeviceManager::createAudioDeviceTypes (OwnedArray<AudioIODeviceType>& list)
{
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (false));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (true));
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_iOSAudio());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ALSA());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_JACK());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_OpenSLES());
addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_Android());
}
@@ -177,6 +177,17 @@ void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType)
}
}
static bool deviceListContains (AudioIODeviceType* type, bool isInput, const String& name)
{
StringArray devices (type->getDeviceNames (isInput));
for (int i = devices.size(); --i >= 0;)
if (devices[i].trim().equalsIgnoreCase (name.trim()))
return true;
return false;
}
//==============================================================================
String AudioDeviceManager::initialise (const int numInputChannelsNeeded,
const int numOutputChannelsNeeded,
@@ -363,8 +374,8 @@ AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const
{
AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i);
if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true))
|| (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true)))
if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName))
|| (outputName.isNotEmpty() && deviceListContains (type, false, outputName)))
{
return type;
}
@@ -458,17 +469,11 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
deleteCurrentDevice();
scanDevicesIfNeeded();
if (newOutputDeviceName.isNotEmpty()
&& ! type->getDeviceNames (false).contains (newOutputDeviceName))
{
if (newOutputDeviceName.isNotEmpty() && ! deviceListContains (type, false, newOutputDeviceName))
return "No such device: " + newOutputDeviceName;
}
if (newInputDeviceName.isNotEmpty()
&& ! type->getDeviceNames (true).contains (newInputDeviceName))
{
if (newInputDeviceName.isNotEmpty() && ! deviceListContains (type, true, newInputDeviceName))
return "No such device: " + newInputDeviceName;
}
currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName);


+ 0
- 1
libs/juce/source/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h View File

@@ -450,7 +450,6 @@ private:
BigInteger inputChannels, outputChannels;
ScopedPointer<XmlElement> lastExplicitSettings;
mutable bool listNeedsScanning;
bool useInputNames;
Atomic<int> inputLevelMeasurementEnabledCount;
double inputLevel;
ScopedPointer<AudioSampleBuffer> testSound;