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