Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: Source/platform/audio/StereoPanner.cpp

Issue 691143007: Implement StereoPannerNode for robust stereo panning (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google Inc. nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #include "config.h"
30
31 #if ENABLE(WEB_AUDIO)
32
33 #include "platform/audio/StereoPanner.h"
34
35 #include "platform/audio/AudioBus.h"
36 #include "platform/audio/AudioUtilities.h"
37 #include "wtf/MathExtras.h"
38 #include <algorithm>
39
40 // Use a 50ms smoothing / de-zippering time-constant.
41 const float SmoothingTimeConstant = 0.050f;
42
43 namespace blink {
44
45 StereoPanner::StereoPanner(float sampleRate) : Spatializer(PanningModelEqualPowe r)
46 , m_isFirstRender(true)
47 , m_gainL(0.5)
48 , m_gainR(0.5)
49 {
50 m_smoothingConstant = AudioUtilities::discreteTimeConstantForSampleRate(Smoo thingTimeConstant, sampleRate);
51 }
52
53 void StereoPanner::panWithSampleAccurateValues(const AudioBus* inputBus, AudioBu s* outputBus, const float* panValues, size_t framesToProcess)
54 {
55 bool isInputSafe = inputBus
56 && (inputBus->numberOfChannels() == 1 || inputBus->numberOfChannels() == 2)
57 && framesToProcess <= inputBus->length();
58 ASSERT(isInputSafe);
59 if (!isInputSafe)
60 return;
61
62 unsigned numberOfInputChannels = inputBus->numberOfChannels();
63
64 bool isOutputSafe = outputBus
65 && outputBus->numberOfChannels() == 2
66 && framesToProcess <= outputBus->length();
67 ASSERT(isOutputSafe);
68 if (!isOutputSafe)
69 return;
70
71 const float* sourceL = inputBus->channel(0)->data();
72 const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->dat a() : sourceL;
73 float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutab leData();
74 float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->muta bleData();
75
76 if (!sourceL || !sourceR || !destinationL || !destinationR)
77 return;
78
79 // Cache in local variables.
80 double gainL = m_gainL;
81 double gainR = m_gainR;
82
83 int n = framesToProcess;
84
85 if (numberOfInputChannels == 1) { // For mono source case.
86 while (n--) {
87 float inputL = *sourceL++;
88 float panPosition = (*panValues++ * 0.5 + 0.5) * piOverTwoDouble;
89 gainL = std::cos(panPosition);
90 gainR = std::sin(panPosition);
91 *destinationL++ = static_cast<float>(inputL * gainL);
92 *destinationR++ = static_cast<float>(inputL * gainR);
93 }
94 } else { // For stereo source case.
95 while (n--) {
96 float inputL = *sourceL++;
97 float inputR = *sourceR++;
98 float panPosition = (*panValues++ * 0.5 + 0.5) * piOverTwoDouble;
99 gainL = std::cos(panPosition);
100 gainR = std::sin(panPosition);
101 *destinationL++ = static_cast<float>(inputL * gainL);
102 *destinationR++ = static_cast<float>(inputR * gainR);
103 }
104 }
105
106 m_gainL = gainL;
107 m_gainR = gainR;
108 }
109
110 void StereoPanner::panToTargetValue(const AudioBus* inputBus, AudioBus* outputBu s, float panValue, size_t framesToProcess)
111 {
112 bool isInputSafe = inputBus
113 && (inputBus->numberOfChannels() == 1 || inputBus->numberOfChannels() == 2)
114 && framesToProcess <= inputBus->length();
115 ASSERT(isInputSafe);
116 if (!isInputSafe)
117 return;
118
119 unsigned numberOfInputChannels = inputBus->numberOfChannels();
120
121 bool isOutputSafe = outputBus
122 && outputBus->numberOfChannels() == 2
123 && framesToProcess <= outputBus->length();
124 ASSERT(isOutputSafe);
125 if (!isOutputSafe)
126 return;
127
128 const float* sourceL = inputBus->channel(0)->data();
129 const float* sourceR = numberOfInputChannels > 1 ? inputBus->channel(1)->dat a() : sourceL;
130 float* destinationL = outputBus->channelByType(AudioBus::ChannelLeft)->mutab leData();
131 float* destinationR = outputBus->channelByType(AudioBus::ChannelRight)->muta bleData();
132
133 if (!sourceL || !sourceR || !destinationL || !destinationR)
134 return;
135
136 double targetGainL = std::cos(piOverTwoDouble * (panValue * 0.5 + 0.5));
137 double targetGainR = std::sin(piOverTwoDouble * (panValue * 0.5 + 0.5));
138
139 // Don't de-zipper on first render call.
140 if (m_isFirstRender) {
141 m_isFirstRender = false;
142 m_gainL = targetGainL;
143 m_gainR = targetGainR;
144 }
145
146 // Cache in local variables.
147 double gainL = m_gainL;
148 double gainR = m_gainR;
149
150 // Get local copy of smoothing constant.
151 const double SmoothingConstant = m_smoothingConstant;
152
153 int n = framesToProcess;
154
155 if (numberOfInputChannels == 1) { // For mono source case.
156 while (n--) {
157 float inputL = *sourceL++;
158 gainL += (targetGainL - gainL) * SmoothingConstant;
159 gainR += (targetGainR - gainR) * SmoothingConstant;
160 *destinationL++ = static_cast<float>(inputL * gainL);
161 *destinationR++ = static_cast<float>(inputL * gainR);
162 }
163 } else { // For stereo source case.
164 while (n--) {
165 float inputL = *sourceL++;
166 float inputR = *sourceR++;
167 gainL += (targetGainL - gainL) * SmoothingConstant;
168 gainR += (targetGainR - gainR) * SmoothingConstant;
169 *destinationL++ = static_cast<float>(inputL * gainL);
170 *destinationR++ = static_cast<float>(inputR * gainR);
171 }
172 }
173
174 m_gainL = gainL;
175 m_gainR = gainR;
176 }
177
178 } // namespace blink
179
180 #endif // ENABLE(WEB_AUDIO)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698