1 /*
2  * Copyright (C) 2010, Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
20  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
23  * DAMAGE.
24  */
25 
26 #include "third_party/blink/renderer/platform/audio/audio_utilities.h"
27 #include "third_party/blink/renderer/platform/wtf/assertions.h"
28 #include "third_party/blink/renderer/platform/wtf/math_extras.h"
29 
30 namespace blink {
31 
32 namespace audio_utilities {
33 
DecibelsToLinear(float decibels)34 float DecibelsToLinear(float decibels) {
35   return powf(10, 0.05f * decibels);
36 }
37 
LinearToDecibels(float linear)38 float LinearToDecibels(float linear) {
39   DCHECK_GE(linear, 0);
40 
41   return 20 * log10f(linear);
42 }
43 
DiscreteTimeConstantForSampleRate(double time_constant,double sample_rate)44 double DiscreteTimeConstantForSampleRate(double time_constant,
45                                          double sample_rate) {
46   // From the WebAudio spec, the formula for setTargetAtTime is
47   //
48   //   v(t) = V1 + (V0 - V1)*exp(-t/tau)
49   //
50   // where tau is the time constant, V1 is the target value and V0 is
51   // the starting value.
52   //
53   // Rewrite this as
54   //
55   //   v(t) = V0 + (V1 - V0)*(1-exp(-t/tau))
56   //
57   // The implementation of setTargetAtTime uses this form.  So at the
58   // sample points, we have
59   //
60   //   v(n/Fs) = V0 + (V1 - V0)*(1-exp(-n/(Fs*tau)))
61   //
62   // where Fs is the sample rate of the sampled systme.  Thus, the
63   // discrete time constant is
64   //
65   //   1 - exp(-1/(Fs*tau)
66   return 1 - exp(-1 / (sample_rate * time_constant));
67 }
68 
TimeToSampleFrame(double time,double sample_rate,enum SampleFrameRounding rounding_mode)69 size_t TimeToSampleFrame(double time,
70                          double sample_rate,
71                          enum SampleFrameRounding rounding_mode) {
72   DCHECK_GE(time, 0);
73 
74   // To compute the desired frame number, we pretend we're actually running the
75   // context at a much higher sample rate (by a factor of |oversample_factor|).
76   // Round this to get the nearest frame number at the higher rate.  Then
77   // convert back to the original rate to get a new frame number that may not be
78   // an integer.  Then use the specified |rounding_mode| to round this to the
79   // integer frame number that we need.
80   //
81   // Doing this partially solves the issue where Fs * (k / Fs) != k when doing
82   // floating point arithmtic for integer k and Fs is the sample rate.  By
83   // oversampling and rounding, we'll get k back most of the time.
84   //
85   // The oversampling factor MUST be a power of two so as not to introduce
86   // additional round-off in computing the oversample frame number.
87   const double oversample_factor = 1024;
88   double frame =
89       round(time * sample_rate * oversample_factor) / oversample_factor;
90 
91   switch (rounding_mode) {
92     case kRoundToNearest:
93       frame = round(frame);
94       break;
95     case kRoundDown:
96       frame = floor(frame);
97       break;
98     case kRoundUp:
99       frame = ceil(frame);
100       break;
101     default:
102       NOTREACHED();
103   }
104 
105   // Just return the largest possible size_t value if necessary.
106   if (frame >= std::numeric_limits<size_t>::max()) {
107     return std::numeric_limits<size_t>::max();
108   }
109 
110   return static_cast<size_t>(frame);
111 }
112 
IsValidAudioBufferSampleRate(float sample_rate)113 bool IsValidAudioBufferSampleRate(float sample_rate) {
114   return sample_rate >= MinAudioBufferSampleRate() &&
115          sample_rate <= MaxAudioBufferSampleRate();
116 }
117 
MinAudioBufferSampleRate()118 float MinAudioBufferSampleRate() {
119   // crbug.com/344375
120   return 3000;
121 }
122 
MaxAudioBufferSampleRate()123 float MaxAudioBufferSampleRate() {
124   // <video> tags support sample rates up 384 kHz so audio context
125   // should too.
126   return 384000;
127 }
128 
IsPowerOfTwo(size_t x)129 bool IsPowerOfTwo(size_t x) {
130   // From Hacker's Delight.  x & (x - 1) turns off (zeroes) the
131   // rightmost 1-bit in the word x.  If x is a power of two, then the
132   // result is, of course, 0.
133   return x > 0 && ((x & (x - 1)) == 0);
134 }
135 
136 }  // namespace audio_utilities
137 
138 }  // namespace blink
139