diff --git a/examples/DSP module plugin demo/DSP module plugin demo.jucer b/examples/DSP module plugin demo/DSP module plugin demo.jucer index 67e37a1318..839660664f 100644 --- a/examples/DSP module plugin demo/DSP module plugin demo.jucer +++ b/examples/DSP module plugin demo/DSP module plugin demo.jucer @@ -125,5 +125,5 @@ - + diff --git a/examples/DSP module plugin demo/JuceLibraryCode/AppConfig.h b/examples/DSP module plugin demo/JuceLibraryCode/AppConfig.h index 69c1fbf2cb..31d8d119c3 100644 --- a/examples/DSP module plugin demo/JuceLibraryCode/AppConfig.h +++ b/examples/DSP module plugin demo/JuceLibraryCode/AppConfig.h @@ -130,6 +130,10 @@ //#define JUCE_FORCE_USE_LEGACY_PARAM_IDS 1 #endif +#ifndef JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE + //#define JUCE_FORCE_LEGACY_PARAMETER_AUTOMATION_TYPE 1 +#endif + #ifndef JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS //#define JUCE_USE_STUDIO_ONE_COMPATIBLE_PARAMETERS 1 #endif @@ -214,6 +218,10 @@ //#define JUCE_DSP_USE_STATIC_FFTW 1 #endif +#ifndef JUCE_DSP_ENABLE_SNAP_TO_ZERO + #define JUCE_DSP_ENABLE_SNAP_TO_ZERO 0 +#endif + //============================================================================== // juce_events flags: diff --git a/examples/DSP module plugin demo/Source/PluginProcessor.cpp b/examples/DSP module plugin demo/Source/PluginProcessor.cpp index 8e9ac479ac..389776a3c8 100644 --- a/examples/DSP module plugin demo/Source/PluginProcessor.cpp +++ b/examples/DSP module plugin demo/Source/PluginProcessor.cpp @@ -114,6 +114,8 @@ void DspModulePluginDemoAudioProcessor::releaseResources() void DspModulePluginDemoAudioProcessor::process (dsp::ProcessContextReplacing context) noexcept { + ScopedNoDenormals noDenormals; + // Input volume applied with a LinearSmoothedValue inputVolume.process (context); diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.cpp b/extras/Projucer/JuceLibraryCode/BinaryData.cpp index ab7a9dda7e..543a94bc05 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.cpp +++ b/extras/Projucer/JuceLibraryCode/BinaryData.cpp @@ -1617,6 +1617,7 @@ static const unsigned char temp_binary_data_8[] = "\r\n" "void FILTERCLASSNAME::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)\r\n" "{\r\n" +" ScopedNoDenormals noDenormals;\r\n" " const int totalNumInputChannels = getTotalNumInputChannels();\r\n" " const int totalNumOutputChannels = getTotalNumOutputChannels();\r\n" "\r\n" @@ -7028,7 +7029,7 @@ const char* getNamedResource (const char* resourceNameUTF8, int& numBytes) throw case 0xafccbd3f: numBytes = 3141; return jucer_AudioComponentTemplate_cpp; case 0x27c5a93a: numBytes = 1310; return jucer_AudioPluginEditorTemplate_cpp; case 0x4d0721bf: numBytes = 938; return jucer_AudioPluginEditorTemplate_h; - case 0x51b49ac5: numBytes = 5611; return jucer_AudioPluginFilterTemplate_cpp; + case 0x51b49ac5: numBytes = 5647; return jucer_AudioPluginFilterTemplate_cpp; case 0x488afa0a: numBytes = 2245; return jucer_AudioPluginFilterTemplate_h; case 0xabad7041: numBytes = 2151; return jucer_ComponentTemplate_cpp; case 0xfc72fe86: numBytes = 2064; return jucer_ComponentTemplate_h; diff --git a/extras/Projucer/JuceLibraryCode/BinaryData.h b/extras/Projucer/JuceLibraryCode/BinaryData.h index 1ad41adb5c..798ca25825 100644 --- a/extras/Projucer/JuceLibraryCode/BinaryData.h +++ b/extras/Projucer/JuceLibraryCode/BinaryData.h @@ -33,7 +33,7 @@ namespace BinaryData const int jucer_AudioPluginEditorTemplate_hSize = 938; extern const char* jucer_AudioPluginFilterTemplate_cpp; - const int jucer_AudioPluginFilterTemplate_cppSize = 5611; + const int jucer_AudioPluginFilterTemplate_cppSize = 5647; extern const char* jucer_AudioPluginFilterTemplate_h; const int jucer_AudioPluginFilterTemplate_hSize = 2245; diff --git a/extras/Projucer/Source/BinaryData/jucer_AudioPluginFilterTemplate.cpp b/extras/Projucer/Source/BinaryData/jucer_AudioPluginFilterTemplate.cpp index 64b036e975..bec4e61204 100644 --- a/extras/Projucer/Source/BinaryData/jucer_AudioPluginFilterTemplate.cpp +++ b/extras/Projucer/Source/BinaryData/jucer_AudioPluginFilterTemplate.cpp @@ -131,6 +131,7 @@ bool FILTERCLASSNAME::isBusesLayoutSupported (const BusesLayout& layouts) const void FILTERCLASSNAME::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { + ScopedNoDenormals noDenormals; const int totalNumInputChannels = getTotalNumInputChannels(); const int totalNumOutputChannels = getTotalNumOutputChannels(); diff --git a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h index 708f5ac2aa..c44bbd800f 100644 --- a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h +++ b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h @@ -221,4 +221,34 @@ public: static void JUCE_CALLTYPE disableDenormalisedNumberSupport() noexcept; }; +//============================================================================== +/** + Helper class providing an RAII-based mechanism for temporarily disabling + denormals on your CPU. +*/ +class ScopedNoDenormals +{ +public: + inline ScopedNoDenormals() noexcept + { + #if JUCE_USE_SSE_INTRINSICS + mxcsr = _mm_getcsr(); + _mm_setcsr (mxcsr | 0x8040); // add the DAZ and FZ bits + #endif + } + + + inline ~ScopedNoDenormals() noexcept + { + #if JUCE_USE_SSE_INTRINSICS + _mm_setcsr (mxcsr); + #endif + } + +private: + #if JUCE_USE_SSE_INTRINSICS + unsigned int mxcsr; + #endif +}; + } // namespace juce diff --git a/modules/juce_audio_basics/juce_audio_basics.h b/modules/juce_audio_basics/juce_audio_basics.h index 023fa4760b..a6c7b85f1e 100644 --- a/modules/juce_audio_basics/juce_audio_basics.h +++ b/modules/juce_audio_basics/juce_audio_basics.h @@ -51,6 +51,7 @@ #include +//============================================================================== #undef Complex // apparently some C libraries actually define these symbols (!) #undef Factor diff --git a/modules/juce_dsp/juce_dsp.h b/modules/juce_dsp/juce_dsp.h index 4566489153..c700684cae 100644 --- a/modules/juce_dsp/juce_dsp.h +++ b/modules/juce_dsp/juce_dsp.h @@ -166,6 +166,23 @@ #define JUCE_DSP_USE_STATIC_FFTW 0 #endif +/** Config: JUCE_DSP_ENABLE_SNAP_TO_ZERO + + Enables code in the dsp module to avoid floating point denormals during the + processing of some of the dsp module's filters. + + Enabling this will add a slight performance overhead to the DSP module's + filters and algorithms. If your audio app already disables denormals altogether + (for exmaple, by using the ScopedNoDenormals class or the + FloatVectorOperations::disableDenormalisedNumberSupport method), then you + can safely disable this flag to shave off a few cpu cycles from the DSP module's + filters and algorithms. +*/ +#ifndef JUCE_DSP_ENABLE_SNAP_TO_ZERO + #define JUCE_DSP_ENABLE_SNAP_TO_ZERO 1 +#endif + + //============================================================================== #undef Complex // apparently some C libraries actually define these symbols (!) #undef Factor @@ -185,11 +202,19 @@ namespace juce This function will work with both primitives and simple containers. */ + #if JUCE_DSP_ENABLE_SNAP_TO_ZERO inline void snapToZero (float& x) noexcept { JUCE_SNAP_TO_ZERO (x); } #ifndef DOXYGEN inline void snapToZero (double& x) noexcept { JUCE_SNAP_TO_ZERO (x); } inline void snapToZero (long double& x) noexcept { JUCE_SNAP_TO_ZERO (x); } #endif + #else + inline void snapToZero (float& x) noexcept { ignoreUnused (x); } + #ifndef DOXYGEN + inline void snapToZero (double& x) noexcept { ignoreUnused (x); } + inline void snapToZero (long double& x) noexcept { ignoreUnused (x); } + #endif + #endif } } } diff --git a/modules/juce_dsp/processors/juce_Oversampling.cpp b/modules/juce_dsp/processors/juce_Oversampling.cpp index c039f484b3..2ce6ea6cb9 100644 --- a/modules/juce_dsp/processors/juce_Oversampling.cpp +++ b/modules/juce_dsp/processors/juce_Oversampling.cpp @@ -444,7 +444,7 @@ public: auto numStages = coefficientsUp.size(); for (auto n = 0; n < numStages; n++) - JUCE_SNAP_TO_ZERO (lv1[n]); + util::snapToZero (lv1[n]); } } else @@ -455,7 +455,7 @@ public: auto numStages = coefficientsDown.size(); for (auto n = 0; n < numStages; n++) - JUCE_SNAP_TO_ZERO (lv1[n]); + util::snapToZero (lv1[n]); } } }