Browse Source

Global: Avoid floating-point equality checks where possible

v7.0.9
reuk 2 years ago
parent
commit
28414a6af8
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
100 changed files with 475 additions and 404 deletions
  1. +1
    -1
      examples/Audio/AudioPlaybackDemo.h
  2. +3
    -3
      examples/Audio/AudioSynthesiserDemo.h
  3. +4
    -4
      examples/Audio/MPEDemo.h
  4. +1
    -1
      examples/DSP/FIRFilterDemo.h
  5. +1
    -1
      examples/DSP/IIRFilterDemo.h
  6. +1
    -1
      examples/DSP/OverdriveDemo.h
  7. +1
    -1
      examples/DSP/SIMDRegisterDemo.h
  8. +1
    -1
      examples/DSP/StateVariableFilterDemo.h
  9. +1
    -1
      examples/GUI/VideoDemo.h
  10. +3
    -3
      examples/Plugins/AudioPluginDemo.h
  11. +1
    -1
      examples/Plugins/DSPModulePluginDemo.h
  12. +2
    -2
      examples/Plugins/SamplerPluginDemo.h
  13. +3
    -3
      extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp
  14. +2
    -2
      extras/Build/CMake/JUCEHelperTargets.cmake
  15. +1
    -1
      extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h
  16. +2
    -2
      extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h
  17. +1
    -1
      extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp
  18. +1
    -1
      extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementRoundedRectangle.h
  19. +1
    -1
      extras/Projucer/Source/ComponentEditor/Properties/jucer_FontPropertyComponent.h
  20. +1
    -1
      extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp
  21. +6
    -4
      extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h
  22. +1
    -1
      extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp
  23. +1
    -1
      extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h
  24. +19
    -4
      extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h
  25. +2
    -2
      modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp
  26. +1
    -1
      modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.cpp
  27. +6
    -6
      modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h
  28. +1
    -1
      modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  29. +3
    -3
      modules/juce_audio_basics/midi/juce_MidiFile.cpp
  30. +2
    -2
      modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp
  31. +2
    -2
      modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp
  32. +4
    -4
      modules/juce_audio_basics/native/juce_CoreAudioLayouts_mac.h
  33. +1
    -1
      modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp
  34. +2
    -2
      modules/juce_audio_basics/sources/juce_MemoryAudioSource.cpp
  35. +1
    -1
      modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp
  36. +1
    -1
      modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp
  37. +2
    -2
      modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  38. +1
    -1
      modules/juce_audio_basics/utilities/juce_Interpolators.h
  39. +5
    -3
      modules/juce_audio_basics/utilities/juce_SmoothedValue.h
  40. +1
    -1
      modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp
  41. +2
    -2
      modules/juce_audio_devices/native/juce_Audio_ios.cpp
  42. +4
    -4
      modules/juce_audio_devices/native/juce_CoreAudio_mac.cpp
  43. +7
    -6
      modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp
  44. +12
    -11
      modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp
  45. +1
    -1
      modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h
  46. +9
    -8
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp
  47. +5
    -4
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp
  48. +14
    -13
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm
  49. +15
    -14
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm
  50. +2
    -2
      modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm
  51. +2
    -2
      modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp
  52. +4
    -4
      modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp
  53. +8
    -8
      modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp
  54. +2
    -2
      modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  55. +1
    -1
      modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp
  56. +1
    -1
      modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp
  57. +3
    -2
      modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp
  58. +31
    -30
      modules/juce_audio_processors/format_types/juce_VST3Headers.h
  59. +3
    -3
      modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  60. +3
    -3
      modules/juce_audio_processors/format_types/juce_VST3PluginFormat_test.cpp
  61. +4
    -4
      modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  62. +1
    -1
      modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
  63. +1
    -1
      modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp
  64. +2
    -2
      modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp
  65. +7
    -11
      modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
  66. +1
    -1
      modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp
  67. +1
    -1
      modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp
  68. +2
    -2
      modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp
  69. +5
    -5
      modules/juce_audio_utils/gui/juce_KeyboardComponentBase.cpp
  70. +7
    -6
      modules/juce_box2d/juce_box2d.cpp
  71. +4
    -3
      modules/juce_box2d/juce_box2d.h
  72. +1
    -1
      modules/juce_core/containers/juce_Array.h
  73. +1
    -1
      modules/juce_core/containers/juce_ArrayBase.h
  74. +2
    -2
      modules/juce_core/containers/juce_Variant.cpp
  75. +4
    -4
      modules/juce_core/javascript/juce_Javascript.cpp
  76. +24
    -11
      modules/juce_core/maths/juce_MathsFunctions.h
  77. +4
    -4
      modules/juce_core/maths/juce_NormalisableRange.h
  78. +1
    -1
      modules/juce_core/maths/juce_Random.cpp
  79. +8
    -3
      modules/juce_core/maths/juce_Range.h
  80. +2
    -2
      modules/juce_core/streams/juce_MemoryInputStream.cpp
  81. +22
    -1
      modules/juce_core/system/juce_CompilerWarnings.h
  82. +1
    -1
      modules/juce_core/text/juce_CharacterFunctions.cpp
  83. +7
    -7
      modules/juce_core/text/juce_String.cpp
  84. +1
    -1
      modules/juce_core/text/juce_String.h
  85. +7
    -7
      modules/juce_core/threads/juce_Thread.cpp
  86. +10
    -2
      modules/juce_core/time/juce_RelativeTime.cpp
  87. +2
    -2
      modules/juce_core/unit_tests/juce_UnitTest.h
  88. +1
    -1
      modules/juce_data_structures/values/juce_CachedValue.h
  89. +88
    -85
      modules/juce_dsp/containers/juce_AudioBlock_test.cpp
  90. +5
    -12
      modules/juce_dsp/containers/juce_SIMDRegister_test.cpp
  91. +5
    -6
      modules/juce_dsp/filter_design/juce_FilterDesign.cpp
  92. +1
    -1
      modules/juce_dsp/frequency/juce_Convolution.cpp
  93. +2
    -2
      modules/juce_dsp/frequency/juce_Convolution_test.cpp
  94. +1
    -1
      modules/juce_dsp/maths/juce_LogRampedValue.h
  95. +5
    -5
      modules/juce_dsp/maths/juce_Matrix.cpp
  96. +1
    -1
      modules/juce_dsp/processors/juce_DelayLine.h
  97. +3
    -2
      modules/juce_dsp/processors/juce_IIRFilter_Impl.h
  98. +1
    -1
      modules/juce_dsp/processors/juce_Oversampling.cpp
  99. +6
    -3
      modules/juce_dsp/processors/juce_ProcessContext.h
  100. +1
    -1
      modules/juce_dsp/processors/juce_ProcessorChain_test.cpp

+ 1
- 1
examples/Audio/AudioPlaybackDemo.h View File

@@ -188,7 +188,7 @@ public:
if (canMoveTransport()) if (canMoveTransport())
setRange ({ newStart, newStart + visibleRange.getLength() }); setRange ({ newStart, newStart + visibleRange.getLength() });
if (wheel.deltaY != 0.0f)
if (! approximatelyEqual (wheel.deltaY, 0.0f))
zoomSlider.setValue (zoomSlider.getValue() - wheel.deltaY); zoomSlider.setValue (zoomSlider.getValue() - wheel.deltaY);
repaint(); repaint();


+ 3
- 3
examples/Audio/AudioSynthesiserDemo.h View File

