Bug 1839170 - Refactor Snap pulling, Add Firefox Snap Core22 and GNOME 42 SDK symbols...
[gecko.git] / dom / media / webaudio / WebAudioUtils.h
blob0b01efde69caca45e6244765214f5baac4e0fb47
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef WebAudioUtils_h_
8 #define WebAudioUtils_h_
10 #include <cmath>
11 #include <limits>
12 #include <type_traits>
13 #include "mozilla/FloatingPoint.h"
14 #include "mozilla/Logging.h"
15 #include "MediaSegment.h"
17 // Forward declaration
18 typedef struct SpeexResamplerState_ SpeexResamplerState;
20 namespace mozilla {
22 class AudioNodeTrack;
24 extern LazyLogModule gWebAudioAPILog;
25 #define WEB_AUDIO_API_LOG(...) \
26 MOZ_LOG(gWebAudioAPILog, LogLevel::Debug, (__VA_ARGS__))
28 namespace dom {
30 struct AudioTimelineEvent;
32 namespace WebAudioUtils {
33 // 32 is the minimum required by the spec for createBuffer() and
34 // createScriptProcessor() and matches what is used by Blink. The limit
35 // protects against large memory allocations.
36 const size_t MaxChannelCount = 32;
37 // AudioContext::CreateBuffer() "must support sample-rates in at least the
38 // range 22050 to 96000."
39 const uint32_t MinSampleRate = 8000;
40 const uint32_t MaxSampleRate = 192000;
42 inline bool FuzzyEqual(float v1, float v2) { return fabsf(v1 - v2) < 1e-7f; }
43 inline bool FuzzyEqual(double v1, double v2) { return fabs(v1 - v2) < 1e-7; }
45 /**
46 * Converts an AudioTimelineEvent's floating point time values to tick values
47 * with respect to a destination AudioNodeTrack.
49 * This needs to be called for each AudioTimelineEvent that gets sent to an
50 * AudioNodeEngine, on the engine side where the AudioTimlineEvent is
51 * received. This means that such engines need to be aware of their
52 * destination tracks as well.
54 void ConvertAudioTimelineEventToTicks(AudioTimelineEvent& aEvent,
55 AudioNodeTrack* aDest);
57 /**
58 * Converts a linear value to decibels. Returns aMinDecibels if the linear
59 * value is 0.
61 inline float ConvertLinearToDecibels(float aLinearValue, float aMinDecibels) {
62 return aLinearValue ? 20.0f * std::log10(aLinearValue) : aMinDecibels;
65 /**
66 * Converts a decibel value to a linear value.
68 inline float ConvertDecibelsToLinear(float aDecibels) {
69 return std::pow(10.0f, 0.05f * aDecibels);
72 /**
73 * Converts a decibel to a linear value.
75 inline float ConvertDecibelToLinear(float aDecibel) {
76 return std::pow(10.0f, 0.05f * aDecibel);
79 inline void FixNaN(double& aDouble) {
80 if (std::isnan(aDouble) || std::isinf(aDouble)) {
81 aDouble = 0.0;
85 inline double DiscreteTimeConstantForSampleRate(double timeConstant,
86 double sampleRate) {
87 return 1.0 - std::exp(-1.0 / (sampleRate * timeConstant));
90 inline bool IsTimeValid(double aTime) {
91 return aTime >= 0 && aTime <= (MEDIA_TIME_MAX >> TRACK_RATE_MAX_BITS);
94 /**
95 * Converts a floating point value to an integral type in a safe and
96 * platform agnostic way. The following program demonstrates the kinds
97 * of ways things can go wrong depending on the CPU architecture you're
98 * compiling for:
100 * #include <stdio.h>
101 * volatile float r;
102 * int main()
104 * unsigned int q;
105 * r = 1e100;
106 * q = r;
107 * printf("%f %d\n", r, q);
108 * r = -1e100;
109 * q = r;
110 * printf("%f %d\n", r, q);
111 * r = 1e15;
112 * q = r;
113 * printf("%f %x\n", r, q);
114 * r = 0/0.;
115 * q = r;
116 * printf("%f %d\n", r, q);
119 * This program, when compiled for unsigned int, generates the following
120 * results depending on the architecture:
122 * x86 and x86-64
123 * ---
124 * inf 0
125 * -inf 0
126 * 999999995904.000000 -727384064 d4a50000
127 * nan 0
129 * ARM
130 * ---
131 * inf -1
132 * -inf 0
133 * 999999995904.000000 -1
134 * nan 0
136 * When compiled for int, this program generates the following results:
138 * x86 and x86-64
139 * ---
140 * inf -2147483648
141 * -inf -2147483648
142 * 999999995904.000000 -2147483648
143 * nan -2147483648
145 * ARM
146 * ---
147 * inf 2147483647
148 * -inf -2147483648
149 * 999999995904.000000 2147483647
150 * nan 0
152 * Note that the caller is responsible to make sure that the value
153 * passed to this function is not a NaN. This function will abort if
154 * it sees a NaN.
156 template <typename IntType, typename FloatType>
157 IntType TruncateFloatToInt(FloatType f) {
158 using std::numeric_limits;
159 static_assert(std::is_integral_v<IntType> == true,
160 "IntType must be an integral type");
161 static_assert(std::is_floating_point_v<FloatType> == true,
162 "FloatType must be a floating point type");
164 if (std::isnan(f)) {
165 // It is the responsibility of the caller to deal with NaN values.
166 // If we ever get to this point, we have a serious bug to fix.
167 MOZ_CRASH("We should never see a NaN here");
170 // If the floating point value is outside of the range of maximum
171 // integral value for this type, just clamp to the maximum value.
172 // The equality case must also return max() due to loss of precision when
173 // converting max() to float.
174 if (f >= FloatType(numeric_limits<IntType>::max())) {
175 return numeric_limits<IntType>::max();
178 if (f <= FloatType(numeric_limits<IntType>::min())) {
179 // If the floating point value is outside of the range of minimum
180 // integral value for this type, just clamp to the minimum value.
181 return numeric_limits<IntType>::min();
184 // Otherwise, this conversion must be well defined.
185 return IntType(f);
188 void Shutdown();
190 int SpeexResamplerProcess(SpeexResamplerState* aResampler, uint32_t aChannel,
191 const float* aIn, uint32_t* aInLen, float* aOut,
192 uint32_t* aOutLen);
194 int SpeexResamplerProcess(SpeexResamplerState* aResampler, uint32_t aChannel,
195 const int16_t* aIn, uint32_t* aInLen, float* aOut,
196 uint32_t* aOutLen);
198 int SpeexResamplerProcess(SpeexResamplerState* aResampler, uint32_t aChannel,
199 const int16_t* aIn, uint32_t* aInLen, int16_t* aOut,
200 uint32_t* aOutLen);
202 void LogToDeveloperConsole(uint64_t aWindowID, const char* aKey);
204 } // namespace WebAudioUtils
206 } // namespace dom
207 } // namespace mozilla
209 #endif