AAX SDK 2.8.0
Avid Audio Extensions Development Kit
Loading...
Searching...
No Matches
AAX_Denormal.h
Go to the documentation of this file.
1/*================================================================================================*/
2/*
3 * Copyright 2014-2016, 2019, 2021, 2023-2024 Avid Technology, Inc.
4 * All rights reserved.
5 *
6 * This file is part of the Avid AAX SDK.
7 *
8 * The AAX SDK is subject to commercial or open-source licensing.
9 *
10 * By using the AAX SDK, you agree to the terms of both the Avid AAX SDK License
11 * Agreement and Avid Privacy Policy.
12 *
13 * AAX SDK License: https://developer.avid.com/aax
14 * Privacy Policy: https://www.avid.com/legal/privacy-policy-statement
15 *
16 * Or: You may also use this code under the terms of the GPL v3 (see
17 * www.gnu.org/licenses).
18 *
19 * THE AAX SDK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 * EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 * DISCLAIMED.
22 */
23
30/*================================================================================================*/
31#pragma once
32
33#ifndef AAX_DENORMAL_H
34#define AAX_DENORMAL_H
35
36
37// AAX Includes
38#include "AAX.h"
40
41
42#if ! defined( _TMS320C6X )
43#include <limits>
44#include <math.h>
45#endif // ! defined( _TMS320C6X )
46
47
48
66#if defined( _TMS320C6X )
67
68// TODO: Currently noop on TI
69#define AAX_SCOPE_COMPUTE_DENORMALS() do {} while(0)
70#define AAX_SCOPE_DENORMALS_AS_ZERO() do {} while(0)
71
72#elif ((defined _MSC_VER) || defined(WINDOWS_VERSION))
73// Visual Studio
74
75// Note: In Pro Tools 11 and higher for Windows, DAZ is turned on for all plug-in processing threads
76
77// FIXME: These macros are currently noop on Windows because of compiler problems when intrin.h is included. Investigate using _controlfp(_DN_FLUSH, _MCW_DN) instead
78#define AAX_SCOPE_COMPUTE_DENORMALS() do {} while(0)
79#define AAX_SCOPE_DENORMALS_AS_ZERO() do {} while(0)
80//#define AAX_SCOPE_COMPUTE_DENORMALS() AAX_StDenormalAsZeroFlagsOff computeDenormalFlagsScope ## __LINE__ ; do {} while (0)
81//#define AAX_SCOPE_DENORMALS_AS_ZERO() AAX_StDenormalAsZeroFlagsOn denormalAsZeroFlagsScope ## __LINE__ ; do {} while (0)
82//
83//#include <Windows.h>
84//#include <mmintrin.h>
85//
91//const unsigned gMXCSRFlags_DAZFZ = 0x00008040;
92//
94//struct AAX_StDenormalAsZeroFlagsOn
95//{
96//public:
97// AAX_StDenormalAsZeroFlagsOn()
98// : mSSESupported(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
99// {
100// if (mSSESupported) { set_flags(); }
101// }
102//
103// ~AAX_StDenormalAsZeroFlagsOn()
104// {
105// if (mSSESupported) { reset_flags(); }
106// }
107//
108//private:
109// void set_flags()
110// {
111// mPrevFlags = _mm_getcsr();
112// unsigned newFlags = mPrevFlags | gMXCSRFlags_DAZFZ;
113// _mm_setcsr(newFlags);
114// }
115//
116// void reset_flags()
117// {
118// _mm_setcsr(mPrevFlags);
119// }
120//
121// unsigned mPrevFlags;
122// const bool mSSESupported;
123//};
124//
126//struct AAX_StDenormalAsZeroFlagsOff
127//{
128//public:
129// AAX_StDenormalAsZeroFlagsOff()
130// : mSSESupported(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE))
131// {
132// if (mSSESupported) { set_flags(); }
133// }
134//
135// ~AAX_StDenormalAsZeroFlagsOff()
136// {
137// if (mSSESupported) { reset_flags(); }
138// }
139//
140//private:
141// void set_flags()
142// {
143// mPrevFlags = _mm_getcsr();
144// unsigned newFlags = mPrevFlags & (~gMXCSRFlags_DAZFZ);
145// _mm_setcsr(newFlags);
146// }
147//
148// void reset_flags()
149// {
150// _mm_setcsr(mPrevFlags);
151// }
152//
153// unsigned mPrevFlags;
154// const bool mSSESupported;
155//};
156
157
158#elif defined(__linux__)
159// Linux
160
161// TODO: Currently noop on Linux
162#define AAX_SCOPE_COMPUTE_DENORMALS() do {} while(0)
163#define AAX_SCOPE_DENORMALS_AS_ZERO() do {} while(0)
164
165#elif (defined (__GNUC__) || defined(MAC_VERSION))
166// GCC / macOS
167
168// Note: In Pro Tools 11 through Pro Tools 12.6 on macOS, DAZ is turned off for all plug-in processing threads
169
170#define AAX_SCOPE_COMPUTE_DENORMALS() AAX_StDenormalAsZeroFlagsOff computeDenormalFlagsScope ## __LINE__ ; do {} while (0)
171#define AAX_SCOPE_DENORMALS_AS_ZERO() AAX_StDenormalAsZeroFlagsOn denormalAsZeroFlagsScope ## __LINE__ ; do {} while (0)
172
173#include <fenv.h>
174struct AAX_StDenormalAsZeroFlagsOn
175{
176public:
177 AAX_StDenormalAsZeroFlagsOn() { set_flags(); }
178 ~AAX_StDenormalAsZeroFlagsOn() { reset_flags(); }
179
180private:
181#if !defined(__arm64__)
182 void set_flags() { fegetenv(&mPrevFlags); fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV); }
183#else
184 void set_flags() { fegetenv(&mPrevFlags); fesetenv(FE_DFL_DISABLE_DENORMS_ENV); }
185#endif
186 void reset_flags() { fesetenv(&mPrevFlags); }
187 fenv_t mPrevFlags;
188};
189struct AAX_StDenormalAsZeroFlagsOff
190{
191public:
192 AAX_StDenormalAsZeroFlagsOff() { set_flags(); }
193 ~AAX_StDenormalAsZeroFlagsOff() { reset_flags(); }
194
195private:
196 void set_flags() { fegetenv(&mPrevFlags); fesetenv(FE_DFL_ENV); } // assuming that FE_DFL_ENV are the flags that we want here
197 void reset_flags() { fesetenv(&mPrevFlags); }
198 fenv_t mPrevFlags;
199};
200
201
202
203#else
204
205#error AAX_SCOPE_COMPUTE_DENORMALS is not defined for this compiler
206#error AAX_SCOPE_DENORMALS_AS_ZERO is not defined for this compiler
207
208// Just for Doxygen
209#define AAX_SCOPE_COMPUTE_DENORMALS() do {} while(0)
210#define AAX_SCOPE_DENORMALS_AS_ZERO() do {} while(0)
211
212#endif // End compiler selection for AAX_SCOPE_COMPUTE_DENORMALS / AAX_SCOPE_DENORMALS_AS_ZERO definition
213
214
215
216
217namespace AAX
218{
219 const double cDenormalAvoidanceOffset=3.0e-34;
220 const float cFloatDenormalAvoidanceOffset=3.0e-20f; //This number is emprically derived with minimal trial and error.
221
222#if ! defined( _TMS320C6X )
223 static const float cMinimumNormalFloat = std::numeric_limits<float>::min();
224#endif
225
235 inline void DeDenormal(double &iValue)
236 {
237#if defined(WINDOWS_VERSION) || defined(MAC_VERSION) || defined(LINUX_VERSION)
238 if(iValue < cDenormalAvoidanceOffset && iValue > -cDenormalAvoidanceOffset) iValue=0.0;
239#endif
240 }
241
244 inline void DeDenormal(float &iValue)
245 {
246#if defined(WINDOWS_VERSION) || defined(MAC_VERSION) || defined(LINUX_VERSION)
247 if(iValue < cFloatDenormalAvoidanceOffset && iValue > -cFloatDenormalAvoidanceOffset) iValue=0.0f;
248#endif
249 }
250
251#if AAX_CPP11_SUPPORT
254 inline float DeDenormal(float &&iValue)
255 {
256#if defined(WINDOWS_VERSION) || defined(MAC_VERSION) || defined(LINUX_VERSION)
257 return (iValue < cFloatDenormalAvoidanceOffset && iValue > -cFloatDenormalAvoidanceOffset) ? 0.f : iValue;
258#endif
259 }
260#endif // AAX_CPP11_SUPPORT
261
266 inline void DeDenormalFine(float &iValue)
267 {
268#if ! defined( _TMS320C6X )
269 if(iValue < cMinimumNormalFloat && iValue > -cMinimumNormalFloat) iValue=0.0f;
270#endif
271 }
272
283 inline void FilterDenormals(float* inSamples, int32_t inLength)
284 {
285 //TODO: Implement optimized versions for TI and SSE
286#if ! defined( _TMS320C6X ) // Not yet implemented for TI
287 for( int32_t i = 0; i < inLength; ++i )
288 {
289 float curFloat = *inSamples;
290 if( fabsf(curFloat) < cMinimumNormalFloat )
291 curFloat = 0.0f;
292 *(inSamples++) = curFloat;
293 }
294#endif
295 }
296
297} // namespace AAX
298
299#endif // AAX_QUANTIZE_H
Various utility definitions for AAX.
Definition: AAX_EnvironmentUtilities.h:72
const double cDenormalAvoidanceOffset
Definition: AAX_Denormal.h:219
void FilterDenormals(float *inSamples, int32_t inLength)
Round all denormal/subnormal samples in a buffer to zero.
Definition: AAX_Denormal.h:283
float fabsf(float iVal)
Definition: AAX_MiscUtils.h:195
void DeDenormal(double &iValue)
Clamps very small floating point values to zero.
Definition: AAX_Denormal.h:235
void DeDenormalFine(float &iValue)
Definition: AAX_Denormal.h:266
const float cFloatDenormalAvoidanceOffset
Definition: AAX_Denormal.h:220