@@ -88,8 +88,8 @@ struct SineWaveVoice : public SynthesiserVoice
// start a tail-off by setting this flag. The render callback will pick up on // start a tail-off by setting this flag. The render callback will pick up on
// this and do a fade out, calling clearCurrentNote() when it's finished. // this and do a fade out, calling clearCurrentNote() when it's finished.
if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
tailOff = 1.0; // stopNote method could be called more than once.
if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the
tailOff = 1.0; // stopNote method could be called more than once.
} }
else else
{ {
@@ -104,7 +104,7 @@ struct SineWaveVoice : public SynthesiserVoice
void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
{ {
if (angleDelta != 0.0)
if (! approximatelyEqual (angleDelta, 0.0))
{ {
if (tailOff > 0.0) if (tailOff > 0.0)
{ {


+ 4
- 4
examples/Audio/MPEDemo.h View File

@@ -499,8 +499,8 @@ public:
// start a tail-off by setting this flag. The render callback will pick up on // start a tail-off by setting this flag. The render callback will pick up on
// this and do a fade out, calling clearCurrentNote() when it's finished. // this and do a fade out, calling clearCurrentNote() when it's finished.
if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
// stopNote method could be called more than once.
if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the
// stopNote method could be called more than once.
tailOff = 1.0; tailOff = 1.0;
} }
else else
@@ -530,7 +530,7 @@ public:
void setCurrentSampleRate (double newRate) override void setCurrentSampleRate (double newRate) override
{ {
if (currentSampleRate != newRate)
if (! approximatelyEqual (currentSampleRate, newRate))
{ {
noteStopped (false); noteStopped (false);
currentSampleRate = newRate; currentSampleRate = newRate;
@@ -546,7 +546,7 @@ public:
int startSample, int startSample,
int numSamples) override int numSamples) override
{ {
if (phaseDelta != 0.0)
if (! approximatelyEqual (phaseDelta, 0.0))
{ {
if (tailOff > 0.0) if (tailOff > 0.0)
{ {


+ 1
- 1
examples/DSP/FIRFilterDemo.h View File

@@ -77,7 +77,7 @@ struct FIRFilterDemoDSP
void updateParameters() void updateParameters()
{ {
if (sampleRate != 0.0)
if (! approximatelyEqual (sampleRate, 0.0))
{ {
auto cutoff = static_cast<float> (cutoffParam.getCurrentValue()); auto cutoff = static_cast<float> (cutoffParam.getCurrentValue());
auto windowingMethod = static_cast<WindowingFunction<float>::WindowingMethod> (typeParam.getCurrentSelectedID() - 1); auto windowingMethod = static_cast<WindowingFunction<float>::WindowingMethod> (typeParam.getCurrentSelectedID() - 1);


+ 1
- 1
examples/DSP/IIRFilterDemo.h View File

@@ -76,7 +76,7 @@ struct IIRFilterDemoDSP
void updateParameters() void updateParameters()
{ {
if (sampleRate != 0.0)
if (! approximatelyEqual (sampleRate, 0.0))
{ {
auto cutoff = static_cast<float> (cutoffParam.getCurrentValue()); auto cutoff = static_cast<float> (cutoffParam.getCurrentValue());
auto qVal = static_cast<float> (qParam.getCurrentValue()); auto qVal = static_cast<float> (qParam.getCurrentValue());


+ 1
- 1
examples/DSP/OverdriveDemo.h View File

@@ -90,7 +90,7 @@ struct OverdriveDemoDSP
void updateParameters() void updateParameters()
{ {
if (sampleRate != 0.0)
if (! approximatelyEqual (sampleRate, 0.0))
{ {
overdrive.get<0>().setGainDecibels (static_cast<float> (inGainParam.getCurrentValue())); overdrive.get<0>().setGainDecibels (static_cast<float> (inGainParam.getCurrentValue()));
overdrive.get<4>().setGainDecibels (static_cast<float> (outGainParam.getCurrentValue())); overdrive.get<4>().setGainDecibels (static_cast<float> (outGainParam.getCurrentValue()));


+ 1
- 1
examples/DSP/SIMDRegisterDemo.h View File

@@ -124,7 +124,7 @@ struct SIMDRegisterDemoDSP
void updateParameters() void updateParameters()
{ {
if (sampleRate != 0.0)
if (! approximatelyEqual (sampleRate, 0.0))
{ {
auto cutoff = static_cast<float> (cutoffParam.getCurrentValue()); auto cutoff = static_cast<float> (cutoffParam.getCurrentValue());
auto qVal = static_cast<float> (qParam.getCurrentValue()); auto qVal = static_cast<float> (qParam.getCurrentValue());


+ 1
- 1
examples/DSP/StateVariableFilterDemo.h View File

@@ -74,7 +74,7 @@ struct StateVariableFilterDemoDSP
void updateParameters() void updateParameters()
{ {
if (sampleRate != 0.0)
if (! approximatelyEqual (sampleRate, 0.0))
{ {
filter.setCutoffFrequency (static_cast<float> (cutoffParam.getCurrentValue())); filter.setCutoffFrequency (static_cast<float> (cutoffParam.getCurrentValue()));
filter.setResonance (static_cast<float> (qParam.getCurrentValue())); filter.setResonance (static_cast<float> (qParam.getCurrentValue()));


+ 1
- 1
examples/GUI/VideoDemo.h View File

@@ -630,7 +630,7 @@ private:
currentPositionLabel.setText (getPositionString (position, duration), sendNotification); currentPositionLabel.setText (getPositionString (position, duration), sendNotification);
if (! positionSliderDragging) if (! positionSliderDragging)
positionSlider.setValue (duration != 0 ? (position / duration) : 0.0, dontSendNotification);
positionSlider.setValue (approximatelyEqual (duration, 0.0) ? 0.0 : (position / duration), dontSendNotification);
} }
void seekVideoToStart() void seekVideoToStart()


+ 3
- 3
examples/Plugins/AudioPluginDemo.h View File

@@ -97,8 +97,8 @@ public:
// start a tail-off by setting this flag. The render callback will pick up on // start a tail-off by setting this flag. The render callback will pick up on
// this and do a fade out, calling clearCurrentNote() when it's finished. // this and do a fade out, calling clearCurrentNote() when it's finished.
if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
// stopNote method could be called more than once.
if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the
// stopNote method could be called more than once.
tailOff = 1.0; tailOff = 1.0;
} }
else else
@@ -122,7 +122,7 @@ public:
void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
{ {
if (angleDelta != 0.0)
if (! approximatelyEqual (angleDelta, 0.0))
{ {
if (tailOff > 0.0) if (tailOff > 0.0)
{ {


+ 1
- 1
examples/Plugins/DSPModulePluginDemo.h View File

@@ -969,7 +969,7 @@ private:
//============================================================================== //==============================================================================
static String getPanningTextForValue (float value) static String getPanningTextForValue (float value)
{ {
if (value == 0.5f)
if (approximatelyEqual (value, 0.5f))
return "center"; return "center";
if (value < 0.5f) if (value < 0.5f)


+ 2
- 2
examples/Plugins/SamplerPluginDemo.h View File

@@ -291,7 +291,7 @@ public:
{ {
jassert (currentlyPlayingNote.keyState == MPENote::off); jassert (currentlyPlayingNote.keyState == MPENote::off);
if (allowTailOff && tailOff == 0.0)
if (allowTailOff && approximatelyEqual (tailOff, 0.0))
tailOff = 1.0; tailOff = 1.0;
else else
stopNote(); stopNote();
@@ -422,7 +422,7 @@ private:
bool isTailingOff() const bool isTailingOff() const
{ {
return tailOff != 0.0;
return ! approximatelyEqual (tailOff, 0.0);
} }
void stopNote() void stopNote()


+ 3
- 3
extras/AudioPluginHost/Source/Plugins/InternalPlugins.cpp View File

@@ -262,8 +262,8 @@ private:
// start a tail-off by setting this flag. The render callback will pick up on // start a tail-off by setting this flag. The render callback will pick up on
// this and do a fade out, calling clearCurrentNote() when it's finished. // this and do a fade out, calling clearCurrentNote() when it's finished.
if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
// stopNote method could be called more than once.
if (approximatelyEqual (tailOff, 0.0)) // we only need to begin a tail-off if it's not already doing so - the
// stopNote method could be called more than once.
tailOff = 1.0; tailOff = 1.0;
} }
else else
@@ -287,7 +287,7 @@ private:
void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
{ {
if (angleDelta != 0.0)
if (! approximatelyEqual (angleDelta, 0.0))
{ {
if (tailOff > 0) if (tailOff > 0)
{ {


+ 2
- 2
extras/Build/CMake/JUCEHelperTargets.cmake View File

@@ -34,7 +34,7 @@ elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR (CMAKE_CXX_COMPILER_ID STREQU
-Wsign-conversion -Wbool-conversion -Wextra-semi -Wunreachable-code -Wsign-conversion -Wbool-conversion -Wextra-semi -Wunreachable-code
-Wcast-align -Wshift-sign-overflow -Wmissing-prototypes -Wcast-align -Wshift-sign-overflow -Wmissing-prototypes
-Wnullable-to-nonnull-conversion -Wno-ignored-qualifiers -Wswitch-enum -Wnullable-to-nonnull-conversion -Wno-ignored-qualifiers -Wswitch-enum
-Wpedantic -Wdeprecated
-Wpedantic -Wdeprecated -Wfloat-equal
$<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:OBJCXX>>: $<$<OR:$<COMPILE_LANGUAGE:CXX>,$<COMPILE_LANGUAGE:OBJCXX>>:
-Wzero-as-null-pointer-constant -Wunused-private-field -Wzero-as-null-pointer-constant -Wunused-private-field
-Woverloaded-virtual -Wreorder -Woverloaded-virtual -Wreorder
@@ -47,7 +47,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-Wunused-parameter -Wsign-compare -Wsign-conversion -Wunreachable-code -Wunused-parameter -Wsign-compare -Wsign-conversion -Wunreachable-code
-Wcast-align -Wno-implicit-fallthrough -Wno-maybe-uninitialized -Wcast-align -Wno-implicit-fallthrough -Wno-maybe-uninitialized
-Wno-ignored-qualifiers -Wswitch-enum -Wno-ignored-qualifiers -Wswitch-enum
-Wredundant-decls -Wno-strict-overflow -Wshadow
-Wredundant-decls -Wno-strict-overflow -Wshadow -Wfloat-equal
$<$<COMPILE_LANGUAGE:CXX>: $<$<COMPILE_LANGUAGE:CXX>:
-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant>) -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant>)
endif() endif()


+ 1
- 1
extras/Projucer/Source/ComponentEditor/Components/jucer_SliderHandler.h View File

@@ -145,7 +145,7 @@ struct SliderHandler : public ComponentTypeHandler
if (needsSliderListener (component)) if (needsSliderListener (component))
r << memberVariableName << "->addListener (this);\n"; r << memberVariableName << "->addListener (this);\n";
if (s->getSkewFactor() != 1.0)
if (! approximatelyEqual (s->getSkewFactor(), 1.0))
r << memberVariableName << "->setSkewFactor (" << s->getSkewFactor() << ");\n"; r << memberVariableName << "->setSkewFactor (" << s->getSkewFactor() << ");\n";
r << '\n'; r << '\n';


+ 2
- 2
extras/Projucer/Source/ComponentEditor/PaintElements/jucer_FillType.h View File

@@ -77,7 +77,7 @@ public:
&& gradPos1 == other.gradPos1 && gradPos1 == other.gradPos1
&& gradPos2 == other.gradPos2 && gradPos2 == other.gradPos2
&& imageResourceName == other.imageResourceName && imageResourceName == other.imageResourceName
&& imageOpacity == other.imageOpacity
&& approximatelyEqual (imageOpacity, other.imageOpacity)
&& imageAnchor == other.imageAnchor; && imageAnchor == other.imageAnchor;
} }
@@ -320,7 +320,7 @@ public:
return gradCol1.isTransparent() && gradCol2.isTransparent(); return gradCol1.isTransparent() && gradCol2.isTransparent();
case imageBrush: case imageBrush:
return imageOpacity == 0.0;
return approximatelyEqual (imageOpacity, 0.0);
default: default:
jassertfalse; jassertfalse;


+ 1
- 1
extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementImage.cpp View File

@@ -244,7 +244,7 @@ void PaintElementImage::setOpacity (double newOpacity, const bool undoable)
{ {
newOpacity = jlimit (0.0, 1.0, newOpacity); newOpacity = jlimit (0.0, 1.0, newOpacity);
if (opacity != newOpacity)
if (! approximatelyEqual (opacity, newOpacity))
{ {
if (undoable) if (undoable)
{ {


+ 1
- 1
extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementRoundedRectangle.h View File

@@ -95,7 +95,7 @@ public:
void setCornerSize (const double newSize, const bool undoable) void setCornerSize (const double newSize, const bool undoable)
{ {
if (newSize != cornerSize)
if (! approximatelyEqual (newSize, cornerSize))
{ {
if (undoable) if (undoable)
{ {


+ 1
- 1
extras/Projucer/Source/ComponentEditor/Properties/jucer_FontPropertyComponent.h View File

@@ -132,7 +132,7 @@ public:
s << getFontStyleCode (font) s << getFontStyleCode (font)
<< ")"; << ")";
if (font.getExtraKerningFactor() != 0.0f)
if (! approximatelyEqual (font.getExtraKerningFactor(), 0.0f))
s << ".withExtraKerningFactor (" s << ".withExtraKerningFactor ("
<< CodeHelpers::floatLiteral (font.getExtraKerningFactor(), 3) << CodeHelpers::floatLiteral (font.getExtraKerningFactor(), 3)
<< ")"; << ")";


+ 1
- 1
extras/Projucer/Source/ComponentEditor/UI/jucer_PaintRoutineEditor.cpp View File

@@ -184,7 +184,7 @@ void PaintRoutineEditor::refreshAllElements()
repaint(); repaint();
} }
if (componentOverlayOpacity != document.getComponentOverlayOpacity())
if (! approximatelyEqual (componentOverlayOpacity, document.getComponentOverlayOpacity()))
{ {
componentOverlay = Image(); componentOverlay = Image();
componentOverlayOpacity = document.getComponentOverlayOpacity(); componentOverlayOpacity = document.getComponentOverlayOpacity();


+ 6
- 4
extras/Projucer/Source/ComponentEditor/UI/jucer_RelativePositionedRectangle.h View File

@@ -420,10 +420,12 @@ public:
/** Compares two objects. */ /** Compares two objects. */
bool operator== (const PositionedRectangle& other) const noexcept bool operator== (const PositionedRectangle& other) const noexcept
{ {
return x == other.x && y == other.y
&& w == other.w && h == other.h
&& xMode == other.xMode && yMode == other.yMode
&& wMode == other.wMode && hMode == other.hMode;
const auto tie = [] (const PositionedRectangle& r)
{
return std::tie (r.x, r.y, r.xMode, r.yMode, r.wMode, r.hMode);
};
return tie (*this) == tie (other);
} }
/** Compares two objects. */ /** Compares two objects. */


+ 1
- 1
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp View File

@@ -245,7 +245,7 @@ void JucerDocument::setSnappingGrid (const int numPixels, const bool active, con
void JucerDocument::setComponentOverlayOpacity (const float alpha) void JucerDocument::setComponentOverlayOpacity (const float alpha)
{ {
if (alpha != componentOverlayOpacity)
if (! approximatelyEqual (alpha, componentOverlayOpacity))
{ {
componentOverlayOpacity = alpha; componentOverlayOpacity = alpha;
changed(); changed();


+ 1
- 1
extras/Projucer/Source/Project/UI/jucer_ContentViewComponents.h View File

@@ -136,7 +136,7 @@ private:
for (auto w : widths) for (auto w : widths)
total += w; total += w;
if (total == 1.0f)
if (approximatelyEqual (total, 1.0f))
return; return;
auto diff = 1.0f - total; auto diff = 1.0f - total;


+ 19
- 4
extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h View File

@@ -320,10 +320,25 @@ public:
static CompilerWarningFlags getRecommendedForGCCAndLLVM() static CompilerWarningFlags getRecommendedForGCCAndLLVM()
{ {
CompilerWarningFlags result; CompilerWarningFlags result;
result.common = { "-Wall", "-Wstrict-aliasing", "-Wuninitialized", "-Wunused-parameter",
"-Wswitch-enum", "-Wsign-conversion", "-Wsign-compare",
"-Wunreachable-code", "-Wcast-align", "-Wno-ignored-qualifiers" };
result.cpp = { "-Woverloaded-virtual", "-Wreorder", "-Wzero-as-null-pointer-constant" };
result.common = {
"-Wall",
"-Wcast-align",
"-Wfloat-equal",
"-Wno-ignored-qualifiers",
"-Wsign-compare",
"-Wsign-conversion",
"-Wstrict-aliasing",
"-Wswitch-enum",
"-Wuninitialized",
"-Wunreachable-code",
"-Wunused-parameter"
};
result.cpp = {
"-Woverloaded-virtual",
"-Wreorder",
"-Wzero-as-null-pointer-constant"
};
return result; return result;
} }


+ 2
- 2
modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp View File

@@ -599,7 +599,7 @@ public:
for (int ch = 0; ch < numChannels; ++ch) for (int ch = 0; ch < numChannels; ++ch)
for (int i = 0; i < numSamples; ++i) for (int i = 0; i < numSamples; ++i)
expect (destBuffer.getSample (0, ch + (i * numChannels)) == sourceBuffer.getSample (ch, i));
expectEquals (destBuffer.getSample (0, ch + (i * numChannels)), sourceBuffer.getSample (ch, i));
} }
beginTest ("Deinterleaving"); beginTest ("Deinterleaving");
@@ -620,7 +620,7 @@ public:
for (int ch = 0; ch < numChannels; ++ch) for (int ch = 0; ch < numChannels; ++ch)
for (int i = 0; i < numSamples; ++i) for (int i = 0; i < numSamples; ++i)
expect (sourceBuffer.getSample (0, ch + (i * numChannels)) == destBuffer.getSample (ch, i));
expectEquals (sourceBuffer.getSample (0, ch + (i * numChannels)), destBuffer.getSample (ch, i));
} }
} }
}; };


+ 1
- 1
modules/juce_audio_basics/buffers/juce_AudioProcessLoadMeasurer.cpp View File

@@ -60,7 +60,7 @@ void AudioProcessLoadMeasurer::registerRenderTime (double milliseconds, int numS
void AudioProcessLoadMeasurer::registerRenderTimeLocked (double milliseconds, int numSamples) void AudioProcessLoadMeasurer::registerRenderTimeLocked (double milliseconds, int numSamples)
{ {
if (msPerSample == 0)
if (approximatelyEqual (msPerSample, 0.0))
return; return;
const auto maxMilliseconds = numSamples * msPerSample; const auto maxMilliseconds = numSamples * msPerSample;


+ 6
- 6
modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h View File

@@ -686,11 +686,11 @@ public:
jassert (isPositiveAndBelow (channel, numChannels)); jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size); jassert (startSample >= 0 && numSamples >= 0 && startSample + numSamples <= size);
if (gain != Type (1) && ! isClear)
if (! approximatelyEqual (gain, Type (1)) && ! isClear)
{ {
auto* d = channels[channel] + startSample; auto* d = channels[channel] + startSample;
if (gain == Type())
if (approximatelyEqual (gain, Type()))
FloatVectorOperations::clear (d, numSamples); FloatVectorOperations::clear (d, numSamples);
else else
FloatVectorOperations::multiply (d, gain, numSamples); FloatVectorOperations::multiply (d, gain, numSamples);
@@ -728,7 +728,7 @@ public:
{ {
if (! isClear) if (! isClear)
{ {
if (startGain == endGain)
if (approximatelyEqual (startGain, endGain))
{ {
applyGain (channel, startSample, numSamples, startGain); applyGain (channel, startSample, numSamples, startGain);
} }
@@ -798,7 +798,7 @@ public:
jassert (isPositiveAndBelow (sourceChannel, source.numChannels)); jassert (isPositiveAndBelow (sourceChannel, source.numChannels));
jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size); jassert (sourceStartSample >= 0 && sourceStartSample + numSamples <= source.size);
if (gainToApplyToSource != 0 && numSamples > 0 && ! source.isClear)
if (! approximatelyEqual (gainToApplyToSource, (Type) 0) && numSamples > 0 && ! source.isClear)
{ {
auto* d = channels[destChannel] + destStartSample; auto* d = channels[destChannel] + destStartSample;
auto* s = source.channels[sourceChannel] + sourceStartSample; auto* s = source.channels[sourceChannel] + sourceStartSample;
@@ -809,14 +809,14 @@ public:
{ {
isClear = false; isClear = false;
if (gainToApplyToSource != Type (1))
if (! approximatelyEqual (gainToApplyToSource, Type (1)))
FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples); FloatVectorOperations::copyWithMultiply (d, s, gainToApplyToSource, numSamples);
else else
FloatVectorOperations::copy (d, s, numSamples); FloatVectorOperations::copy (d, s, numSamples);
} }
else else
{ {
if (gainToApplyToSource != Type (1))
if (! approximatelyEqual (gainToApplyToSource, Type (1)))
FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples); FloatVectorOperations::addWithMultiply (d, s, gainToApplyToSource, numSamples);
else else
FloatVectorOperations::add (d, s, numSamples); FloatVectorOperations::add (d, s, numSamples);


+ 1
- 1
modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp View File

@@ -1676,7 +1676,7 @@ public:
static bool areAllValuesEqual (const ValueType* d, int num, ValueType target) static bool areAllValuesEqual (const ValueType* d, int num, ValueType target)
{ {
while (--num >= 0) while (--num >= 0)
if (*d++ != target)
if (! exactlyEqual (*d++, target))
return false; return false;
return true; return true;


+ 3
- 3
modules/juce_audio_basics/midi/juce_MidiFile.cpp View File

@@ -160,7 +160,7 @@ namespace MidiFileHelpers
for (int i = 0; i < numEvents; ++i) for (int i = 0; i < numEvents; ++i)
{ {
auto& m = tempoEvents.getEventPointer(i)->message;
auto& m = tempoEvents.getEventPointer (i)->message;
auto eventTime = m.getTimeStamp(); auto eventTime = m.getTimeStamp();
if (eventTime >= time) if (eventTime >= time)
@@ -174,9 +174,9 @@ namespace MidiFileHelpers
while (i + 1 < numEvents) while (i + 1 < numEvents)
{ {
auto& m2 = tempoEvents.getEventPointer(i + 1)->message;
auto& m2 = tempoEvents.getEventPointer (i + 1)->message;
if (m2.getTimeStamp() != eventTime)
if (! approximatelyEqual (m2.getTimeStamp(), eventTime))
break; break;
if (m2.isTempoMetaEvent()) if (m2.isTempoMetaEvent())


+ 2
- 2
modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp View File

@@ -266,7 +266,7 @@ void MidiMessageSequence::updateMatchedPairs() noexcept
void MidiMessageSequence::addTimeToMessages (double delta) noexcept void MidiMessageSequence::addTimeToMessages (double delta) noexcept
{ {
if (delta != 0)
if (! approximatelyEqual (delta, 0.0))
for (auto* m : list) for (auto* m : list)
m->message.addToTimeStamp (delta); m->message.addToTimeStamp (delta);
} }
@@ -554,7 +554,7 @@ struct MidiMessageSequenceTest : public UnitTest
{ {
const auto isEqual = [this] (const ControlValue& cv, const MidiMessage& msg) const auto isEqual = [this] (const ControlValue& cv, const MidiMessage& msg)
{ {
return msg.getTimeStamp() == time
return exactlyEqual (msg.getTimeStamp(), time)
&& msg.isController() && msg.isController()
&& msg.getChannel() == channel && msg.getChannel() == channel
&& msg.getControllerNumber() == cv.control && msg.getControllerNumber() == cv.control


+ 2
- 2
modules/juce_audio_basics/mpe/juce_MPESynthesiserBase.cpp View File

@@ -107,7 +107,7 @@ void MPESynthesiserBase::renderNextBlock (AudioBuffer<floatType>& outputAudio,
int numSamples) int numSamples)
{ {
// you must set the sample rate before using this! // you must set the sample rate before using this!
jassert (sampleRate != 0);
jassert (! approximatelyEqual (sampleRate, 0.0));
const ScopedLock sl (noteStateLock); const ScopedLock sl (noteStateLock);
@@ -144,7 +144,7 @@ template void MPESynthesiserBase::renderNextBlock<double> (AudioBuffer<double>&,
//============================================================================== //==============================================================================
void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate) void MPESynthesiserBase::setCurrentPlaybackSampleRate (const double newRate)
{ {
if (sampleRate != newRate)
if (! approximatelyEqual (sampleRate, newRate))
{ {
const ScopedLock sl (noteStateLock); const ScopedLock sl (noteStateLock);
instrument.releaseAllNotes(); instrument.releaseAllNotes();


+ 4
- 4
modules/juce_audio_basics/native/juce_CoreAudioLayouts_mac.h View File

@@ -263,13 +263,13 @@ public:
} }
} }
auto numChannels = tag & 0xffff;
const auto numChannels = tag & 0xffff;
if (tag >= coreAudioHOASN3DLayoutTag && tag <= (coreAudioHOASN3DLayoutTag | 0xffff)) if (tag >= coreAudioHOASN3DLayoutTag && tag <= (coreAudioHOASN3DLayoutTag | 0xffff))
{ {
auto sqrtMinusOne = std::sqrt (static_cast<float> (numChannels)) - 1.0f;
auto ambisonicOrder = jmax (0, static_cast<int> (std::floor (sqrtMinusOne)));
const auto ambisonicOrder = AudioChannelSet::getAmbisonicOrderForNumChannels (static_cast<int> (numChannels));
if (static_cast<float> (ambisonicOrder) == sqrtMinusOne)
if (ambisonicOrder != -1)
return AudioChannelSet::ambisonic (ambisonicOrder).getChannelTypes(); return AudioChannelSet::ambisonic (ambisonicOrder).getChannelTypes();
} }


+ 1
- 1
modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp View File

@@ -51,7 +51,7 @@ void BufferingAudioSource::prepareToPlay (int samplesPerBlockExpected, double ne
{ {
auto bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer); auto bufferSizeNeeded = jmax (samplesPerBlockExpected * 2, numberOfSamplesToBuffer);
if (newSampleRate != sampleRate
if (! approximatelyEqual (newSampleRate, sampleRate)
|| bufferSizeNeeded != buffer.getNumSamples() || bufferSizeNeeded != buffer.getNumSamples()
|| ! isPrepared) || ! isPrepared)
{ {


+ 2
- 2
modules/juce_audio_basics/sources/juce_MemoryAudioSource.cpp View File

@@ -184,7 +184,7 @@ struct MemoryAudioSourceTests : public UnitTest
play (source, channelInfo); play (source, channelInfo);
for (int sample = 0; sample < buffer.getNumSamples(); ++sample) for (int sample = 0; sample < buffer.getNumSamples(); ++sample)
expect (bufferToFill.getSample (0, sample + buffer.getNumSamples()) == buffer.getSample (0, sample));
expectEquals (bufferToFill.getSample (0, sample + buffer.getNumSamples()), buffer.getSample (0, sample));
expect (! isSilent (bufferToFill)); expect (! isSilent (bufferToFill));
} }
@@ -219,7 +219,7 @@ struct MemoryAudioSourceTests : public UnitTest
for (int i = 0; i < 100; ++i) for (int i = 0; i < 100; ++i)
{ {
play (source, channelInfo); play (source, channelInfo);
expect (bufferToFill.getSample (0, 0) == buffer.getSample (0, (i * blockSize) % buffer.getNumSamples()));
expectEquals (bufferToFill.getSample (0, 0), buffer.getSample (0, (i * blockSize) % buffer.getNumSamples()));
} }
} }
} }


+ 1
- 1
modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp View File

@@ -88,7 +88,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf
localRatio = ratio; localRatio = ratio;
} }
if (lastRatio != localRatio)
if (! approximatelyEqual (lastRatio, localRatio))
{ {
createLowPass (localRatio); createLowPass (localRatio);
lastRatio = localRatio; lastRatio = localRatio;


+ 1
- 1
modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp View File

@@ -62,7 +62,7 @@ void ToneGeneratorAudioSource::releaseResources()
void ToneGeneratorAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info) void ToneGeneratorAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
{ {
if (phasePerSample == 0.0)
if (approximatelyEqual (phasePerSample, 0.0))
phasePerSample = MathConstants<double>::twoPi / (sampleRate / frequency); phasePerSample = MathConstants<double>::twoPi / (sampleRate / frequency);
for (int i = 0; i < info.numSamples; ++i) for (int i = 0; i < info.numSamples; ++i)


+ 2
- 2
modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp View File

@@ -153,7 +153,7 @@ void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples, bool shoul
//============================================================================== //==============================================================================
void Synthesiser::setCurrentPlaybackSampleRate (const double newRate) void Synthesiser::setCurrentPlaybackSampleRate (const double newRate)
{ {
if (sampleRate != newRate)
if (! approximatelyEqual (sampleRate, newRate))
{ {
const ScopedLock sl (lock); const ScopedLock sl (lock);
allNotesOff (0, false); allNotesOff (0, false);
@@ -171,7 +171,7 @@ void Synthesiser::processNextBlock (AudioBuffer<floatType>& outputAudio,
int numSamples) int numSamples)
{ {
// must set the sample rate before using this! // must set the sample rate before using this!
jassert (sampleRate != 0);
jassert (! exactlyEqual (sampleRate, 0.0));
const int targetChannels = outputAudio.getNumChannels(); const int targetChannels = outputAudio.getNumChannels();
auto midiIterator = midiData.findNextSamplePosition (startSample); auto midiIterator = midiData.findNextSamplePosition (startSample);


+ 1
- 1
modules/juce_audio_basics/utilities/juce_Interpolators.h View File

@@ -73,7 +73,7 @@ private:
sign = (sincPosition < 0 ? -1 : 1); sign = (sincPosition < 0 ? -1 : 1);
} }
if (sincPosition == 0.0f)
if (approximatelyEqual (sincPosition, 0.0f))
result += inputs[samplePosition]; result += inputs[samplePosition];
else if (sincPosition < floatCrossings && sincPosition > -floatCrossings) else if (sincPosition < floatCrossings && sincPosition > -floatCrossings)
result += inputs[samplePosition] * windowedSinc (firstFrac, index); result += inputs[samplePosition] * windowedSinc (firstFrac, index);


+ 5
- 3
modules/juce_audio_basics/utilities/juce_SmoothedValue.h View File

@@ -237,7 +237,8 @@ public:
SmoothedValue (FloatType initialValue) noexcept SmoothedValue (FloatType initialValue) noexcept
{ {
// Multiplicative smoothed values cannot ever reach 0! // Multiplicative smoothed values cannot ever reach 0!
jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && initialValue == 0));
jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative>
&& approximatelyEqual (initialValue, (FloatType) 0)));
// Visual Studio can't handle base class initialisation with CRTP // Visual Studio can't handle base class initialisation with CRTP
this->currentValue = initialValue; this->currentValue = initialValue;
@@ -270,7 +271,7 @@ public:
*/ */
void setTargetValue (FloatType newValue) noexcept void setTargetValue (FloatType newValue) noexcept
{ {
if (newValue == this->target)
if (approximatelyEqual (newValue, this->target))
return; return;
if (stepsToTarget <= 0) if (stepsToTarget <= 0)
@@ -280,7 +281,8 @@ public:
} }
// Multiplicative smoothed values cannot ever reach 0! // Multiplicative smoothed values cannot ever reach 0!
jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && newValue == 0));
jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative>
&& approximatelyEqual (newValue, (FloatType) 0)));
this->target = newValue; this->target = newValue;
this->countdown = stepsToTarget; this->countdown = stepsToTarget;


+ 1
- 1
modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp View File

@@ -56,7 +56,7 @@ void MidiMessageCollector::addMessageToQueue (const MidiMessage& message)
// the messages that come in here need to be time-stamped correctly - see MidiInput // the messages that come in here need to be time-stamped correctly - see MidiInput
// for details of what the number should be. // for details of what the number should be.
jassert (message.getTimeStamp() != 0);
jassert (! approximatelyEqual (message.getTimeStamp(), 0.0));
auto sampleNumber = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate); auto sampleNumber = (int) ((message.getTimeStamp() - 0.001 * lastCallbackTime) * sampleRate);


+ 2
- 2
modules/juce_audio_devices/native/juce_Audio_ios.cpp View File

@@ -938,7 +938,7 @@ struct iOSAudioIODevice::Pimpl : public AsyncUpdater
{ {
if (! firstHostTime) if (! firstHostTime)
{ {
if ((time->mSampleTime - lastSampleTime) != lastNumFrames)
if (! approximatelyEqual ((time->mSampleTime - lastSampleTime), (double) lastNumFrames))
xrun++; xrun++;
} }
else else
@@ -1159,7 +1159,7 @@ struct iOSAudioIODevice::Pimpl : public AsyncUpdater
&desc, &desc,
&dataSize); &dataSize);
if (desc.mSampleRate != 0 && desc.mSampleRate != sampleRate)
if (! approximatelyEqual (desc.mSampleRate, 0.0) && ! approximatelyEqual (desc.mSampleRate, sampleRate))
{ {
JUCE_IOS_AUDIO_LOG ("Stream format has changed: Sample rate " << desc.mSampleRate); JUCE_IOS_AUDIO_LOG ("Stream format has changed: Sample rate " << desc.mSampleRate);
triggerAsyncUpdate(); triggerAsyncUpdate();


+ 4
- 4
modules/juce_audio_devices/native/juce_CoreAudio_mac.cpp View File

@@ -966,7 +966,7 @@ public:
jassert (timestamp == nullptr || (((timestamp->mFlags & kAudioTimeStampSampleTimeValid) != 0) jassert (timestamp == nullptr || (((timestamp->mFlags & kAudioTimeStampSampleTimeValid) != 0)
&& ((timestamp->mFlags & kAudioTimeStampHostTimeValid) != 0))); && ((timestamp->mFlags & kAudioTimeStampHostTimeValid) != 0)));
if (previousSampleTime == invalidSampleTime)
if (exactlyEqual (previousSampleTime, invalidSampleTime))
previousSampleTime = timestamp != nullptr ? timestamp->mSampleTime : 0.0; previousSampleTime = timestamp != nullptr ? timestamp->mSampleTime : 0.0;
if (timestamp != nullptr && std::fabs (previousSampleTime - timestamp->mSampleTime) >= 1.0) if (timestamp != nullptr && std::fabs (previousSampleTime - timestamp->mSampleTime) >= 1.0)
@@ -1091,7 +1091,7 @@ private:
if (! updateDetailsFromDevice()) if (! updateDetailsFromDevice())
owner.stopInternal(); owner.stopInternal();
else if ((oldBufferSize != bufferSize || oldSampleRate != sampleRate) && owner.shouldRestartDevice())
else if ((oldBufferSize != bufferSize || ! approximatelyEqual (oldSampleRate, sampleRate)) && owner.shouldRestartDevice())
owner.restart(); owner.restart();
} }
@@ -1577,7 +1577,7 @@ public:
{ {
auto deviceSampleRate = d->getCurrentSampleRate(); auto deviceSampleRate = d->getCurrentSampleRate();
if (deviceSampleRate != sampleRateRequested)
if (! approximatelyEqual (deviceSampleRate, sampleRateRequested))
{ {
if (! getAvailableSampleRates().contains (deviceSampleRate)) if (! getAvailableSampleRates().contains (deviceSampleRate))
return; return;
@@ -1912,7 +1912,7 @@ private:
for (auto& d : getDeviceWrappers()) for (auto& d : getDeviceWrappers())
{ {
if (d->getCurrentSampleRate() != currentSampleRate)
if (! approximatelyEqual (d->getCurrentSampleRate(), currentSampleRate))
{ {
d->setCurrentSampleRate (currentSampleRate); d->setCurrentSampleRate (currentSampleRate);
anySampleRateChanges = true; anySampleRateChanges = true;


+ 7
- 6
modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp View File

@@ -111,15 +111,16 @@ namespace FlacNamespace
#endif #endif
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion", JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
"-Wshadow",
"-Wdeprecated-register", "-Wdeprecated-register",
"-Wswitch-enum",
"-Wswitch-default",
"-Wfloat-equal",
"-Wimplicit-fallthrough", "-Wimplicit-fallthrough",
"-Wzero-as-null-pointer-constant",
"-Wsign-conversion",
"-Wlanguage-extension-token",
"-Wredundant-decls", "-Wredundant-decls",
"-Wlanguage-extension-token")
"-Wshadow",
"-Wsign-conversion",
"-Wswitch-default",
"-Wswitch-enum",
"-Wzero-as-null-pointer-constant")
#if JUCE_INTEL #if JUCE_INTEL
#if JUCE_32BIT #if JUCE_32BIT


+ 12
- 11
modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp View File

@@ -37,20 +37,21 @@ namespace OggVorbisNamespace
#if JUCE_INCLUDE_OGGVORBIS_CODE || ! defined (JUCE_INCLUDE_OGGVORBIS_CODE) #if JUCE_INCLUDE_OGGVORBIS_CODE || ! defined (JUCE_INCLUDE_OGGVORBIS_CODE)
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4305 4189 4706 4995 4365 4456 4457 4459 6297 6011 6001 6308 6255 6386 6385 6246 6387 6263 6262 28182) JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4305 4189 4706 4995 4365 4456 4457 4459 6297 6011 6001 6308 6255 6386 6385 6246 6387 6263 6262 28182)
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
"-Wshadow",
"-Wfloat-conversion",
"-Wdeprecated-register",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align",
"-Wconversion",
"-Wdeprecated-declarations", "-Wdeprecated-declarations",
"-Wswitch-enum",
"-Wzero-as-null-pointer-constant",
"-Wsign-conversion",
"-Wswitch-default",
"-Wredundant-decls",
"-Wdeprecated-register",
"-Wfloat-conversion",
"-Wfloat-equal",
"-Wmaybe-uninitialized",
"-Wmisleading-indentation", "-Wmisleading-indentation",
"-Wmissing-prototypes", "-Wmissing-prototypes",
"-Wcast-align",
"-Wmaybe-uninitialized")
"-Wredundant-decls",
"-Wshadow",
"-Wsign-conversion",
"-Wswitch-default",
"-Wswitch-enum",
"-Wzero-as-null-pointer-constant")
JUCE_BEGIN_NO_SANITIZE ("undefined") JUCE_BEGIN_NO_SANITIZE ("undefined")
#include "oggvorbis/vorbisenc.h" #include "oggvorbis/vorbisenc.h"


+ 1
- 1
modules/juce_audio_plugin_client/detail/juce_VSTWindowUtilities.h View File

@@ -50,7 +50,7 @@ struct VSTWindowUtilities
comp->addToDesktop (desktopFlags | defaultFlags, parentView); comp->addToDesktop (desktopFlags | defaultFlags, parentView);
// (this workaround is because Wavelab provides a zero-size parent view..) // (this workaround is because Wavelab provides a zero-size parent view..)
if ([parentView frame].size.height == 0)
if (approximatelyEqual ([parentView frame].size.height, 0.0))
[((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint]; [((NSView*) comp->getWindowHandle()) setFrameOrigin: NSZeroPoint];
comp->setVisible (true); comp->setVisible (true);


+ 9
- 8
modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX.cpp View File

@@ -35,16 +35,17 @@
#include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp> #include <juce_audio_processors/format_types/juce_LegacyAudioParameter.cpp>
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4127 4512 4996) JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4127 4512 4996)
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wnon-virtual-dtor",
"-Wsign-conversion",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations",
"-Wextra-semi", "-Wextra-semi",
"-Wshift-sign-overflow",
"-Wpragma-pack",
"-Wzero-as-null-pointer-constant",
"-Winconsistent-missing-destructor-override",
"-Wfloat-equal",
"-Wfour-char-constants", "-Wfour-char-constants",
"-Winconsistent-missing-destructor-override",
"-Wnon-virtual-dtor",
"-Wpragma-pack",
"-Wshift-sign-overflow",
"-Wsign-conversion",
"-Wtautological-overlap-compare", "-Wtautological-overlap-compare",
"-Wdeprecated-declarations")
"-Wzero-as-null-pointer-constant")
#include <AAX_Version.h> #include <AAX_Version.h>
@@ -1004,7 +1005,7 @@ namespace AAXClasses
{ {
auto newValue = static_cast<float> (value); auto newValue = static_cast<float> (value);
if (newValue != param->getValue())
if (! approximatelyEqual (newValue, param->getValue()))
{ {
param->setValue (newValue); param->setValue (newValue);


+ 5
- 4
modules/juce_audio_plugin_client/juce_audio_plugin_client_AAX_utils.cpp View File

@@ -40,12 +40,13 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant")
#include <Libs/AAXLibrary/source/AAX_CAutoreleasePool.Win.cpp> #include <Libs/AAXLibrary/source/AAX_CAutoreleasePool.Win.cpp>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE JUCE_END_IGNORE_WARNINGS_GCC_LIKE
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wunused-parameter",
"-Wshift-sign-overflow",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations",
"-Wextra-semi", "-Wextra-semi",
"-Wzero-as-null-pointer-constant",
"-Wfloat-equal",
"-Winconsistent-missing-destructor-override", "-Winconsistent-missing-destructor-override",
"-Wdeprecated-declarations")
"-Wshift-sign-overflow",
"-Wunused-parameter",
"-Wzero-as-null-pointer-constant")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6001 6053 4996 5033 4068 4996) JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6001 6053 4996 5033 4068 4996)
#include <Libs/AAXLibrary/source/AAX_CChunkDataParser.cpp> #include <Libs/AAXLibrary/source/AAX_CChunkDataParser.cpp>


+ 14
- 13
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_1.mm View File

@@ -29,21 +29,22 @@
#if JucePlugin_Build_AU #if JucePlugin_Build_AU
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wshorten-64-to-32",
"-Wunused-parameter",
"-Wdeprecated-declarations",
"-Wsign-conversion",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align",
"-Wconversion", "-Wconversion",
"-Woverloaded-virtual",
"-Wdeprecated-anon-enum-enum-conversion",
"-Wdeprecated-declarations",
"-Wextra-semi", "-Wextra-semi",
"-Wcast-align",
"-Wfloat-equal",
"-Wformat-pedantic",
"-Wgnu-zero-variadic-macro-arguments",
"-Wnullable-to-nonnull-conversion",
"-Woverloaded-virtual",
"-Wshadow", "-Wshadow",
"-Wshorten-64-to-32",
"-Wsign-conversion",
"-Wswitch-enum", "-Wswitch-enum",
"-Wzero-as-null-pointer-constant",
"-Wnullable-to-nonnull-conversion",
"-Wgnu-zero-variadic-macro-arguments",
"-Wformat-pedantic",
"-Wdeprecated-anon-enum-enum-conversion")
"-Wunused-parameter",
"-Wzero-as-null-pointer-constant")
#include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h> #include <juce_audio_plugin_client/detail/juce_IncludeSystemHeaders.h>
@@ -1066,7 +1067,7 @@ public:
{ {
auto value = inValue / getMaximumParameterValue (param); auto value = inValue / getMaximumParameterValue (param);
if (value != param->getValue())
if (! approximatelyEqual (value, param->getValue()))
{ {
inParameterChangedCallback = true; inParameterChangedCallback = true;
param->setValueNotifyingHost (value); param->setValueNotifyingHost (value);
@@ -1634,7 +1635,7 @@ public:
static NSTimeInterval lastEventTime = 0; // check we're not recursively sending the same event static NSTimeInterval lastEventTime = 0; // check we're not recursively sending the same event
NSTimeInterval eventTime = [[NSApp currentEvent] timestamp]; NSTimeInterval eventTime = [[NSApp currentEvent] timestamp];
if (lastEventTime != eventTime)
if (! approximatelyEqual (lastEventTime, eventTime))
{ {
lastEventTime = eventTime; lastEventTime = eventTime;


+ 15
- 14
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm View File

@@ -29,28 +29,29 @@
#include <juce_core/system/juce_CompilerWarnings.h> #include <juce_core/system/juce_CompilerWarnings.h>
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wparentheses",
"-Wextra-tokens",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wambiguous-reversed-operator",
"-Wc99-extensions",
"-Wcast-align",
"-Wcomment", "-Wcomment",
"-Wconversion", "-Wconversion",
"-Wunused-parameter",
"-Wunused",
"-Wdeprecated-anon-enum-enum-conversion",
"-Wextra-semi", "-Wextra-semi",
"-Wextra-tokens",
"-Wfloat-equal",
"-Wformat-pedantic", "-Wformat-pedantic",
"-Wfour-char-constants",
"-Wgnu-zero-variadic-macro-arguments", "-Wgnu-zero-variadic-macro-arguments",
"-Wshadow-all",
"-Wcast-align",
"-Wswitch-enum",
"-Wimplicit-fallthrough",
"-Wzero-as-null-pointer-constant",
"-Wnullable-to-nonnull-conversion",
"-Wignored-qualifiers", "-Wignored-qualifiers",
"-Wfour-char-constants",
"-Wimplicit-fallthrough",
"-Wmissing-prototypes", "-Wmissing-prototypes",
"-Wdeprecated-anon-enum-enum-conversion",
"-Wambiguous-reversed-operator",
"-Wnullable-to-nonnull-conversion",
"-Wparentheses",
"-Wshadow-all",
"-Wswitch-enum",
"-Wunknown-attributes", "-Wunknown-attributes",
"-Wc99-extensions")
"-Wunused",
"-Wunused-parameter",
"-Wzero-as-null-pointer-constant")
// From MacOS 10.13 and iOS 11 Apple has (sensibly!) stopped defining a whole // From MacOS 10.13 and iOS 11 Apple has (sensibly!) stopped defining a whole
// set of functions with rather generic names. However, we still need a couple // set of functions with rather generic names. However, we still need a couple


+ 2
- 2
modules/juce_audio_plugin_client/juce_audio_plugin_client_AUv3.mm View File

@@ -1350,7 +1350,7 @@ private:
void setAudioProcessorParameter (AudioProcessorParameter* juceParam, float value) void setAudioProcessorParameter (AudioProcessorParameter* juceParam, float value)
{ {
if (value != juceParam->getValue())
if (! approximatelyEqual (value, juceParam->getValue()))
{ {
juceParam->setValue (value); juceParam->setValue (value);
@@ -1458,7 +1458,7 @@ private:
const auto numProcessorBusesOut = AudioUnitHelpers::getBusCount (processor, false); const auto numProcessorBusesOut = AudioUnitHelpers::getBusCount (processor, false);
if (lastTimeStamp.mSampleTime != timestamp->mSampleTime)
if (! approximatelyEqual (lastTimeStamp.mSampleTime, timestamp->mSampleTime))
{ {
// process params and incoming midi (only once for a given timestamp) // process params and incoming midi (only once for a given timestamp)
midiMessages.clear(); midiMessages.clear();


+ 2
- 2
modules/juce_audio_plugin_client/juce_audio_plugin_client_LV2.cpp View File

@@ -156,7 +156,7 @@ public:
return value; return value;
}(); }();
if (scaledValue != param->getValue())
if (! approximatelyEqual (scaledValue, param->getValue()))
{ {
ScopedValueSetter<bool> scope (ignoreCallbacks, true); ScopedValueSetter<bool> scope (ignoreCallbacks, true);
param->setValueNotifyingHost (scaledValue); param->setValueNotifyingHost (scaledValue);
@@ -326,7 +326,7 @@ public:
info->setBpm (parser.parseNumericAtom<float> (atomBeatsPerMinute)); info->setBpm (parser.parseNumericAtom<float> (atomBeatsPerMinute));
info->setPpqPosition (parser.parseNumericAtom<double> (atomBeat)); info->setPpqPosition (parser.parseNumericAtom<double> (atomBeat));
info->setIsPlaying (parser.parseNumericAtom<float> (atomSpeed).orFallback (0.0f) != 0.0f);
info->setIsPlaying (! approximatelyEqual (parser.parseNumericAtom<float> (atomSpeed).orFallback (0.0f), 0.0f));
info->setBarCount (parser.parseNumericAtom<int64_t> (atomBar)); info->setBarCount (parser.parseNumericAtom<int64_t> (atomBar));
if (const auto parsed = parser.parseNumericAtom<int64_t> (atomFrame)) if (const auto parsed = parser.parseNumericAtom<int64_t> (atomFrame))


+ 4
- 4
modules/juce_audio_plugin_client/juce_audio_plugin_client_VST2.cpp View File

@@ -552,7 +552,7 @@ public:
if (detail::PluginUtilities::getHostType().isAbletonLive() if (detail::PluginUtilities::getHostType().isAbletonLive()
&& hostCallback != nullptr && hostCallback != nullptr
&& processor->getTailLengthSeconds() == std::numeric_limits<double>::infinity())
&& std::isinf (processor->getTailLengthSeconds()))
{ {
AbletonLiveHostSpecific hostCmd; AbletonLiveHostSpecific hostCmd;
@@ -645,7 +645,7 @@ public:
}()); }());
const auto effectiveRate = info.getFrameRate().hasValue() ? info.getFrameRate()->getEffectiveRate() : 0.0; const auto effectiveRate = info.getFrameRate().hasValue() ? info.getFrameRate()->getEffectiveRate() : 0.0;
info.setEditOriginTime (effectiveRate != 0.0 ? makeOptional (ti->smpteOffset / (80.0 * effectiveRate)) : nullopt);
info.setEditOriginTime (! approximatelyEqual (effectiveRate, 0.0) ? makeOptional (ti->smpteOffset / (80.0 * effectiveRate)) : nullopt);
} }
info.setIsRecording ((ti->flags & Vst2::kVstTransportRecording) != 0); info.setIsRecording ((ti->flags & Vst2::kVstTransportRecording) != 0);
@@ -1395,7 +1395,7 @@ private:
void setValueAndNotifyIfChanged (AudioProcessorParameter& param, float newValue) void setValueAndNotifyIfChanged (AudioProcessorParameter& param, float newValue)
{ {
if (param.getValue() == newValue)
if (approximatelyEqual (param.getValue(), newValue))
return; return;
inParameterChangedCallback = true; inParameterChangedCallback = true;
@@ -1896,7 +1896,7 @@ private:
auto tailSeconds = processor->getTailLengthSeconds(); auto tailSeconds = processor->getTailLengthSeconds();
if (tailSeconds == std::numeric_limits<double>::infinity())
if (std::isinf (tailSeconds))
result = std::numeric_limits<int32>::max(); result = std::numeric_limits<int32>::max();
else else
result = static_cast<int32> (tailSeconds * sampleRate); result = static_cast<int32> (tailSeconds * sampleRate);


+ 8
- 8
modules/juce_audio_plugin_client/juce_audio_plugin_client_VST3.cpp View File

@@ -701,7 +701,7 @@ static thread_local bool inParameterChangedCallback = false;
static void setValueAndNotifyIfChanged (AudioProcessorParameter& param, float newValue) static void setValueAndNotifyIfChanged (AudioProcessorParameter& param, float newValue)
{ {
if (param.getValue() == newValue)
if (approximatelyEqual (param.getValue(), newValue))
return; return;
const InParameterChangedCallbackSetter scopedSetter { inParameterChangedCallback }; const InParameterChangedCallbackSetter scopedSetter { inParameterChangedCallback };
@@ -830,7 +830,7 @@ public:
{ {
v = jlimit (0.0, 1.0, v); v = jlimit (0.0, 1.0, v);
if (v != valueNormalized)
if (! approximatelyEqual (v, valueNormalized))
{ {
valueNormalized = v; valueNormalized = v;
@@ -910,7 +910,7 @@ public:
if (programValue != owner.getCurrentProgram()) if (programValue != owner.getCurrentProgram())
owner.setCurrentProgram (programValue); owner.setCurrentProgram (programValue);
if (valueNormalized != v)
if (! approximatelyEqual (valueNormalized, v))
{ {
valueNormalized = v; valueNormalized = v;
changed(); changed();
@@ -1931,7 +1931,7 @@ private:
auto aspectRatio = (float) constrainer->getFixedAspectRatio(); auto aspectRatio = (float) constrainer->getFixedAspectRatio();
if (aspectRatio != 0.0)
if (! approximatelyEqual (aspectRatio, 0.0f))
{ {
bool adjustWidth = (width / height > aspectRatio); bool adjustWidth = (width / height > aspectRatio);
@@ -1939,9 +1939,9 @@ private:
{ {
auto currentEditorBounds = editor->getBounds().toFloat(); auto currentEditorBounds = editor->getBounds().toFloat();
if (currentEditorBounds.getWidth() == width && currentEditorBounds.getHeight() != height)
if (approximatelyEqual (currentEditorBounds.getWidth(), width) && ! approximatelyEqual (currentEditorBounds.getHeight(), height))
adjustWidth = true; adjustWidth = true;
else if (currentEditorBounds.getHeight() == height && currentEditorBounds.getWidth() != width)
else if (approximatelyEqual (currentEditorBounds.getHeight(), height) && ! approximatelyEqual (currentEditorBounds.getWidth(), width))
adjustWidth = false; adjustWidth = false;
} }
@@ -2322,7 +2322,7 @@ private:
{ {
const auto previous = std::exchange (scaleFactor, newFactor).get(); const auto previous = std::exchange (scaleFactor, newFactor).get();
if (previous == scaleFactor.get())
if (approximatelyEqual (previous, scaleFactor.get()))
return; return;
if (owner != nullptr) if (owner != nullptr)
@@ -3422,7 +3422,7 @@ public:
if (tailLengthSeconds <= 0.0 || processSetup.sampleRate <= 0.0) if (tailLengthSeconds <= 0.0 || processSetup.sampleRate <= 0.0)
return Vst::kNoTail; return Vst::kNoTail;
if (tailLengthSeconds == std::numeric_limits<double>::infinity())
if (std::isinf (tailLengthSeconds))
return Vst::kInfiniteTail; return Vst::kInfiniteTail;
return (Steinberg::uint32) roundToIntAccurate (tailLengthSeconds * processSetup.sampleRate); return (Steinberg::uint32) roundToIntAccurate (tailLengthSeconds * processSetup.sampleRate);


+ 2
- 2
modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm View File

@@ -1247,7 +1247,7 @@ public:
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, scope, static_cast<UInt32> (i), &sampleRate, &sampleRateSize); AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, scope, static_cast<UInt32> (i), &sampleRate, &sampleRateSize);
if (sampleRate != sr)
if (! approximatelyEqual (sampleRate, sr))
{ {
if (isAUv3) // setting kAudioUnitProperty_SampleRate fails on AUv3s if (isAUv3) // setting kAudioUnitProperty_SampleRate fails on AUv3s
{ {
@@ -2739,7 +2739,7 @@ private:
if (@available (macOS 10.11, *)) if (@available (macOS 10.11, *))
size = [controller preferredContentSize]; size = [controller preferredContentSize];
if (size.width == 0 || size.height == 0)
if (approximatelyEqual (size.width, 0.0) || approximatelyEqual (size.height, 0.0))
size = controller.view.frame.size; size = controller.view.frame.size;
return CGSizeMake (jmax ((CGFloat) 20.0f, size.width), return CGSizeMake (jmax ((CGFloat) 20.0f, size.width),


+ 1
- 1
modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp View File

@@ -457,7 +457,7 @@ private:
{ {
const ScopedLock sl (pluginInstance.lock); const ScopedLock sl (pluginInstance.lock);
if (paramValue.unscaled != newValue)
if (! approximatelyEqual (paramValue.unscaled, newValue))
paramValue = ParameterValue (getNewParamScaled (interface->PortRangeHints [paramID], newValue), newValue); paramValue = ParameterValue (getNewParamScaled (interface->PortRangeHints [paramID], newValue), newValue);
} }
} }


+ 1
- 1
modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp View File

@@ -3287,7 +3287,7 @@ private:
{ {
if (auto* r = ref.getComponent()) if (auto* r = ref.getComponent())
{ {
if (std::exchange (r->nativeScaleFactor, platformScale) == platformScale)
if (approximatelyEqual (std::exchange (r->nativeScaleFactor, platformScale), platformScale))
return; return;
r->nativeScaleFactor = platformScale; r->nativeScaleFactor = platformScale;


+ 3
- 2
modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp View File

@@ -31,6 +31,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wc99-extensions",
"-Wdeprecated-declarations", "-Wdeprecated-declarations",
"-Wextra-semi", "-Wextra-semi",
"-Wfloat-conversion", "-Wfloat-conversion",
"-Wfloat-equal",
"-Wformat-overflow",
"-Wimplicit-float-conversion", "-Wimplicit-float-conversion",
"-Wimplicit-int-conversion", "-Wimplicit-int-conversion",
"-Wmicrosoft-include", "-Wmicrosoft-include",
@@ -44,8 +46,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wc99-extensions",
"-Wsign-conversion", "-Wsign-conversion",
"-Wswitch-enum", "-Wswitch-enum",
"-Wunused-parameter", "-Wunused-parameter",
"-Wzero-as-null-pointer-constant",
"-Wformat-overflow")
"-Wzero-as-null-pointer-constant")
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100 4200 4244 4267 4389 4702 4706 4800 4996 6308 28182 28183 6385 6386 6387 6011 6282 6323 6330 6001 6031) JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100 4200 4244 4267 4389 4702 4706 4800 4996 6308 28182 28183 6385 6386 6387 6011 6282 6323 6330 6001 6031)
extern "C" extern "C"


+ 31
- 30
modules/juce_audio_processors/format_types/juce_VST3Headers.h View File

@@ -32,44 +32,45 @@
// Wow, those Steinberg guys really don't worry too much about compiler warnings. // Wow, those Steinberg guys really don't worry too much about compiler warnings.
JUCE_BEGIN_IGNORE_WARNINGS_LEVEL_MSVC (0, 4505 4702 6011 6031 6221 6386 6387 6330 6001 28199) JUCE_BEGIN_IGNORE_WARNINGS_LEVEL_MSVC (0, 4505 4702 6011 6031 6221 6386 6387 6330 6001 28199)
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor",
"-Wnon-virtual-dtor",
"-Wdeprecated",
"-Wreorder",
"-Wunsequenced",
"-Wint-to-pointer-cast",
"-Wunused-parameter",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-W#warnings",
"-Wcast-align",
"-Wclass-memaccess",
"-Wcomma",
"-Wconversion", "-Wconversion",
"-Woverloaded-virtual",
"-Wshadow",
"-Wdeprecated-register",
"-Wunused-function",
"-Wsign-conversion",
"-Wsign-compare",
"-Wcpp",
"-Wdelete-non-virtual-dtor", "-Wdelete-non-virtual-dtor",
"-Wdeprecated",
"-Wdeprecated-copy-dtor",
"-Wdeprecated-declarations", "-Wdeprecated-declarations",
"-Wdeprecated-register",
"-Wextra",
"-Wextra-semi", "-Wextra-semi",
"-Wmissing-braces",
"-Wswitch-default",
"-Wshadow-field",
"-Wpragma-pack",
"-Wcomma",
"-Wzero-as-null-pointer-constant",
"-Winconsistent-missing-destructor-override",
"-Wcast-align",
"-Wfloat-equal",
"-Wformat",
"-Wformat=",
"-Wignored-qualifiers", "-Wignored-qualifiers",
"-Winconsistent-missing-destructor-override",
"-Wint-to-pointer-cast",
"-Wmaybe-uninitialized",
"-Wmissing-braces",
"-Wmissing-field-initializers", "-Wmissing-field-initializers",
"-Wformat=",
"-Wformat",
"-Wpedantic",
"-Wextra",
"-Wclass-memaccess",
"-Wmissing-prototypes", "-Wmissing-prototypes",
"-Wnon-virtual-dtor",
"-Woverloaded-virtual",
"-Wpedantic",
"-Wpragma-pack",
"-Wreorder",
"-Wshadow",
"-Wshadow-field",
"-Wsign-compare",
"-Wsign-conversion",
"-Wswitch-default",
"-Wtype-limits", "-Wtype-limits",
"-Wcpp",
"-W#warnings",
"-Wmaybe-uninitialized",
"-Wunused-but-set-variable")
"-Wunsequenced",
"-Wunused-but-set-variable",
"-Wunused-function",
"-Wunused-parameter",
"-Wzero-as-null-pointer-constant")
#undef DEVELOPMENT #undef DEVELOPMENT
#define DEVELOPMENT 0 // This avoids a Clang warning in Steinberg code about unused values #define DEVELOPMENT 0 // This avoids a Clang warning in Steinberg code about unused values


+ 3
- 3
modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp View File

@@ -2498,7 +2498,7 @@ public:
// Avoid redundantly calling things like setActive, which can be a heavy-duty call for some plugins: // Avoid redundantly calling things like setActive, which can be a heavy-duty call for some plugins:
if (isActive if (isActive
&& getSampleRate() == newSampleRate
&& approximatelyEqual (getSampleRate(), newSampleRate)
&& getBlockSize() == estimatedSamplesPerBlock) && getBlockSize() == estimatedSamplesPerBlock)
return; return;
@@ -3432,7 +3432,7 @@ private:
// call was processBlockBypassed, otherwise do nothing // call was processBlockBypassed, otherwise do nothing
if (processBlockBypassedCalled) if (processBlockBypassedCalled)
{ {
if (bypassParam != nullptr && (bypassParam->getValue() == 0.0f || ! lastProcessBlockCallWasBypass))
if (bypassParam != nullptr && (approximatelyEqual (bypassParam->getValue(), 0.0f) || ! lastProcessBlockCallWasBypass))
bypassParam->setValue (1.0f); bypassParam->setValue (1.0f);
} }
else else
@@ -3618,7 +3618,7 @@ tresult VST3HostContext::performEdit (Vst::ParamID paramID, Vst::ParamValue valu
param->setValueNotifyingHost ((float) valueNormalised); param->setValueNotifyingHost ((float) valueNormalised);
// did the plug-in already update the parameter internally // did the plug-in already update the parameter internally
if (plugin->editController->getParamNormalized (paramID) != (float) valueNormalised)
if (! approximatelyEqual (plugin->editController->getParamNormalized (paramID), valueNormalised))
return plugin->editController->setParamNormalized (paramID, valueNormalised); return plugin->editController->setParamNormalized (paramID, valueNormalised);
return kResultTrue; return kResultTrue;


+ 3
- 3
modules/juce_audio_processors/format_types/juce_VST3PluginFormat_test.cpp View File

@@ -584,7 +584,7 @@ private:
bool allMatch (int channel, float value) const bool allMatch (int channel, float value) const
{ {
const auto& buf = buffers[(size_t) channel]; const auto& buf = buffers[(size_t) channel];
return std::all_of (buf.begin(), buf.end(), [&] (auto x) { return x == value; });
return std::all_of (buf.begin(), buf.end(), [&] (auto x) { return exactlyEqual (x, value); });
} }
bool isClear (int channel) const bool isClear (int channel) const
@@ -607,13 +607,13 @@ private:
static bool channelStartsWithValue (Steinberg::Vst::AudioBusBuffers& bus, size_t index, float value) static bool channelStartsWithValue (Steinberg::Vst::AudioBusBuffers& bus, size_t index, float value)
{ {
return bus.channelBuffers32[index][0] == value;
return exactlyEqual (bus.channelBuffers32[index][0], value);
} }
static bool allMatch (const AudioBuffer<float>& buf, int index, float value) static bool allMatch (const AudioBuffer<float>& buf, int index, float value)
{ {
const auto* ptr = buf.getReadPointer (index); const auto* ptr = buf.getReadPointer (index);
return std::all_of (ptr, ptr + buf.getNumSamples(), [&] (auto x) { return x == value; });
return std::all_of (ptr, ptr + buf.getNumSamples(), [&] (auto x) { return exactlyEqual (x, value); });
} }
struct MultiBusBuffers struct MultiBusBuffers


+ 4
- 4
modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp View File

@@ -904,7 +904,7 @@ struct VSTPluginInstance final : public AudioPluginInstance,
{ {
const ScopedLock sl (pluginInstance.lock); const ScopedLock sl (pluginInstance.lock);
if (effect->getParameter (effect, getParameterIndex()) != newValue)
if (! approximatelyEqual (effect->getParameter (effect, getParameterIndex()), newValue))
effect->setParameter (effect, getParameterIndex(), newValue); effect->setParameter (effect, getParameterIndex(), newValue);
} }
} }
@@ -2004,7 +2004,7 @@ private:
void setValue (float newValue) override void setValue (float newValue) override
{ {
currentValue = (newValue != 0.0f);
currentValue = (! approximatelyEqual (newValue, 0.0f));
if (parent.vstSupportsBypass) if (parent.vstSupportsBypass)
parent.dispatch (Vst2::effSetBypass, 0, currentValue ? 1 : 0, nullptr, 0.0f); parent.dispatch (Vst2::effSetBypass, 0, currentValue ? 1 : 0, nullptr, 0.0f);
@@ -2028,7 +2028,7 @@ private:
float getValue() const override { return currentValue; } float getValue() const override { return currentValue; }
float getDefaultValue() const override { return 0.0f; } float getDefaultValue() const override { return 0.0f; }
String getName (int /*maximumStringLength*/) const override { return "Bypass"; } String getName (int /*maximumStringLength*/) const override { return "Bypass"; }
String getText (float value, int) const override { return (value != 0.0f ? TRANS("On") : TRANS("Off")); }
String getText (float value, int) const override { return (! approximatelyEqual (value, 0.0f) ? TRANS("On") : TRANS("Off")); }
bool isAutomatable() const override { return true; } bool isAutomatable() const override { return true; }
bool isDiscrete() const override { return true; } bool isDiscrete() const override { return true; }
bool isBoolean() const override { return true; } bool isBoolean() const override { return true; }
@@ -2740,7 +2740,7 @@ private:
{ {
if (processBlockBypassedCalled) if (processBlockBypassedCalled)
{ {
if (bypassParam->getValue() == 0.0f || ! lastProcessBlockCallWasBypass)
if (approximatelyEqual (bypassParam->getValue(), 0.0f) || ! lastProcessBlockCallWasBypass)
bypassParam->setValue (1.0f); bypassParam->setValue (1.0f);
} }
else else


+ 1
- 1
modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h View File

@@ -127,7 +127,7 @@ public:
if (processor != nullptr) if (processor != nullptr)
{ {
if (auto* bypassParam = processor->getBypassParameter()) if (auto* bypassParam = processor->getBypassParameter())
return (bypassParam->getValue() != 0.0f);
return ! approximatelyEqual (bypassParam->getValue(), 0.0f);
} }
return bypassed; return bypassed;


+ 1
- 1
modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp View File

@@ -378,7 +378,7 @@ private:
{ {
auto newVal = (float) slider.getValue(); auto newVal = (float) slider.getValue();
if (getParameter().getValue() != newVal)
if (! approximatelyEqual (getParameter().getValue(), newVal))
{ {
if (! isDragging) if (! isDragging)
getParameter().beginChangeGesture(); getParameter().beginChangeGesture();


+ 2
- 2
modules/juce_audio_processors/utilities/juce_AudioParameterFloat.cpp View File

@@ -44,7 +44,7 @@ AudioParameterFloat::AudioParameterFloat (const ParameterID& idToUse,
{ {
int numDecimalPlaces = 7; int numDecimalPlaces = 7;
if (range.interval != 0.0f)
if (! approximatelyEqual (range.interval, 0.0f))
{ {
if (approximatelyEqual (std::abs (range.interval - std::floor (range.interval)), 0.0f)) if (approximatelyEqual (std::abs (range.interval - std::floor (range.interval)), 0.0f))
return 0; return 0;
@@ -95,7 +95,7 @@ void AudioParameterFloat::valueChanged (float) {}
AudioParameterFloat& AudioParameterFloat::operator= (float newValue) AudioParameterFloat& AudioParameterFloat::operator= (float newValue)
{ {
if (value != newValue)
if (! approximatelyEqual ((float) value, newValue))
setValueNotifyingHost (convertTo0to1 (newValue)); setValueNotifyingHost (convertTo0to1 (newValue));
return *this; return *this;


+ 7
- 11
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp View File

@@ -52,13 +52,11 @@ bool AudioProcessorValueTreeState::Parameter::isBoolean() const { return
void AudioProcessorValueTreeState::Parameter::valueChanged (float newValue) void AudioProcessorValueTreeState::Parameter::valueChanged (float newValue)
{ {
if (lastValue == newValue)
if (approximatelyEqual ((float) lastValue, newValue))
return; return;
lastValue = newValue; lastValue = newValue;
if (onValueChanged != nullptr)
onValueChanged();
NullCheckedInvocation::invoke (onValueChanged);
} }
//============================================================================== //==============================================================================
@@ -93,10 +91,8 @@ public:
void setDenormalisedValue (float value) void setDenormalisedValue (float value)
{ {
if (value == unnormalisedValue)
return;
setNormalisedValue (normalise (value));
if (! approximatelyEqual (value, (float) unnormalisedValue))
setNormalisedValue (normalise (value));
} }
float getDenormalisedValueForText (const String& text) const float getDenormalisedValueForText (const String& text) const
@@ -119,9 +115,9 @@ public:
if (! needsUpdate.compare_exchange_strong (needsUpdateTestValue, false)) if (! needsUpdate.compare_exchange_strong (needsUpdateTestValue, false))
return false; return false;
if (auto valueProperty = tree.getPropertyPointer (key))
if (auto* valueProperty = tree.getPropertyPointer (key))
{ {
if ((float) *valueProperty != unnormalisedValue)
if (! approximatelyEqual ((float) *valueProperty, unnormalisedValue.load()))
{ {
ScopedValueSetter<bool> svs (ignoreParameterChangedCallbacks, true); ScopedValueSetter<bool> svs (ignoreParameterChangedCallbacks, true);
tree.setProperty (key, unnormalisedValue.load(), um); tree.setProperty (key, unnormalisedValue.load(), um);
@@ -144,7 +140,7 @@ private:
{ {
const auto newValue = denormalise (parameter.getValue()); const auto newValue = denormalise (parameter.getValue());
if (unnormalisedValue == newValue && ! listenersNeedCalling)
if (! listenersNeedCalling && approximatelyEqual ((float) unnormalisedValue, newValue))
return; return;
unnormalisedValue = newValue; unnormalisedValue = newValue;


+ 1
- 1
modules/juce_audio_processors/utilities/juce_ParameterAttachments.cpp View File

@@ -84,7 +84,7 @@ void ParameterAttachment::callIfParameterValueChanged (float newDenormalisedValu
{ {
const auto newValue = normalise (newDenormalisedValue); const auto newValue = normalise (newDenormalisedValue);
if (parameter.getValue() != newValue)
if (! approximatelyEqual (parameter.getValue(), newValue))
callback (newValue); callback (newValue);
} }


+ 1
- 1
modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp View File

@@ -722,7 +722,7 @@ private:
auto currentRate = currentDevice->getCurrentSampleRate(); auto currentRate = currentDevice->getCurrentSampleRate();
if (currentRate == 0)
if (exactlyEqual (currentRate, 0.0))
currentRate = 48000.0; currentRate = 48000.0;
for (auto bs : currentDevice->getAvailableBufferSizes()) for (auto bs : currentDevice->getAvailableBufferSizes())


+ 2
- 2
modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp View File

@@ -501,8 +501,8 @@ private:
if (numSamples == numSamplesCached if (numSamples == numSamplesCached
&& numChannelsCached == numChans && numChannelsCached == numChans
&& startTime == cachedStart
&& timePerPixel == cachedTimePerPixel
&& approximatelyEqual (startTime, cachedStart)
&& approximatelyEqual (timePerPixel, cachedTimePerPixel)
&& ! cacheNeedsRefilling) && ! cacheNeedsRefilling)
{ {
return ! cacheNeedsRefilling; return ! cacheNeedsRefilling;


+ 5
- 5
modules/juce_audio_utils/gui/juce_KeyboardComponentBase.cpp View File

@@ -79,7 +79,7 @@ void KeyboardComponentBase::setKeyWidth (float widthInPixels)
{ {
jassert (widthInPixels > 0); jassert (widthInPixels > 0);
if (keyWidth != widthInPixels) // Prevent infinite recursion if the width is being computed in a 'resized()' callback
if (! approximatelyEqual (keyWidth, widthInPixels)) // Prevent infinite recursion if the width is being computed in a 'resized()' callback
{ {
keyWidth = widthInPixels; keyWidth = widthInPixels;
resized(); resized();
@@ -130,7 +130,7 @@ void KeyboardComponentBase::setLowestVisibleKeyFloat (float noteNumber)
{ {
noteNumber = jlimit ((float) rangeStart, (float) rangeEnd, noteNumber); noteNumber = jlimit ((float) rangeStart, (float) rangeEnd, noteNumber);
if (noteNumber != firstKey)
if (! approximatelyEqual (noteNumber, firstKey))
{ {
bool hasMoved = (((int) firstKey) != (int) noteNumber); bool hasMoved = (((int) firstKey) != (int) noteNumber);
firstKey = noteNumber; firstKey = noteNumber;
@@ -151,7 +151,7 @@ void KeyboardComponentBase::setBlackNoteLengthProportion (float ratio) noexcept
{ {
jassert (ratio >= 0.0f && ratio <= 1.0f); jassert (ratio >= 0.0f && ratio <= 1.0f);
if (blackNoteLengthRatio != ratio)
if (! approximatelyEqual (blackNoteLengthRatio, ratio))
{ {
blackNoteLengthRatio = ratio; blackNoteLengthRatio = ratio;
resized(); resized();
@@ -168,7 +168,7 @@ void KeyboardComponentBase::setBlackNoteWidthProportion (float ratio) noexcept
{ {
jassert (ratio >= 0.0f && ratio <= 1.0f); jassert (ratio >= 0.0f && ratio <= 1.0f);
if (blackNoteWidthRatio != ratio)
if (! approximatelyEqual (blackNoteWidthRatio, ratio))
{ {
blackNoteWidthRatio = ratio; blackNoteWidthRatio = ratio;
resized(); resized();
@@ -452,7 +452,7 @@ void KeyboardComponentBase::resized()
//============================================================================== //==============================================================================
void KeyboardComponentBase::mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel) void KeyboardComponentBase::mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel)
{ {
auto amount = (orientation == horizontalKeyboard && wheel.deltaX != 0)
auto amount = (orientation == horizontalKeyboard && ! approximatelyEqual (wheel.deltaX, 0.0f))
? wheel.deltaX : (orientation == verticalKeyboardFacingLeft ? wheel.deltaY ? wheel.deltaX : (orientation == verticalKeyboardFacingLeft ? wheel.deltaY
: -wheel.deltaY); : -wheel.deltaY);


+ 7
- 6
modules/juce_box2d/juce_box2d.cpp View File

@@ -35,15 +35,16 @@
#include "juce_box2d.h" #include "juce_box2d.h"
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011) JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6011)
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
"-Wsign-conversion",
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align",
"-Wconversion",
"-Wfloat-conversion", "-Wfloat-conversion",
"-Wcast-align",
"-Wswitch-enum",
"-Wfloat-equal",
"-Wmaybe-uninitialized",
"-Wsign-conversion",
"-Wswitch-default", "-Wswitch-default",
"-Wswitch-enum",
"-Wunused-but-set-variable", "-Wunused-but-set-variable",
"-Wzero-as-null-pointer-constant",
"-Wmaybe-uninitialized")
"-Wzero-as-null-pointer-constant")
#include <cstdarg> #include <cstdarg>


+ 4
- 3
modules/juce_box2d/juce_box2d.h View File

@@ -56,11 +56,12 @@
#include <juce_graphics/juce_graphics.h> #include <juce_graphics/juce_graphics.h>
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion", JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
"-Wdeprecated",
"-Wfloat-equal",
"-Wmaybe-uninitialized",
"-Wshadow-field", "-Wshadow-field",
"-Wzero-as-null-pointer-constant",
"-Wsign-conversion", "-Wsign-conversion",
"-Wdeprecated",
"-Wmaybe-uninitialized")
"-Wzero-as-null-pointer-constant")
#include <climits> #include <climits>
#include <cfloat> #include <cfloat>


+ 1
- 1
modules/juce_core/containers/juce_Array.h View File

@@ -404,7 +404,7 @@ public:
auto endPtr = values.end(); auto endPtr = values.end();
for (; e != endPtr; ++e) for (; e != endPtr; ++e)
if (elementToLookFor == *e)
if (exactlyEqual (elementToLookFor, *e))
return true; return true;
return false; return false;


+ 1
- 1
modules/juce_core/containers/juce_ArrayBase.h View File

@@ -123,7 +123,7 @@ public:
auto* e = begin(); auto* e = begin();
for (auto& o : other) for (auto& o : other)
if (! (*e++ == o))
if (! exactlyEqual (*e++, o))
return false; return false;
return true; return true;


+ 2
- 2
modules/juce_core/containers/juce_Variant.cpp View File

@@ -201,7 +201,7 @@ struct var::VariantType
static int64 doubleToInt64 (const ValueUnion& data) noexcept { return (int64) data.doubleValue; } static int64 doubleToInt64 (const ValueUnion& data) noexcept { return (int64) data.doubleValue; }
static double doubleToDouble (const ValueUnion& data) noexcept { return data.doubleValue; } static double doubleToDouble (const ValueUnion& data) noexcept { return data.doubleValue; }
static String doubleToString (const ValueUnion& data) { return serialiseDouble (data.doubleValue); } static String doubleToString (const ValueUnion& data) { return serialiseDouble (data.doubleValue); }
static bool doubleToBool (const ValueUnion& data) noexcept { return data.doubleValue != 0.0; }
static bool doubleToBool (const ValueUnion& data) noexcept { return ! exactlyEqual (data.doubleValue, 0.0); }
static bool doubleEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept static bool doubleEquals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) noexcept
{ {
@@ -645,7 +645,7 @@ static int compare (const var& v1, const var& v2)
return v1.toString().compare (v2.toString()); return v1.toString().compare (v2.toString());
auto diff = static_cast<double> (v1) - static_cast<double> (v2); auto diff = static_cast<double> (v1) - static_cast<double> (v2);
return diff == 0 ? 0 : (diff < 0 ? -1 : 1);
return exactlyEqual (diff, 0.0) ? 0 : (diff < 0 ? -1 : 1);
} }
bool operator== (const var& v1, const var& v2) { return v1.equals (v2); } bool operator== (const var& v1, const var& v2) { return v1.equals (v2); }


+ 4
- 4
modules/juce_core/javascript/juce_Javascript.cpp View File

@@ -520,7 +520,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
{ {
EqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {} EqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::equals) {}
var getWithUndefinedArg() const override { return true; } var getWithUndefinedArg() const override { return true; }
var getWithDoubles (double a, double b) const override { return a == b; }
var getWithDoubles (double a, double b) const override { return exactlyEqual (a, b); }
var getWithInts (int64 a, int64 b) const override { return a == b; } var getWithInts (int64 a, int64 b) const override { return a == b; }
var getWithStrings (const String& a, const String& b) const override { return a == b; } var getWithStrings (const String& a, const String& b) const override { return a == b; }
var getWithArrayOrObject (const var& a, const var& b) const override { return a == b; } var getWithArrayOrObject (const var& a, const var& b) const override { return a == b; }
@@ -530,7 +530,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
{ {
NotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {} NotEqualsOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::notEquals) {}
var getWithUndefinedArg() const override { return false; } var getWithUndefinedArg() const override { return false; }
var getWithDoubles (double a, double b) const override { return a != b; }
var getWithDoubles (double a, double b) const override { return ! exactlyEqual (a, b); }
var getWithInts (int64 a, int64 b) const override { return a != b; } var getWithInts (int64 a, int64 b) const override { return a != b; }
var getWithStrings (const String& a, const String& b) const override { return a != b; } var getWithStrings (const String& a, const String& b) const override { return a != b; }
var getWithArrayOrObject (const var& a, const var& b) const override { return a != b; } var getWithArrayOrObject (const var& a, const var& b) const override { return a != b; }
@@ -593,14 +593,14 @@ struct JavascriptEngine::RootObject : public DynamicObject
struct DivideOp : public BinaryOperator struct DivideOp : public BinaryOperator
{ {
DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {} DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {}
var getWithDoubles (double a, double b) const override { return b != 0 ? a / b : std::numeric_limits<double>::infinity(); }
var getWithDoubles (double a, double b) const override { return exactlyEqual (b, 0.0) ? std::numeric_limits<double>::infinity() : a / b; }
var getWithInts (int64 a, int64 b) const override { return b != 0 ? var ((double) a / (double) b) : var (std::numeric_limits<double>::infinity()); } var getWithInts (int64 a, int64 b) const override { return b != 0 ? var ((double) a / (double) b) : var (std::numeric_limits<double>::infinity()); }
}; };
struct ModuloOp : public BinaryOperator struct ModuloOp : public BinaryOperator
{ {
ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {} ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {}
var getWithDoubles (double a, double b) const override { return b != 0 ? fmod (a, b) : std::numeric_limits<double>::infinity(); }
var getWithDoubles (double a, double b) const override { return exactlyEqual (b, 0.0) ? std::numeric_limits<double>::infinity() : fmod (a, b); }
var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a % b) : var (std::numeric_limits<double>::infinity()); } var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a % b) : var (std::numeric_limits<double>::infinity()); }
}; };


+ 24
- 11
modules/juce_core/maths/juce_MathsFunctions.h View File

@@ -86,6 +86,29 @@ using uint32 = unsigned int;
using ssize_t = pointer_sized_int; using ssize_t = pointer_sized_int;
#endif #endif
/** Returns true if the two numbers are approximately equal. This is useful for floating-point
and double comparisons.
*/
template <typename Type>
bool approximatelyEqual (Type a, Type b) noexcept
{
return std::abs (a - b) <= (std::numeric_limits<Type>::epsilon() * std::max (a, b))
|| std::abs (a - b) < std::numeric_limits<Type>::min();
}
/** Equivalent to operator==, but suppresses float-equality warnings.
This allows code to be explicit about float-equality checks that are known to have the correct
semantics.
*/
template <typename Type>
constexpr bool exactlyEqual (Type a, Type b)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wfloat-equal")
return a == b;
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
//============================================================================== //==============================================================================
// Some indispensable min/max functions // Some indispensable min/max functions
@@ -126,7 +149,7 @@ constexpr Type jmap (Type value0To1, Type targetRangeMin, Type targetRangeMax)
template <typename Type> template <typename Type>
Type jmap (Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax) Type jmap (Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax)
{ {
jassert (sourceRangeMax != sourceRangeMin); // mapping from a range of zero will produce NaN!
jassert (! approximatelyEqual (sourceRangeMax, sourceRangeMin)); // mapping from a range of zero will produce NaN!
return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin); return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin);
} }
@@ -317,16 +340,6 @@ bool isWithin (Type a, Type b, Type tolerance) noexcept
return std::abs (a - b) <= tolerance; return std::abs (a - b) <= tolerance;
} }
/** Returns true if the two numbers are approximately equal. This is useful for floating-point
and double comparisons.
*/
template <typename Type>
bool approximatelyEqual (Type a, Type b) noexcept
{
return std::abs (a - b) <= (std::numeric_limits<Type>::epsilon() * std::max (a, b))
|| std::abs (a - b) < std::numeric_limits<Type>::min();
}
//============================================================================== //==============================================================================
/** Handy function for avoiding unused variables warning. */ /** Handy function for avoiding unused variables warning. */
template <typename... Types> template <typename... Types>


+ 4
- 4
modules/juce_core/maths/juce_NormalisableRange.h View File

@@ -128,7 +128,7 @@ public:
auto proportion = clampTo0To1 ((v - start) / (end - start)); auto proportion = clampTo0To1 ((v - start) / (end - start));
if (skew == static_cast<ValueType> (1))
if (exactlyEqual (skew, static_cast<ValueType> (1)))
return proportion; return proportion;
if (! symmetricSkew) if (! symmetricSkew)
@@ -154,7 +154,7 @@ public:
if (! symmetricSkew) if (! symmetricSkew)
{ {
if (skew != static_cast<ValueType> (1) && proportion > ValueType())
if (! exactlyEqual (skew, static_cast<ValueType> (1)) && proportion > ValueType())
proportion = std::exp (std::log (proportion) / skew); proportion = std::exp (std::log (proportion) / skew);
return start + (end - start) * proportion; return start + (end - start) * proportion;
@@ -162,7 +162,7 @@ public:
auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1); auto distanceFromMiddle = static_cast<ValueType> (2) * proportion - static_cast<ValueType> (1);
if (skew != static_cast<ValueType> (1) && distanceFromMiddle != static_cast<ValueType> (0))
if (! exactlyEqual (skew, static_cast<ValueType> (1)) && ! exactlyEqual (distanceFromMiddle, static_cast<ValueType> (0)))
distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew) distanceFromMiddle = std::exp (std::log (std::abs (distanceFromMiddle)) / skew)
* (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1) * (distanceFromMiddle < ValueType() ? static_cast<ValueType> (-1)
: static_cast<ValueType> (1)); : static_cast<ValueType> (1));
@@ -250,7 +250,7 @@ private:
// If you hit this assertion then either your normalisation function is not working // If you hit this assertion then either your normalisation function is not working
// correctly or your input is out of the expected bounds. // correctly or your input is out of the expected bounds.
jassert (clampedValue == value);
jassert (exactlyEqual (clampedValue, value));
return clampedValue; return clampedValue;
} }


+ 1
- 1
modules/juce_core/maths/juce_Random.cpp View File

@@ -103,7 +103,7 @@ float Random::nextFloat() noexcept
{ {
auto result = static_cast<float> (static_cast<uint32> (nextInt())) auto result = static_cast<float> (static_cast<uint32> (nextInt()))
/ (static_cast<float> (std::numeric_limits<uint32>::max()) + 1.0f); / (static_cast<float> (std::numeric_limits<uint32>::max()) + 1.0f);
return result == 1.0f ? 1.0f - std::numeric_limits<float>::epsilon() : result;
return jmin (result, 1.0f - std::numeric_limits<float>::epsilon());
} }
double Random::nextDouble() noexcept double Random::nextDouble() noexcept


+ 8
- 3
modules/juce_core/maths/juce_Range.h View File

@@ -86,7 +86,7 @@ public:
constexpr inline ValueType getEnd() const noexcept { return end; } constexpr inline ValueType getEnd() const noexcept { return end; }
/** Returns true if the range has a length of zero. */ /** Returns true if the range has a length of zero. */
constexpr inline bool isEmpty() const noexcept { return start == end; }
constexpr inline bool isEmpty() const noexcept { return exactlyEqual (start, end); }
//============================================================================== //==============================================================================
/** Changes the start position of the range, leaving the end position unchanged. /** Changes the start position of the range, leaving the end position unchanged.
@@ -198,8 +198,13 @@ public:
return Range (start - amountToSubtract, end - amountToSubtract); return Range (start - amountToSubtract, end - amountToSubtract);
} }
constexpr bool operator== (Range other) const noexcept { return start == other.start && end == other.end; }
constexpr bool operator!= (Range other) const noexcept { return start != other.start || end != other.end; }
constexpr bool operator== (Range other) const noexcept
{
const auto tie = [] (const Range& r) { return std::tie (r.start, r.end); };
return tie (*this) == tie (other);
}
constexpr bool operator!= (Range other) const noexcept { return ! operator== (other); }
//============================================================================== //==============================================================================
/** Returns true if the given position lies inside this range. /** Returns true if the given position lies inside this range.


+ 2
- 2
modules/juce_core/streams/juce_MemoryInputStream.cpp View File

@@ -138,8 +138,8 @@ public:
expectEquals (mi.readString(), randomString); expectEquals (mi.readString(), randomString);
expect (mi.readInt64() == randomInt64); expect (mi.readInt64() == randomInt64);
expect (mi.readInt64BigEndian() == randomInt64); expect (mi.readInt64BigEndian() == randomInt64);
expect (mi.readDouble() == randomDouble);
expect (mi.readDoubleBigEndian() == randomDouble);
expectEquals (mi.readDouble(), randomDouble);
expectEquals (mi.readDoubleBigEndian(), randomDouble);
const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26); const MemoryBlock data ("abcdefghijklmnopqrstuvwxyz", 26);
MemoryInputStream stream (data, true); MemoryInputStream stream (data, true);


+ 22
- 1
modules/juce_core/system/juce_CompilerWarnings.h View File

@@ -31,7 +31,8 @@
#define JUCE_NTH_ARG_(_00, _01, _02, _03, _04, _05, _06, _07, _08, _09, \ #define JUCE_NTH_ARG_(_00, _01, _02, _03, _04, _05, _06, _07, _08, _09, \
_10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
_20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
_30, _31, _32, _33, _34, _35, _36, _37, _38, _39, N, ...)\
_30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
_40, _41, _42, _43, _44, _45, _46, _47, _48, _49, N, ...)\
N N
#define JUCE_EACH_00_(FN) #define JUCE_EACH_00_(FN)
@@ -74,10 +75,30 @@
#define JUCE_EACH_37_(FN, X, ...) FN(X) JUCE_EACH_36_(FN, __VA_ARGS__) #define JUCE_EACH_37_(FN, X, ...) FN(X) JUCE_EACH_36_(FN, __VA_ARGS__)
#define JUCE_EACH_38_(FN, X, ...) FN(X) JUCE_EACH_37_(FN, __VA_ARGS__) #define JUCE_EACH_38_(FN, X, ...) FN(X) JUCE_EACH_37_(FN, __VA_ARGS__)
#define JUCE_EACH_39_(FN, X, ...) FN(X) JUCE_EACH_38_(FN, __VA_ARGS__) #define JUCE_EACH_39_(FN, X, ...) FN(X) JUCE_EACH_38_(FN, __VA_ARGS__)
#define JUCE_EACH_40_(FN, X, ...) FN(X) JUCE_EACH_39_(FN, __VA_ARGS__)
#define JUCE_EACH_41_(FN, X, ...) FN(X) JUCE_EACH_40_(FN, __VA_ARGS__)
#define JUCE_EACH_42_(FN, X, ...) FN(X) JUCE_EACH_41_(FN, __VA_ARGS__)
#define JUCE_EACH_43_(FN, X, ...) FN(X) JUCE_EACH_42_(FN, __VA_ARGS__)
#define JUCE_EACH_44_(FN, X, ...) FN(X) JUCE_EACH_43_(FN, __VA_ARGS__)
#define JUCE_EACH_45_(FN, X, ...) FN(X) JUCE_EACH_44_(FN, __VA_ARGS__)
#define JUCE_EACH_46_(FN, X, ...) FN(X) JUCE_EACH_45_(FN, __VA_ARGS__)
#define JUCE_EACH_47_(FN, X, ...) FN(X) JUCE_EACH_46_(FN, __VA_ARGS__)
#define JUCE_EACH_48_(FN, X, ...) FN(X) JUCE_EACH_47_(FN, __VA_ARGS__)
#define JUCE_EACH_49_(FN, X, ...) FN(X) JUCE_EACH_48_(FN, __VA_ARGS__)
/** Apply the macro FN to each of the other arguments. */ /** Apply the macro FN to each of the other arguments. */
#define JUCE_EACH(FN, ...) \ #define JUCE_EACH(FN, ...) \
JUCE_NTH_ARG_(, __VA_ARGS__, \ JUCE_NTH_ARG_(, __VA_ARGS__, \
JUCE_EACH_49_, \
JUCE_EACH_48_, \
JUCE_EACH_47_, \
JUCE_EACH_46_, \
JUCE_EACH_45_, \
JUCE_EACH_44_, \
JUCE_EACH_43_, \
JUCE_EACH_42_, \
JUCE_EACH_41_, \
JUCE_EACH_40_, \
JUCE_EACH_39_, \ JUCE_EACH_39_, \
JUCE_EACH_38_, \ JUCE_EACH_38_, \
JUCE_EACH_37_, \ JUCE_EACH_37_, \


+ 1
- 1
modules/juce_core/text/juce_CharacterFunctions.cpp View File

@@ -134,7 +134,7 @@ double CharacterFunctions::mulexp10 (const double value, int exponent) noexcept
if (exponent == 0) if (exponent == 0)
return value; return value;
if (value == 0.0)
if (exactlyEqual (value, 0.0))
return 0; return 0;
const bool negative = (exponent < 0); const bool negative = (exponent < 0);


+ 7
- 7
modules/juce_core/text/juce_String.cpp View File

@@ -2266,7 +2266,7 @@ static String serialiseDouble (double input)
int intInput = (int) input; int intInput = (int) input;
if ((double) intInput == input)
if (exactlyEqual ((double) intInput, input))
return { input, 1 }; return { input, 1 };
auto numberOfDecimalPlaces = [absInput] auto numberOfDecimalPlaces = [absInput]
@@ -2567,16 +2567,16 @@ public:
beginTest ("Numeric conversions"); beginTest ("Numeric conversions");
expect (String().getIntValue() == 0); expect (String().getIntValue() == 0);
expect (String().getDoubleValue() == 0.0);
expect (String().getFloatValue() == 0.0f);
expectEquals (String().getDoubleValue(), 0.0);
expectEquals (String().getFloatValue(), 0.0f);
expect (s.getIntValue() == 12345678); expect (s.getIntValue() == 12345678);
expect (s.getLargeIntValue() == (int64) 12345678); expect (s.getLargeIntValue() == (int64) 12345678);
expect (s.getDoubleValue() == 12345678.0);
expect (s.getFloatValue() == 12345678.0f);
expectEquals (s.getDoubleValue(), 12345678.0);
expectEquals (s.getFloatValue(), 12345678.0f);
expect (String (-1234).getIntValue() == -1234); expect (String (-1234).getIntValue() == -1234);
expect (String ((int64) -1234).getLargeIntValue() == -1234); expect (String ((int64) -1234).getLargeIntValue() == -1234);
expect (String (-1234.56).getDoubleValue() == -1234.56);
expect (String (-1234.56f).getFloatValue() == -1234.56f);
expectEquals (String (-1234.56).getDoubleValue(), -1234.56);
expectEquals (String (-1234.56f).getFloatValue(), -1234.56f);
expect (String (std::numeric_limits<int>::max()).getIntValue() == std::numeric_limits<int>::max()); expect (String (std::numeric_limits<int>::max()).getIntValue() == std::numeric_limits<int>::max());
expect (String (std::numeric_limits<int>::min()).getIntValue() == std::numeric_limits<int>::min()); expect (String (std::numeric_limits<int>::min()).getIntValue() == std::numeric_limits<int>::min());
expect (String (std::numeric_limits<int64>::max()).getLargeIntValue() == std::numeric_limits<int64>::max()); expect (String (std::numeric_limits<int64>::max()).getLargeIntValue() == std::numeric_limits<int64>::max());


+ 1
- 1
modules/juce_core/text/juce_String.h View File

@@ -1117,7 +1117,7 @@ public:
{ {
jassert (numberOfSignificantFigures > 0); jassert (numberOfSignificantFigures > 0);
if (number == 0)
if (exactlyEqual (number, DecimalType()))
{ {
if (numberOfSignificantFigures > 1) if (numberOfSignificantFigures > 1)
{ {


+ 7
- 7
modules/juce_core/threads/juce_Thread.cpp View File

@@ -417,7 +417,7 @@ public:
class AtomicTester class AtomicTester
{ {
public: public:
AtomicTester() {}
AtomicTester() = default;
static void testInteger (UnitTest& test) static void testInteger (UnitTest& test)
{ {
@@ -460,17 +460,17 @@ public:
/* These are some simple test cases to check the atomics - let me know /* These are some simple test cases to check the atomics - let me know
if any of these assertions fail on your system! if any of these assertions fail on your system!
*/ */
test.expect (a.get() == (Type) 101);
test.expect (exactlyEqual (a.get(), (Type) 101));
test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200)); test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
test.expect (a.get() == (Type) 101);
test.expect (exactlyEqual (a.get(), (Type) 101));
test.expect (a.compareAndSetBool ((Type) 200, a.get())); test.expect (a.compareAndSetBool ((Type) 200, a.get()));
test.expect (a.get() == (Type) 200);
test.expect (exactlyEqual (a.get(), (Type) 200));
test.expect (a.exchange ((Type) 300) == (Type) 200);
test.expect (a.get() == (Type) 300);
test.expect (exactlyEqual (a.exchange ((Type) 300), (Type) 200));
test.expect (exactlyEqual (a.get(), (Type) 300));
b = a; b = a;
test.expect (b.get() == a.get());
test.expect (exactlyEqual (b.get(), a.get()));
} }
}; };
}; };


+ 10
- 2
modules/juce_core/time/juce_RelativeTime.cpp View File

@@ -54,8 +54,16 @@ RelativeTime RelativeTime::operator-= (double secs) noexcept { numSeconds
JUCE_API RelativeTime JUCE_CALLTYPE operator+ (RelativeTime t1, RelativeTime t2) noexcept { return t1 += t2; } JUCE_API RelativeTime JUCE_CALLTYPE operator+ (RelativeTime t1, RelativeTime t2) noexcept { return t1 += t2; }
JUCE_API RelativeTime JUCE_CALLTYPE operator- (RelativeTime t1, RelativeTime t2) noexcept { return t1 -= t2; } JUCE_API RelativeTime JUCE_CALLTYPE operator- (RelativeTime t1, RelativeTime t2) noexcept { return t1 -= t2; }
JUCE_API bool JUCE_CALLTYPE operator== (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() == t2.inSeconds(); }
JUCE_API bool JUCE_CALLTYPE operator!= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() != t2.inSeconds(); }
JUCE_API bool JUCE_CALLTYPE operator== (RelativeTime t1, RelativeTime t2) noexcept
{
return exactlyEqual (t1.inSeconds(), t2.inSeconds());
}
JUCE_API bool JUCE_CALLTYPE operator!= (RelativeTime t1, RelativeTime t2) noexcept
{
return ! (t1 == t2);
}
JUCE_API bool JUCE_CALLTYPE operator> (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() > t2.inSeconds(); } JUCE_API bool JUCE_CALLTYPE operator> (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() > t2.inSeconds(); }
JUCE_API bool JUCE_CALLTYPE operator< (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() < t2.inSeconds(); } JUCE_API bool JUCE_CALLTYPE operator< (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() < t2.inSeconds(); }
JUCE_API bool JUCE_CALLTYPE operator>= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() >= t2.inSeconds(); } JUCE_API bool JUCE_CALLTYPE operator>= (RelativeTime t1, RelativeTime t2) noexcept { return t1.inSeconds() >= t2.inSeconds(); }


+ 2
- 2
modules/juce_core/unit_tests/juce_UnitTest.h View File

@@ -150,7 +150,7 @@ public:
template <class ValueType> template <class ValueType>
void expectEquals (ValueType actual, ValueType expected, String failureMessage = String()) void expectEquals (ValueType actual, ValueType expected, String failureMessage = String())
{ {
bool result = actual == expected;
bool result = exactlyEqual (actual, expected);
expectResultAndPrint (actual, expected, result, "", failureMessage); expectResultAndPrint (actual, expected, result, "", failureMessage);
} }
@@ -160,7 +160,7 @@ public:
template <class ValueType> template <class ValueType>
void expectNotEquals (ValueType value, ValueType valueToCompareTo, String failureMessage = String()) void expectNotEquals (ValueType value, ValueType valueToCompareTo, String failureMessage = String())
{ {
bool result = value != valueToCompareTo;
bool result = ! exactlyEqual (value, valueToCompareTo);
expectResultAndPrint (value, valueToCompareTo, result, "unequal to", failureMessage); expectResultAndPrint (value, valueToCompareTo, result, "unequal to", failureMessage);
} }


+ 1
- 1
modules/juce_data_structures/values/juce_CachedValue.h View File

@@ -245,7 +245,7 @@ inline CachedValue<Type>& CachedValue<Type>::operator= (const Type& newValue)
template <typename Type> template <typename Type>
inline void CachedValue<Type>::setValue (const Type& newValue, UndoManager* undoManagerToUse) inline void CachedValue<Type>::setValue (const Type& newValue, UndoManager* undoManagerToUse)
{ {
if (cachedValue != newValue || isUsingDefault())
if (! exactlyEqual (cachedValue, newValue) || isUsingDefault())
{ {
cachedValue = newValue; cachedValue = newValue;
targetTree.setProperty (targetProperty, VariantConverter<Type>::toVar (newValue), undoManagerToUse); targetTree.setProperty (targetProperty, VariantConverter<Type>::toVar (newValue), undoManagerToUse);


+ 88
- 85
modules/juce_dsp/containers/juce_AudioBlock_test.cpp View File

@@ -28,6 +28,9 @@ namespace juce
namespace dsp namespace dsp
{ {
template <typename SampleType>
String& operator<< (String& str, SIMDRegister<SampleType>) { return str; }
template <typename SampleType> template <typename SampleType>
class AudioBlockUnitTests : public UnitTest class AudioBlockUnitTests : public UnitTest
{ {
@@ -79,25 +82,25 @@ public:
resetBlocks(); resetBlocks();
expect (block != otherBlock); expect (block != otherBlock);
expect (block.getSample (0, 0) == SampleType (1.0));
expect (block.getSample (0, 4) == SampleType (5.0));
expect (otherBlock.getSample (0, 0) == SampleType (-1.0));
expect (otherBlock.getSample (0, 3) == SampleType (-4.0));
expectEquals (block.getSample (0, 0), SampleType (1.0));
expectEquals (block.getSample (0, 4), SampleType (5.0));
expectEquals (otherBlock.getSample (0, 0), SampleType (-1.0));
expectEquals (otherBlock.getSample (0, 3), SampleType (-4.0));
block.swap (otherBlock); block.swap (otherBlock);
expect (block != otherBlock); expect (block != otherBlock);
expect (otherBlock.getSample (0, 0) == SampleType (1.0));
expect (otherBlock.getSample (0, 4) == SampleType (5.0));
expect (block.getSample (0, 0) == SampleType (-1.0));
expect (block.getSample (0, 3) == SampleType (-4.0));
expectEquals (otherBlock.getSample (0, 0), SampleType (1.0));
expectEquals (otherBlock.getSample (0, 4), SampleType (5.0));
expectEquals (block.getSample (0, 0), SampleType (-1.0));
expectEquals (block.getSample (0, 3), SampleType (-4.0));
block.swap (otherBlock); block.swap (otherBlock);
expect (block.getSample (0, 0) == SampleType (1.0));
expect (block.getSample (0, 4) == SampleType (5.0));
expect (otherBlock.getSample (0, 0) == SampleType (-1.0));
expect (otherBlock.getSample (0, 3) == SampleType (-4.0));
expectEquals (block.getSample (0, 0), SampleType (1.0));
expectEquals (block.getSample (0, 4), SampleType (5.0));
expectEquals (otherBlock.getSample (0, 0), SampleType (-1.0));
expectEquals (otherBlock.getSample (0, 3), SampleType (-4.0));
} }
beginTest ("Getters and setters"); beginTest ("Getters and setters");
@@ -107,49 +110,49 @@ public:
expectEquals ((int) block.getNumChannels(), (int) data.size()); expectEquals ((int) block.getNumChannels(), (int) data.size());
expectEquals ((int) block.getNumSamples(), numSamples); expectEquals ((int) block.getNumSamples(), numSamples);
expect (block.getChannelPointer (0)[2] == SampleType (3.0));
expectEquals (block.getChannelPointer (0)[2], SampleType (3.0));
block.getChannelPointer (0)[2] = SampleType (999.0); block.getChannelPointer (0)[2] = SampleType (999.0);
expect (block.getChannelPointer (0)[2] == SampleType (999.0));
expectEquals (block.getChannelPointer (0)[2], SampleType (999.0));
expect (block.getSample (0, 4) == SampleType (5.0));
expect (block.getSample (1, 4) == SampleType (11.0));
expectEquals (block.getSample (0, 4), SampleType (5.0));
expectEquals (block.getSample (1, 4), SampleType (11.0));
expect (block.getSingleChannelBlock (1).getSample (0, 3) == block.getSample (1, 3));
expectEquals (block.getSingleChannelBlock (1).getSample (0, 3), block.getSample (1, 3));
expect (block.getSubsetChannelBlock (0, 2).getSample (1, 3) == block.getSample (1, 3));
expect (block.getSubsetChannelBlock (1, 1).getSample (0, 3) == block.getSample (1, 3));
expectEquals (block.getSubsetChannelBlock (0, 2).getSample (1, 3), block.getSample (1, 3));
expectEquals (block.getSubsetChannelBlock (1, 1).getSample (0, 3), block.getSample (1, 3));
block.setSample (1, 1, SampleType (777.0)); block.setSample (1, 1, SampleType (777.0));
expect (block.getSample (1, 1) == SampleType (777.0));
expectEquals (block.getSample (1, 1), SampleType (777.0));
block.addSample (1, 1, SampleType (1.0)); block.addSample (1, 1, SampleType (1.0));
expect (block.getSample (1, 1) == SampleType (778.0));
expectEquals (block.getSample (1, 1), SampleType (778.0));
} }
beginTest ("Basic copying"); beginTest ("Basic copying");
{ {
block.clear(); block.clear();
expect (block.getSample (0, 2) == SampleType (0.0));
expect (block.getSample (1, 4) == SampleType (0.0));
expectEquals (block.getSample (0, 2), SampleType (0.0));
expectEquals (block.getSample (1, 4), SampleType (0.0));
block.fill ((NumericType) 456.0); block.fill ((NumericType) 456.0);
expect (block.getSample (0, 2) == SampleType (456.0));
expect (block.getSample (1, 4) == SampleType (456.0));
expectEquals (block.getSample (0, 2), SampleType (456.0));
expectEquals (block.getSample (1, 4), SampleType (456.0));
block.copyFrom (otherBlock); block.copyFrom (otherBlock);
expect (block != otherBlock); expect (block != otherBlock);
expect (block.getSample (0, 2) == otherBlock.getSample (0, 2));
expect (block.getSample (1, 4) == otherBlock.getSample (1, 4));
expectEquals (block.getSample (0, 2), otherBlock.getSample (0, 2));
expectEquals (block.getSample (1, 4), otherBlock.getSample (1, 4));
resetBlocks(); resetBlocks();
SampleType testSample1 = block.getSample (0, 2); SampleType testSample1 = block.getSample (0, 2);
SampleType testSample2 = block.getSample (1, 3); SampleType testSample2 = block.getSample (1, 3);
expect (testSample1 != block.getSample (0, 4));
expect (testSample2 != block.getSample (1, 5));
expectNotEquals (testSample1, block.getSample (0, 4));
expectNotEquals (testSample2, block.getSample (1, 5));
block.move (0, 2); block.move (0, 2);
expect (block.getSample (0, 4) == testSample1);
expect (block.getSample (1, 5) == testSample2);
expectEquals (block.getSample (0, 4), testSample1);
expectEquals (block.getSample (1, 5), testSample2);
} }
beginTest ("Addition"); beginTest ("Addition");
@@ -157,22 +160,22 @@ public:
resetBlocks(); resetBlocks();
block.add ((NumericType) 15.0); block.add ((NumericType) 15.0);
expect (block.getSample (0, 4) == SampleType (20.0));
expect (block.getSample (1, 4) == SampleType (26.0));
expectEquals (block.getSample (0, 4), SampleType (20.0));
expectEquals (block.getSample (1, 4), SampleType (26.0));
block.add (otherBlock); block.add (otherBlock);
expect (block.getSample (0, 4) == SampleType (15.0));
expect (block.getSample (1, 4) == SampleType (15.0));
expectEquals (block.getSample (0, 4), SampleType (15.0));
expectEquals (block.getSample (1, 4), SampleType (15.0));
block.replaceWithSumOf (otherBlock, (NumericType) 9.0); block.replaceWithSumOf (otherBlock, (NumericType) 9.0);
expect (block.getSample (0, 4) == SampleType (4.0));
expect (block.getSample (1, 4) == SampleType (-2.0));
expectEquals (block.getSample (0, 4), SampleType (4.0));
expectEquals (block.getSample (1, 4), SampleType (-2.0));
resetBlocks(); resetBlocks();
block.replaceWithSumOf (block, otherBlock); block.replaceWithSumOf (block, otherBlock);
expect (block.getSample (0, 4) == SampleType (0.0));
expect (block.getSample (1, 4) == SampleType (0.0));
expectEquals (block.getSample (0, 4), SampleType (0.0));
expectEquals (block.getSample (1, 4), SampleType (0.0));
} }
beginTest ("Subtraction"); beginTest ("Subtraction");
@@ -180,22 +183,22 @@ public:
resetBlocks(); resetBlocks();
block.subtract ((NumericType) 15.0); block.subtract ((NumericType) 15.0);
expect (block.getSample (0, 4) == SampleType (-10.0));
expect (block.getSample (1, 4) == SampleType (-4.0));
expectEquals (block.getSample (0, 4), SampleType (-10.0));
expectEquals (block.getSample (1, 4), SampleType (-4.0));
block.subtract (otherBlock); block.subtract (otherBlock);
expect (block.getSample (0, 4) == SampleType (-5.0));
expect (block.getSample (1, 4) == SampleType (7.0));
expectEquals (block.getSample (0, 4), SampleType (-5.0));
expectEquals (block.getSample (1, 4), SampleType (7.0));
block.replaceWithDifferenceOf (otherBlock, (NumericType) 9.0); block.replaceWithDifferenceOf (otherBlock, (NumericType) 9.0);
expect (block.getSample (0, 4) == SampleType (-14.0));
expect (block.getSample (1, 4) == SampleType (-20.0));
expectEquals (block.getSample (0, 4), SampleType (-14.0));
expectEquals (block.getSample (1, 4), SampleType (-20.0));
resetBlocks(); resetBlocks();
block.replaceWithDifferenceOf (block, otherBlock); block.replaceWithDifferenceOf (block, otherBlock);
expect (block.getSample (0, 4) == SampleType (10.0));
expect (block.getSample (1, 4) == SampleType (22.0));
expectEquals (block.getSample (0, 4), SampleType (10.0));
expectEquals (block.getSample (1, 4), SampleType (22.0));
} }
beginTest ("Multiplication"); beginTest ("Multiplication");
@@ -203,22 +206,22 @@ public:
resetBlocks(); resetBlocks();
block.multiplyBy ((NumericType) 10.0); block.multiplyBy ((NumericType) 10.0);
expect (block.getSample (0, 4) == SampleType (50.0));
expect (block.getSample (1, 4) == SampleType (110.0));
expectEquals (block.getSample (0, 4), SampleType (50.0));
expectEquals (block.getSample (1, 4), SampleType (110.0));
block.multiplyBy (otherBlock); block.multiplyBy (otherBlock);
expect (block.getSample (0, 4) == SampleType (-250.0));
expect (block.getSample (1, 4) == SampleType (-1210.0));
expectEquals (block.getSample (0, 4), SampleType (-250.0));
expectEquals (block.getSample (1, 4), SampleType (-1210.0));
block.replaceWithProductOf (otherBlock, (NumericType) 3.0); block.replaceWithProductOf (otherBlock, (NumericType) 3.0);
expect (block.getSample (0, 4) == SampleType (-15.0));
expect (block.getSample (1, 4) == SampleType (-33.0));
expectEquals (block.getSample (0, 4), SampleType (-15.0));
expectEquals (block.getSample (1, 4), SampleType (-33.0));
resetBlocks(); resetBlocks();
block.replaceWithProductOf (block, otherBlock); block.replaceWithProductOf (block, otherBlock);
expect (block.getSample (0, 4) == SampleType (-25.0));
expect (block.getSample (1, 4) == SampleType (-121.0));
expectEquals (block.getSample (0, 4), SampleType (-25.0));
expectEquals (block.getSample (1, 4), SampleType (-121.0));
} }
beginTest ("Multiply add"); beginTest ("Multiply add");
@@ -226,12 +229,12 @@ public:
resetBlocks(); resetBlocks();
block.addProductOf (otherBlock, (NumericType) -1.0); block.addProductOf (otherBlock, (NumericType) -1.0);
expect (block.getSample (0, 4) == SampleType (10.0));
expect (block.getSample (1, 4) == SampleType (22.0));
expectEquals (block.getSample (0, 4), SampleType (10.0));
expectEquals (block.getSample (1, 4), SampleType (22.0));
block.addProductOf (otherBlock, otherBlock); block.addProductOf (otherBlock, otherBlock);
expect (block.getSample (0, 4) == SampleType (35.0));
expect (block.getSample (1, 4) == SampleType (143.0));
expectEquals (block.getSample (0, 4), SampleType (35.0));
expectEquals (block.getSample (1, 4), SampleType (143.0));
} }
beginTest ("Negative abs min max"); beginTest ("Negative abs min max");
@@ -240,68 +243,68 @@ public:
otherBlock.negate(); otherBlock.negate();
block.add (otherBlock); block.add (otherBlock);
expect (block.getSample (0, 4) == SampleType (10.0));
expect (block.getSample (1, 4) == SampleType (22.0));
expectEquals (block.getSample (0, 4), SampleType (10.0));
expectEquals (block.getSample (1, 4), SampleType (22.0));
block.replaceWithNegativeOf (otherBlock); block.replaceWithNegativeOf (otherBlock);
expect (block.getSample (0, 4) == SampleType (-5.0));
expect (block.getSample (1, 4) == SampleType (-11.0));
expectEquals (block.getSample (0, 4), SampleType (-5.0));
expectEquals (block.getSample (1, 4), SampleType (-11.0));
block.clear(); block.clear();
otherBlock.negate(); otherBlock.negate();
block.replaceWithAbsoluteValueOf (otherBlock); block.replaceWithAbsoluteValueOf (otherBlock);
expect (block.getSample (0, 4) == SampleType (5.0));
expect (block.getSample (1, 4) == SampleType (11.0));
expectEquals (block.getSample (0, 4), SampleType (5.0));
expectEquals (block.getSample (1, 4), SampleType (11.0));
resetBlocks(); resetBlocks();
block.replaceWithMinOf (block, otherBlock); block.replaceWithMinOf (block, otherBlock);
expect (block.getSample (0, 4) == SampleType (-5.0));
expect (block.getSample (1, 4) == SampleType (-11.0));
expectEquals (block.getSample (0, 4), SampleType (-5.0));
expectEquals (block.getSample (1, 4), SampleType (-11.0));
resetBlocks(); resetBlocks();
block.replaceWithMaxOf (block, otherBlock); block.replaceWithMaxOf (block, otherBlock);
expect (block.getSample (0, 4) == SampleType (5.0));
expect (block.getSample (1, 4) == SampleType (11.0));
expectEquals (block.getSample (0, 4), SampleType (5.0));
expectEquals (block.getSample (1, 4), SampleType (11.0));
resetBlocks(); resetBlocks();
auto range = block.findMinAndMax(); auto range = block.findMinAndMax();
expect (SampleType (range.getStart()) == SampleType (1.0));
expect (SampleType (range.getEnd()) == SampleType (12.0));
expectEquals (SampleType (range.getStart()), SampleType (1.0));
expectEquals (SampleType (range.getEnd()), SampleType (12.0));
} }
beginTest ("Operators"); beginTest ("Operators");
{ {
resetBlocks(); resetBlocks();
block += (NumericType) 10.0; block += (NumericType) 10.0;
expect (block.getSample (0, 4) == SampleType (15.0));
expect (block.getSample (1, 4) == SampleType (21.0));
expectEquals (block.getSample (0, 4), SampleType (15.0));
expectEquals (block.getSample (1, 4), SampleType (21.0));
block += otherBlock; block += otherBlock;
expect (block.getSample (0, 4) == SampleType (10.0));
expect (block.getSample (1, 4) == SampleType (10.0));
expectEquals (block.getSample (0, 4), SampleType (10.0));
expectEquals (block.getSample (1, 4), SampleType (10.0));
resetBlocks(); resetBlocks();
block -= (NumericType) 10.0; block -= (NumericType) 10.0;
expect (block.getSample (0, 4) == SampleType (-5.0));
expect (block.getSample (1, 4) == SampleType (1.0));
expectEquals (block.getSample (0, 4), SampleType (-5.0));
expectEquals (block.getSample (1, 4), SampleType (1.0));
block -= otherBlock; block -= otherBlock;
expect (block.getSample (0, 4) == SampleType (0.0));
expect (block.getSample (1, 4) == SampleType (12.0));
expectEquals (block.getSample (0, 4), SampleType (0.0));
expectEquals (block.getSample (1, 4), SampleType (12.0));
resetBlocks(); resetBlocks();
block *= (NumericType) 10.0; block *= (NumericType) 10.0;
expect (block.getSample (0, 4) == SampleType (50.0));
expect (block.getSample (1, 4) == SampleType (110.0));
expectEquals (block.getSample (0, 4), SampleType (50.0));
expectEquals (block.getSample (1, 4), SampleType (110.0));
block *= otherBlock; block *= otherBlock;
expect (block.getSample (0, 4) == SampleType (-250.0));
expect (block.getSample (1, 4) == SampleType (-1210.0));
expectEquals (block.getSample (0, 4), SampleType (-250.0));
expectEquals (block.getSample (1, 4), SampleType (-1210.0));
} }
beginTest ("Process"); beginTest ("Process");
{ {
resetBlocks(); resetBlocks();
AudioBlock<SampleType>::process (block, otherBlock, [] (SampleType x) { return x + (NumericType) 1.0; }); AudioBlock<SampleType>::process (block, otherBlock, [] (SampleType x) { return x + (NumericType) 1.0; });
expect (otherBlock.getSample (0, 4) == SampleType (6.0));
expect (otherBlock.getSample (1, 4) == SampleType (12.0));
expectEquals (otherBlock.getSample (0, 4), SampleType (6.0));
expectEquals (otherBlock.getSample (1, 4), SampleType (12.0));
} }
beginTest ("Copying"); beginTest ("Copying");


+ 5
- 12
modules/juce_dsp/containers/juce_SIMDRegister_test.cpp View File

@@ -117,19 +117,12 @@ public:
template <typename type> template <typename type>
static bool allValuesEqualTo (const SIMDRegister<type>& vec, const type scalar) static bool allValuesEqualTo (const SIMDRegister<type>& vec, const type scalar)
{ {
#ifdef _MSC_VER
__declspec(align(sizeof (SIMDRegister<type>))) type elements[SIMDRegister<type>::SIMDNumElements];
#else
type elements[SIMDRegister<type>::SIMDNumElements] __attribute__((aligned(sizeof (SIMDRegister<type>))));
#endif
alignas (sizeof (SIMDRegister<type>)) type elements[SIMDRegister<type>::SIMDNumElements];
vec.copyToRawArray (elements); vec.copyToRawArray (elements);
// as we do not want to rely on the access operator we cast this to a primitive pointer // as we do not want to rely on the access operator we cast this to a primitive pointer
for (size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
if (elements[i] != scalar) return false;
return true;
return std::all_of (std::begin (elements), std::end (elements), [scalar] (const auto x) { return exactlyEqual (x, scalar); });
} }
template <typename type> template <typename type>
@@ -307,7 +300,7 @@ public:
const SIMDRegister<type>& b = a; const SIMDRegister<type>& b = a;
for (size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i) for (size_t i = 0; i < SIMDRegister<type>::SIMDNumElements; ++i)
u.expect (b[i] == array[i]);
u.expect (exactlyEqual (b[i], array[i]));
} }
}; };
@@ -539,8 +532,8 @@ public:
// do check // do check
for (size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j) for (size_t j = 0; j < SIMDRegister<type>::SIMDNumElements; ++j)
{ {
array_eq [j] = (array_a[j] == array_b[j]) ? static_cast<MaskType> (-1) : 0;
array_neq [j] = (array_a[j] != array_b[j]) ? static_cast<MaskType> (-1) : 0;
array_eq [j] = ( exactlyEqual (array_a[j], array_b[j])) ? static_cast<MaskType> (-1) : 0;
array_neq [j] = (! exactlyEqual (array_a[j], array_b[j])) ? static_cast<MaskType> (-1) : 0;
array_lt [j] = (array_a[j] < array_b[j]) ? static_cast<MaskType> (-1) : 0; array_lt [j] = (array_a[j] < array_b[j]) ? static_cast<MaskType> (-1) : 0;
array_le [j] = (array_a[j] <= array_b[j]) ? static_cast<MaskType> (-1) : 0; array_le [j] = (array_a[j] <= array_b[j]) ? static_cast<MaskType> (-1) : 0;
array_gt [j] = (array_a[j] > array_b[j]) ? static_cast<MaskType> (-1) : 0; array_gt [j] = (array_a[j] > array_b[j]) ? static_cast<MaskType> (-1) : 0;


+ 5
- 6
modules/juce_dsp/filter_design/juce_FilterDesign.cpp View File

@@ -145,6 +145,11 @@ typename FIR::Coefficients<FloatType>::Ptr
auto* result = new typename FIR::Coefficients<FloatType> (static_cast<size_t> (N)); auto* result = new typename FIR::Coefficients<FloatType> (static_cast<size_t> (N));
auto* c = result->getRawCoefficients(); auto* c = result->getRawCoefficients();
auto sinc = [] (double x)
{
return approximatelyEqual (x, 0.0) ? 1 : std::sin (x * MathConstants<double>::pi) / (MathConstants<double>::pi * x);
};
if (N % 2 == 1) if (N % 2 == 1)
{ {
// Type I // Type I
@@ -153,9 +158,6 @@ typename FIR::Coefficients<FloatType>::Ptr
Matrix<double> b (M + 1, 1), Matrix<double> b (M + 1, 1),
q (2 * M + 1, 1); q (2 * M + 1, 1);
auto sinc = [] (double x) { return x == 0 ? 1 : std::sin (x * MathConstants<double>::pi)
/ (MathConstants<double>::pi * x); };
auto factorp = wp / MathConstants<double>::pi; auto factorp = wp / MathConstants<double>::pi;
auto factors = ws / MathConstants<double>::pi; auto factors = ws / MathConstants<double>::pi;
@@ -191,9 +193,6 @@ typename FIR::Coefficients<FloatType>::Ptr
Matrix<double> qp (2 * M, 1); Matrix<double> qp (2 * M, 1);
Matrix<double> qs (2 * M, 1); Matrix<double> qs (2 * M, 1);
auto sinc = [] (double x) { return x == 0 ? 1 : std::sin (x * MathConstants<double>::pi)
/ (MathConstants<double>::pi * x); };
auto factorp = wp / MathConstants<double>::pi; auto factorp = wp / MathConstants<double>::pi;
auto factors = ws / MathConstants<double>::pi; auto factors = ws / MathConstants<double>::pi;


+ 1
- 1
modules/juce_dsp/frequency/juce_Convolution.cpp View File

@@ -647,7 +647,7 @@ static AudioBuffer<float> resampleImpulseResponse (const AudioBuffer<float>& buf
const double srcSampleRate, const double srcSampleRate,
const double destSampleRate) const double destSampleRate)
{ {
if (srcSampleRate == destSampleRate)
if (approximatelyEqual (srcSampleRate, destSampleRate))
return buf; return buf;
const auto factorReading = srcSampleRate / destSampleRate; const auto factorReading = srcSampleRate / destSampleRate;


+ 2
- 2
modules/juce_dsp/frequency/juce_Convolution_test.cpp View File

@@ -97,7 +97,7 @@ class ConvolutionTest : public UnitTest
expect (std::any_of (channel, channel + block.getNumSamples(), [] (float sample) expect (std::any_of (channel, channel + block.getNumSamples(), [] (float sample)
{ {
return sample != 0.0f;
return ! approximatelyEqual (sample, 0.0f);
})); }));
} }
} }
@@ -193,7 +193,7 @@ class ConvolutionTest : public UnitTest
processBlocksWithDiracImpulse(); processBlocksWithDiracImpulse();
// Check if the impulse response was loaded // Check if the impulse response was loaded
if (block.getSample (0, 1) != 0.0f)
if (! approximatelyEqual (block.getSample (0, 1), 0.0f))
break; break;
} }
} }


+ 1
- 1
modules/juce_dsp/maths/juce_LogRampedValue.h View File

@@ -108,7 +108,7 @@ public:
*/ */
void setTargetValue (FloatType newValue) noexcept void setTargetValue (FloatType newValue) noexcept
{ {
if (newValue == this->target)
if (approximatelyEqual (newValue, this->target))
return; return;
if (stepsToTarget <= 0) if (stepsToTarget <= 0)


+ 5
- 5
modules/juce_dsp/maths/juce_Matrix.cpp View File

@@ -176,7 +176,7 @@ bool Matrix<ElementType>::solve (Matrix& b) const noexcept
{ {
auto denominator = A (0,0); auto denominator = A (0,0);
if (denominator == 0)
if (approximatelyEqual (denominator, (ElementType) 0))
return false; return false;
b (0, 0) /= denominator; b (0, 0) /= denominator;
@@ -187,7 +187,7 @@ bool Matrix<ElementType>::solve (Matrix& b) const noexcept
{ {
auto denominator = A (0, 0) * A (1, 1) - A (0, 1) * A (1, 0); auto denominator = A (0, 0) * A (1, 1) - A (0, 1) * A (1, 0);
if (denominator == 0)
if (approximatelyEqual (denominator, (ElementType) 0))
return false; return false;
auto factor = (1 / denominator); auto factor = (1 / denominator);
@@ -204,7 +204,7 @@ bool Matrix<ElementType>::solve (Matrix& b) const noexcept
+ A (0, 1) * (A (1, 2) * A (2, 0) - A (1, 0) * A (2, 2)) + A (0, 1) * (A (1, 2) * A (2, 0) - A (1, 0) * A (2, 2))
+ A (0, 2) * (A (1, 0) * A (2, 1) - A (1, 1) * A (2, 0)); + A (0, 2) * (A (1, 0) * A (2, 1) - A (1, 1) * A (2, 0));
if (denominator == 0)
if (approximatelyEqual (denominator, (ElementType) 0))
return false; return false;
auto factor = 1 / denominator; auto factor = 1 / denominator;
@@ -231,10 +231,10 @@ bool Matrix<ElementType>::solve (Matrix& b) const noexcept
for (size_t j = 0; j < n; ++j) for (size_t j = 0; j < n; ++j)
{ {
if (M (j, j) == 0)
if (approximatelyEqual (M (j, j), (ElementType) 0))
{ {
auto i = j; auto i = j;
while (i < n && M (i, j) == 0)
while (i < n && approximatelyEqual (M (i, j), (ElementType) 0))
++i; ++i;
if (i == n) if (i == n)


+ 1
- 1
modules/juce_dsp/processors/juce_DelayLine.h View File

@@ -271,7 +271,7 @@ private:
auto value1 = bufferData.getSample (channel, index1); auto value1 = bufferData.getSample (channel, index1);
auto value2 = bufferData.getSample (channel, index2); auto value2 = bufferData.getSample (channel, index2);
auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);
auto output = approximatelyEqual (delayFrac, (SampleType) 0) ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);
v[(size_t) channel] = output; v[(size_t) channel] = output;
return output; return output;


+ 3
- 2
modules/juce_dsp/processors/juce_IIRFilter_Impl.h View File

@@ -39,8 +39,9 @@ Coefficients<NumericType>& Coefficients<NumericType>::assignImpl (const NumericT
static_assert (Num % 2 == 0, "Must supply an even number of coefficients"); static_assert (Num % 2 == 0, "Must supply an even number of coefficients");
const auto a0Index = Num / 2; const auto a0Index = Num / 2;
const auto a0 = values[a0Index]; const auto a0 = values[a0Index];
const auto a0Inv = a0 != NumericType() ? static_cast<NumericType> (1) / values[a0Index]
: NumericType();
const auto a0Inv = ! approximatelyEqual (a0, NumericType())
? static_cast<NumericType> (1) / values[a0Index]
: NumericType();
coefficients.clearQuick(); coefficients.clearQuick();
coefficients.ensureStorageAllocated ((int) jmax ((size_t) 8, Num)); coefficients.ensureStorageAllocated ((int) jmax ((size_t) 8, Num));


+ 1
- 1
modules/juce_dsp/processors/juce_Oversampling.cpp View File

@@ -755,7 +755,7 @@ void Oversampling<SampleType>::updateDelayLine()
auto latency = getUncompensatedLatency(); auto latency = getUncompensatedLatency();
fractionalDelay = static_cast<SampleType> (1.0) - (latency - std::floor (latency)); fractionalDelay = static_cast<SampleType> (1.0) - (latency - std::floor (latency));
if (fractionalDelay == static_cast<SampleType> (1.0))
if (approximatelyEqual (fractionalDelay, static_cast<SampleType> (1.0)))
fractionalDelay = static_cast<SampleType> (0.0); fractionalDelay = static_cast<SampleType> (0.0);
else if (fractionalDelay < static_cast<SampleType> (0.618)) else if (fractionalDelay < static_cast<SampleType> (0.618))
fractionalDelay += static_cast<SampleType> (1.0); fractionalDelay += static_cast<SampleType> (1.0);


+ 6
- 3
modules/juce_dsp/processors/juce_ProcessContext.h View File

@@ -48,9 +48,12 @@ struct ProcessSpec
constexpr bool operator== (const ProcessSpec& a, const ProcessSpec& b) constexpr bool operator== (const ProcessSpec& a, const ProcessSpec& b)
{ {
return a.sampleRate == b.sampleRate
&& a.maximumBlockSize == b.maximumBlockSize
&& a.numChannels == b.numChannels;
const auto tie = [] (const ProcessSpec& p)
{
return std::tie (p.sampleRate, p.maximumBlockSize, p.numChannels);
};
return tie (a) == tie (b);
} }
constexpr bool operator!= (const ProcessSpec& a, const ProcessSpec& b) { return ! (a == b); } constexpr bool operator!= (const ProcessSpec& a, const ProcessSpec& b) { return ! (a == b); }


+ 1
- 1
modules/juce_dsp/processors/juce_ProcessorChain_test.cpp View File

@@ -39,7 +39,7 @@ class ProcessorChainTest : public UnitTest
template <typename Context> template <typename Context>
void process (const Context& context) noexcept void process (const Context& context) noexcept
{ {
bufferWasClear = context.getInputBlock().getSample (0, 0) == 0;
bufferWasClear = approximatelyEqual (context.getInputBlock().getSample (0, 0), 0.0f);
if (! context.isBypassed) if (! context.isBypassed)
context.getOutputBlock().add (AddValue); context.getOutputBlock().add (AddValue);


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save