Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/webaudio/WebAudioUtils.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#ifndef WebAudioUtils_h_
8
#define WebAudioUtils_h_
9
10
#include <cmath>
11
#include <limits>
12
#include "mozilla/TypeTraits.h"
13
#include "mozilla/FloatingPoint.h"
14
#include "MediaSegment.h"
15
16
// Forward declaration
17
typedef struct SpeexResamplerState_ SpeexResamplerState;
18
19
namespace mozilla {
20
21
class AudioNodeStream;
22
23
extern LazyLogModule gWebAudioAPILog;
24
#define WEB_AUDIO_API_LOG(...) \
25
0
  MOZ_LOG(gWebAudioAPILog, LogLevel::Debug, (__VA_ARGS__))
26
27
namespace dom {
28
29
struct AudioTimelineEvent;
30
31
namespace WebAudioUtils {
32
  // 32 is the minimum required by the spec for createBuffer() and
33
  // createScriptProcessor() and matches what is used by Blink.  The limit
34
  // protects against large memory allocations.
35
  const size_t MaxChannelCount = 32;
36
  // AudioContext::CreateBuffer() "must support sample-rates in at least the
37
  // range 22050 to 96000."
38
  const uint32_t MinSampleRate = 8000;
39
  const uint32_t MaxSampleRate = 192000;
40
41
  inline bool FuzzyEqual(float v1, float v2)
42
  {
43
    using namespace std;
44
    return fabsf(v1 - v2) < 1e-7f;
45
  }
46
  inline bool FuzzyEqual(double v1, double v2)
47
0
  {
48
0
    using namespace std;
49
0
    return fabs(v1 - v2) < 1e-7;
50
0
  }
51
52
  /**
53
   * Converts an AudioTimelineEvent's floating point time values to tick values
54
   * with respect to a destination AudioNodeStream.
55
   *
56
   * This needs to be called for each AudioTimelineEvent that gets sent to an
57
   * AudioNodeEngine, on the engine side where the AudioTimlineEvent is
58
   * received.  This means that such engines need to be aware of their
59
   * destination streams as well.
60
   */
61
  void ConvertAudioTimelineEventToTicks(AudioTimelineEvent& aEvent,
62
                                        AudioNodeStream* aDest);
63
64
  /**
65
   * Converts a linear value to decibels.  Returns aMinDecibels if the linear
66
   * value is 0.
67
   */
68
  inline float ConvertLinearToDecibels(float aLinearValue, float aMinDecibels)
69
0
  {
70
0
    return aLinearValue ? 20.0f * std::log10(aLinearValue) : aMinDecibels;
71
0
  }
72
73
  /**
74
   * Converts a decibel value to a linear value.
75
   */
76
  inline float ConvertDecibelsToLinear(float aDecibels)
77
0
  {
78
0
    return std::pow(10.0f, 0.05f * aDecibels);
79
0
  }
80
81
  /**
82
   * Converts a decibel to a linear value.
83
   */
84
  inline float ConvertDecibelToLinear(float aDecibel)
85
  {
86
    return std::pow(10.0f, 0.05f * aDecibel);
87
  }
88
89
  inline void FixNaN(double& aDouble)
90
  {
91
    if (IsNaN(aDouble) || IsInfinite(aDouble)) {
92
      aDouble = 0.0;
93
    }
94
  }
95
96
  inline double DiscreteTimeConstantForSampleRate(double timeConstant, double sampleRate)
97
0
  {
98
0
    return 1.0 - std::exp(-1.0 / (sampleRate * timeConstant));
99
0
  }
100
101
  inline bool IsTimeValid(double aTime)
102
0
  {
103
0
    return aTime >= 0 && aTime <= (MEDIA_TIME_MAX >> TRACK_RATE_MAX_BITS);
104
0
  }
105
106
  /**
107
   * Converts a floating point value to an integral type in a safe and
108
   * platform agnostic way.  The following program demonstrates the kinds
109
   * of ways things can go wrong depending on the CPU architecture you're
110
   * compiling for:
111
   *
112
   * #include <stdio.h>
113
   * volatile float r;
114
   * int main()
115
   * {
116
   *   unsigned int q;
117
   *   r = 1e100;
118
   *   q = r;
119
   *   printf("%f %d\n", r, q);
120
   *   r = -1e100;
121
   *   q = r;
122
   *   printf("%f %d\n", r, q);
123
   *   r = 1e15;
124
   *   q = r;
125
   *   printf("%f %x\n", r, q);
126
   *   r = 0/0.;
127
   *   q = r;
128
   *   printf("%f %d\n", r, q);
129
   * }
130
   *
131
   * This program, when compiled for unsigned int, generates the following
132
   * results depending on the architecture:
133
   *
134
   * x86 and x86-64
135
   * ---
136
   *  inf 0
137
   *  -inf 0
138
   *  999999995904.000000 -727384064 d4a50000
139
   *  nan 0
140
   *
141
   * ARM
142
   * ---
143
   *  inf -1
144
   *  -inf 0
145
   *  999999995904.000000 -1
146
   *  nan 0
147
   *
148
   * When compiled for int, this program generates the following results:
149
   *
150
   * x86 and x86-64
151
   * ---
152
   *  inf -2147483648
153
   *  -inf -2147483648
154
   *  999999995904.000000 -2147483648
155
   *  nan -2147483648
156
   *
157
   * ARM
158
   * ---
159
   *  inf 2147483647
160
   *  -inf -2147483648
161
   *  999999995904.000000 2147483647
162
   *  nan 0
163
   *
164
   * Note that the caller is responsible to make sure that the value
165
   * passed to this function is not a NaN.  This function will abort if
166
   * it sees a NaN.
167
   */
168
  template <typename IntType, typename FloatType>
169
  IntType TruncateFloatToInt(FloatType f)
170
0
  {
171
0
    using namespace std;
172
0
173
0
    static_assert(mozilla::IsIntegral<IntType>::value == true,
174
0
                  "IntType must be an integral type");
175
0
    static_assert(mozilla::IsFloatingPoint<FloatType>::value == true,
176
0
                  "FloatType must be a floating point type");
177
0
178
0
    if (mozilla::IsNaN(f)) {
179
0
      // It is the responsibility of the caller to deal with NaN values.
180
0
      // If we ever get to this point, we have a serious bug to fix.
181
0
      MOZ_CRASH("We should never see a NaN here");
182
0
    }
183
0
184
0
    // If the floating point value is outside of the range of maximum
185
0
    // integral value for this type, just clamp to the maximum value.
186
0
    // The equality case must also return max() due to loss of precision when
187
0
    // converting max() to float.
188
0
    if (f >= FloatType(numeric_limits<IntType>::max())) {
189
0
      return numeric_limits<IntType>::max();
190
0
    }
191
0
192
0
    if (f <= FloatType(numeric_limits<IntType>::min())) {
193
0
      // If the floating point value is outside of the range of minimum
194
0
      // integral value for this type, just clamp to the minimum value.
195
0
      return numeric_limits<IntType>::min();
196
0
    }
197
0
198
0
    // Otherwise, this conversion must be well defined.
199
0
    return IntType(f);
200
0
  }
201
202
  void Shutdown();
203
204
  int
205
  SpeexResamplerProcess(SpeexResamplerState* aResampler,
206
                        uint32_t aChannel,
207
                        const float* aIn, uint32_t* aInLen,
208
                        float* aOut, uint32_t* aOutLen);
209
210
  int
211
  SpeexResamplerProcess(SpeexResamplerState* aResampler,
212
                        uint32_t aChannel,
213
                        const int16_t* aIn, uint32_t* aInLen,
214
                        float* aOut, uint32_t* aOutLen);
215
216
  int
217
  SpeexResamplerProcess(SpeexResamplerState* aResampler,
218
                        uint32_t aChannel,
219
                        const int16_t* aIn, uint32_t* aInLen,
220
                        int16_t* aOut, uint32_t* aOutLen);
221
222
  void
223
  LogToDeveloperConsole(uint64_t aWindowID, const char* aKey);
224
225
  } // namespace WebAudioUtils
226
227
} // namespace dom
228
} // namespace mozilla
229
230
#endif
231