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

Side by Side Diff: third_party/WebKit/Source/platform/audio/Reverb.cpp

Issue 2732523003: Make ConvolverNode conform to spec (Closed)
Patch Set: Revert unneeded AudioNode.h change Created 3 years, 9 months 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
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 if (normalize && scale) 112 if (normalize && scale)
113 impulseResponse->scale(1 / scale); 113 impulseResponse->scale(1 / scale);
114 } 114 }
115 115
116 void Reverb::initialize(AudioBus* impulseResponseBuffer, 116 void Reverb::initialize(AudioBus* impulseResponseBuffer,
117 size_t renderSliceSize, 117 size_t renderSliceSize,
118 size_t maxFFTSize, 118 size_t maxFFTSize,
119 size_t numberOfChannels, 119 size_t numberOfChannels,
120 bool useBackgroundThreads) { 120 bool useBackgroundThreads) {
121 m_impulseResponseLength = impulseResponseBuffer->length(); 121 m_impulseResponseLength = impulseResponseBuffer->length();
122 m_numberOfChannels = numberOfChannels;
122 123
123 // The reverb can handle a mono impulse response and still do stereo 124 // The reverb can handle a mono impulse response and still do stereo
124 // processing 125 // processing
hongchan 2017/03/28 16:44:35 nit: a missing period.
125 size_t numResponseChannels = impulseResponseBuffer->numberOfChannels(); 126 size_t numResponseChannels = impulseResponseBuffer->numberOfChannels();
hongchan 2017/03/28 16:44:35 This can be unsigned.
Raymond Toy 2017/03/28 18:26:50 This requires changing various other bits of code
126 m_convolvers.reserveCapacity(numberOfChannels); 127 size_t numConvolvers = std::max(numResponseChannels, static_cast<size_t>(2));
128 m_convolvers.reserveCapacity(numConvolvers);
hongchan 2017/03/28 16:44:35 Is |numConvolvers| properly named? Isn't it more o
Raymond Toy 2017/03/28 18:17:20 numberOfConvolverChannels is confusing too since t
127 129
128 int convolverRenderPhase = 0; 130 int convolverRenderPhase = 0;
129 for (size_t i = 0; i < numResponseChannels; ++i) { 131 for (size_t i = 0; i < numConvolvers; ++i) {
130 AudioChannel* channel = impulseResponseBuffer->channel(i); 132 AudioChannel* channel =
133 impulseResponseBuffer->channel(std::min(i, numResponseChannels - 1));
131 134
132 std::unique_ptr<ReverbConvolver> convolver = WTF::wrapUnique( 135 std::unique_ptr<ReverbConvolver> convolver = WTF::wrapUnique(
133 new ReverbConvolver(channel, renderSliceSize, maxFFTSize, 136 new ReverbConvolver(channel, renderSliceSize, maxFFTSize,
134 convolverRenderPhase, useBackgroundThreads)); 137 convolverRenderPhase, useBackgroundThreads));
135 m_convolvers.push_back(std::move(convolver)); 138 m_convolvers.push_back(std::move(convolver));
136 139
137 convolverRenderPhase += renderSliceSize; 140 convolverRenderPhase += renderSliceSize;
138 } 141 }
139 142
140 // For "True" stereo processing we allocate a temporary buffer to avoid 143 // For "True" stereo processing we allocate a temporary buffer to avoid
(...skipping 25 matching lines...) Expand all
166 destinationBus->zero(); 169 destinationBus->zero();
167 return; 170 return;
168 } 171 }
169 172
170 AudioChannel* destinationChannelL = destinationBus->channel(0); 173 AudioChannel* destinationChannelL = destinationBus->channel(0);
171 const AudioChannel* sourceChannelL = sourceBus->channel(0); 174 const AudioChannel* sourceChannelL = sourceBus->channel(0);
172 175
173 // Handle input -> output matrixing... 176 // Handle input -> output matrixing...
174 size_t numInputChannels = sourceBus->numberOfChannels(); 177 size_t numInputChannels = sourceBus->numberOfChannels();
175 size_t numOutputChannels = destinationBus->numberOfChannels(); 178 size_t numOutputChannels = destinationBus->numberOfChannels();
176 size_t numReverbChannels = m_convolvers.size(); 179 size_t numReverbChannels = m_numberOfChannels;
hongchan 2017/03/28 16:44:35 I can't make a clear distinction between numReverb
Raymond Toy 2017/03/28 18:17:20 numReverbChannels is the number of channels in the
hongchan 2017/03/28 19:01:44 Yeah, this name seems to be problematic.
177 180
178 if (numInputChannels == 2 && numReverbChannels == 2 && 181 DCHECK_LE(numInputChannels, 2ul);
182 DCHECK_LE(numOutputChannels, 2ul);
183 DCHECK(numReverbChannels == 1 || numReverbChannels == 2 ||
184 numReverbChannels == 4);
185
186 // These are the possible combinations of number inputs, response
187 // channels and outputs channels that need to be supported:
188 //
189 // numInputChannels: 1 or 2
190 // numReverbChannels: 1, 2, or 4
191 // numOutputChannels: 1 or 2
192 //
193 // Not all possible combinations are valid. numOutputChannels is
194 // one only if both numInputChannels and numReverbChannels are 1.
195 // Otherwise numOutputChannels MUST be 2.
196 //
197 // The valid combinations are
198 //
199 // Case in -> resp -> out
200 // 1 1 -> 1 -> 1
201 // 2 1 -> 2 -> 2
202 // 3 1 -> 4 -> 2
203 // 4 2 -> 1 -> 2
204 // 5 2 -> 2 -> 2
205 // 6 2 -> 4 -> 2
206
207 if (numInputChannels == 2 &&
208 (numReverbChannels == 1 || numReverbChannels == 2) &&
179 numOutputChannels == 2) { 209 numOutputChannels == 2) {
180 // 2 -> 2 -> 2 210 // Case 4 and 5: 2 -> 2 -> 2 or 2 -> 1 -> 2.
211 //
212 // These can be handled in the same way because in the latter
213 // case, two connvolvers are still created with the second being a
214 // copy of the first.
181 const AudioChannel* sourceChannelR = sourceBus->channel(1); 215 const AudioChannel* sourceChannelR = sourceBus->channel(1);
182 AudioChannel* destinationChannelR = destinationBus->channel(1); 216 AudioChannel* destinationChannelR = destinationBus->channel(1);
183 m_convolvers[0]->process(sourceChannelL, destinationChannelL, 217 m_convolvers[0]->process(sourceChannelL, destinationChannelL,
184 framesToProcess); 218 framesToProcess);
185 m_convolvers[1]->process(sourceChannelR, destinationChannelR, 219 m_convolvers[1]->process(sourceChannelR, destinationChannelR,
186 framesToProcess); 220 framesToProcess);
187 } else if (numInputChannels == 1 && numOutputChannels == 2 && 221 } else if (numInputChannels == 1 && numOutputChannels == 2 &&
188 numReverbChannels == 2) { 222 numReverbChannels == 2) {
189 // 1 -> 2 -> 2 223 // Case 2: 1 -> 2 -> 2
190 for (int i = 0; i < 2; ++i) { 224 for (int i = 0; i < 2; ++i) {
191 AudioChannel* destinationChannel = destinationBus->channel(i); 225 AudioChannel* destinationChannel = destinationBus->channel(i);
192 m_convolvers[i]->process(sourceChannelL, destinationChannel, 226 m_convolvers[i]->process(sourceChannelL, destinationChannel,
193 framesToProcess); 227 framesToProcess);
194 } 228 }
195 } else if (numInputChannels == 1 && numReverbChannels == 1 && 229 } else if (numInputChannels == 1 && numReverbChannels == 1) {
196 numOutputChannels == 2) { 230 // Case 1: 1 -> 1 -> 1
197 // 1 -> 1 -> 2 231 DCHECK_EQ(numOutputChannels, 1ul);
198 m_convolvers[0]->process(sourceChannelL, destinationChannelL,
199 framesToProcess);
200
201 // simply copy L -> R
202 AudioChannel* destinationChannelR = destinationBus->channel(1);
203 bool isCopySafe = destinationChannelL->data() &&
204 destinationChannelR->data() &&
205 destinationChannelL->length() >= framesToProcess &&
206 destinationChannelR->length() >= framesToProcess;
207 ASSERT(isCopySafe);
208 if (!isCopySafe)
209 return;
210 memcpy(destinationChannelR->mutableData(), destinationChannelL->data(),
211 sizeof(float) * framesToProcess);
212 } else if (numInputChannels == 1 && numReverbChannels == 1 &&
213 numOutputChannels == 1) {
214 // 1 -> 1 -> 1
215 m_convolvers[0]->process(sourceChannelL, destinationChannelL, 232 m_convolvers[0]->process(sourceChannelL, destinationChannelL,
216 framesToProcess); 233 framesToProcess);
217 } else if (numInputChannels == 2 && numReverbChannels == 4 && 234 } else if (numInputChannels == 2 && numReverbChannels == 4 &&
218 numOutputChannels == 2) { 235 numOutputChannels == 2) {
219 // 2 -> 4 -> 2 ("True" stereo) 236 // Case 6: 2 -> 4 -> 2 ("True" stereo)
220 const AudioChannel* sourceChannelR = sourceBus->channel(1); 237 const AudioChannel* sourceChannelR = sourceBus->channel(1);
221 AudioChannel* destinationChannelR = destinationBus->channel(1); 238 AudioChannel* destinationChannelR = destinationBus->channel(1);
222 239
223 AudioChannel* tempChannelL = m_tempBuffer->channel(0); 240 AudioChannel* tempChannelL = m_tempBuffer->channel(0);
224 AudioChannel* tempChannelR = m_tempBuffer->channel(1); 241 AudioChannel* tempChannelR = m_tempBuffer->channel(1);
225 242
226 // Process left virtual source 243 // Process left virtual source
227 m_convolvers[0]->process(sourceChannelL, destinationChannelL, 244 m_convolvers[0]->process(sourceChannelL, destinationChannelL,
228 framesToProcess); 245 framesToProcess);
229 m_convolvers[1]->process(sourceChannelL, destinationChannelR, 246 m_convolvers[1]->process(sourceChannelL, destinationChannelR,
230 framesToProcess); 247 framesToProcess);
231 248
232 // Process right virtual source 249 // Process right virtual source
233 m_convolvers[2]->process(sourceChannelR, tempChannelL, framesToProcess); 250 m_convolvers[2]->process(sourceChannelR, tempChannelL, framesToProcess);
234 m_convolvers[3]->process(sourceChannelR, tempChannelR, framesToProcess); 251 m_convolvers[3]->process(sourceChannelR, tempChannelR, framesToProcess);
235 252
236 destinationBus->sumFrom(*m_tempBuffer); 253 destinationBus->sumFrom(*m_tempBuffer);
237 } else if (numInputChannels == 1 && numReverbChannels == 4 && 254 } else if (numInputChannels == 1 && numReverbChannels == 4 &&
238 numOutputChannels == 2) { 255 numOutputChannels == 2) {
239 // 1 -> 4 -> 2 (Processing mono with "True" stereo impulse response) 256 // Case 3: 1 -> 4 -> 2 (Processing mono with "True" stereo impulse
240 // This is an inefficient use of a four-channel impulse response, but we 257 // response) This is an inefficient use of a four-channel impulse
241 // should handle the case. 258 // response, but we should handle the case.
242 AudioChannel* destinationChannelR = destinationBus->channel(1); 259 AudioChannel* destinationChannelR = destinationBus->channel(1);
243 260
244 AudioChannel* tempChannelL = m_tempBuffer->channel(0); 261 AudioChannel* tempChannelL = m_tempBuffer->channel(0);
245 AudioChannel* tempChannelR = m_tempBuffer->channel(1); 262 AudioChannel* tempChannelR = m_tempBuffer->channel(1);
246 263
247 // Process left virtual source 264 // Process left virtual source
248 m_convolvers[0]->process(sourceChannelL, destinationChannelL, 265 m_convolvers[0]->process(sourceChannelL, destinationChannelL,
249 framesToProcess); 266 framesToProcess);
250 m_convolvers[1]->process(sourceChannelL, destinationChannelR, 267 m_convolvers[1]->process(sourceChannelL, destinationChannelR,
251 framesToProcess); 268 framesToProcess);
252 269
253 // Process right virtual source 270 // Process right virtual source
254 m_convolvers[2]->process(sourceChannelL, tempChannelL, framesToProcess); 271 m_convolvers[2]->process(sourceChannelL, tempChannelL, framesToProcess);
255 m_convolvers[3]->process(sourceChannelL, tempChannelR, framesToProcess); 272 m_convolvers[3]->process(sourceChannelL, tempChannelR, framesToProcess);
256 273
257 destinationBus->sumFrom(*m_tempBuffer); 274 destinationBus->sumFrom(*m_tempBuffer);
258 } else { 275 } else {
259 // Handle gracefully any unexpected / unsupported matrixing 276 NOTREACHED();
260 // FIXME: add code for 5.1 support...
261 destinationBus->zero(); 277 destinationBus->zero();
262 } 278 }
263 } 279 }
264 280
265 void Reverb::reset() { 281 void Reverb::reset() {
266 for (size_t i = 0; i < m_convolvers.size(); ++i) 282 for (size_t i = 0; i < m_convolvers.size(); ++i)
267 m_convolvers[i]->reset(); 283 m_convolvers[i]->reset();
268 } 284 }
269 285
270 size_t Reverb::latencyFrames() const { 286 size_t Reverb::latencyFrames() const {
271 return !m_convolvers.isEmpty() ? m_convolvers.front()->latencyFrames() : 0; 287 return !m_convolvers.isEmpty() ? m_convolvers.front()->latencyFrames() : 0;
272 } 288 }
273 289
274 } // namespace blink 290 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698