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

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

Issue 1773973002: Complete the implementation of up/down-mixing rules for AudioNode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Simplifying AudioBus::copyFrom Created 4 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
« no previous file with comments | « third_party/WebKit/Source/platform/audio/AudioBus.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 { 209 {
210 for (unsigned i = 0; i < numberOfChannels(); ++i) 210 for (unsigned i = 0; i < numberOfChannels(); ++i)
211 channel(i)->scale(scale); 211 channel(i)->scale(scale);
212 } 212 }
213 213
214 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channel Interpretation) 214 void AudioBus::copyFrom(const AudioBus& sourceBus, ChannelInterpretation channel Interpretation)
215 { 215 {
216 if (&sourceBus == this) 216 if (&sourceBus == this)
217 return; 217 return;
218 218
219 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 219 // Copying bus is equivalent to zeroing and then summing.
220 unsigned numberOfDestinationChannels = numberOfChannels(); 220 zero();
221 221 sumFrom(sourceBus, channelInterpretation);
222 if (numberOfDestinationChannels == numberOfSourceChannels) {
223 for (unsigned i = 0; i < numberOfSourceChannels; ++i)
224 channel(i)->copyFrom(sourceBus.channel(i));
225 } else {
226 switch (channelInterpretation) {
227 case Speakers:
228 speakersCopyFrom(sourceBus);
229 break;
230 case Discrete:
231 discreteCopyFrom(sourceBus);
232 break;
233 default:
234 ASSERT_NOT_REACHED();
235 }
236 }
237 } 222 }
238 223
239 void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelI nterpretation) 224 void AudioBus::sumFrom(const AudioBus& sourceBus, ChannelInterpretation channelI nterpretation)
240 { 225 {
241 if (&sourceBus == this) 226 if (&sourceBus == this)
242 return; 227 return;
243 228
244 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 229 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
245 unsigned numberOfDestinationChannels = numberOfChannels(); 230 unsigned numberOfDestinationChannels = numberOfChannels();
246 231
247 if (numberOfDestinationChannels == numberOfSourceChannels) { 232 // If the channel numbers are equal, perform channels-wise summing.
233 if (numberOfSourceChannels == numberOfDestinationChannels) {
248 for (unsigned i = 0; i < numberOfSourceChannels; ++i) 234 for (unsigned i = 0; i < numberOfSourceChannels; ++i)
249 channel(i)->sumFrom(sourceBus.channel(i)); 235 channel(i)->sumFrom(sourceBus.channel(i));
250 } else { 236
251 switch (channelInterpretation) { 237 return;
252 case Speakers: 238 }
253 speakersSumFrom(sourceBus); 239
254 break; 240 // Otherwise perform up/down-mix or the discrete transfer based on the
255 case Discrete: 241 // number of channels and the channel interpretation.
256 discreteSumFrom(sourceBus); 242 switch (channelInterpretation) {
257 break; 243 case Speakers:
258 default: 244 if (numberOfSourceChannels < numberOfDestinationChannels)
259 ASSERT_NOT_REACHED(); 245 processUpMix(sourceBus);
260 } 246 else
247 processDownMix(sourceBus);
Raymond Toy 2016/03/09 22:14:19 To make it more obvious can we somehow include "su
hongchan 2016/03/09 23:26:11 Done.
248 break;
249 case Discrete:
250 discreteSumFrom(sourceBus);
251 break;
261 } 252 }
262 } 253 }
263 254
264 void AudioBus::speakersCopyFrom(const AudioBus& sourceBus) 255 void AudioBus::processUpMix(const AudioBus& sourceBus)
265 { 256 {
266 // FIXME: Implement down mixing 5.1 to stereo.
267 // https://bugs.webkit.org/show_bug.cgi?id=79192
268
269 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 257 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
270 unsigned numberOfDestinationChannels = numberOfChannels(); 258 unsigned numberOfDestinationChannels = numberOfChannels();
271 259
272 if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) { 260 // Up-mixing: 1 -> 2, 1 -> 4
273 // Handle mono -> stereo case (for now simply copy mono channel into bot h left and right) 261 // output.L = input
274 // FIXME: Really we should apply an equal-power scaling factor here, sin ce we're effectively panning center... 262 // output.R = input
275 const AudioChannel* sourceChannel = sourceBus.channel(0); 263 // output.SL = 0 (in the case of 1 -> 4)
276 channel(0)->copyFrom(sourceChannel); 264 // output.SR = 0 (in the case of 1 -> 4)
277 channel(1)->copyFrom(sourceChannel); 265 if ((numberOfSourceChannels == 1 && numberOfDestinationChannels == 2) || (nu mberOfSourceChannels == 1 && numberOfDestinationChannels == 4)) {
278 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) {
279 // Handle stereo -> mono case. output = 0.5 * (input.L + input.R).
280 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
281
282 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
283 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data() ;
284
285 float* destination = channelByType(ChannelLeft)->mutableData();
286 vadd(sourceL, 1, sourceR, 1, destination, 1, length());
287 float scale = 0.5;
288 vsmul(destination, 1, &scale, destination, 1, length());
289 } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) {
290 // Handle mono -> 5.1 case, copy mono channel to center.
291 channel(2)->copyFrom(sourceBus.channel(0));
292 channel(0)->zero();
293 channel(1)->zero();
294 channel(3)->zero();
295 channel(4)->zero();
296 channel(5)->zero();
297 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) {
298 // Handle 5.1 -> mono case.
299 zero();
300 speakersSumFrom5_1_ToMono(sourceBus);
301 } else {
302 // Fallback for unknown combinations.
303 discreteCopyFrom(sourceBus);
304 }
305 }
306
307 void AudioBus::speakersSumFrom(const AudioBus& sourceBus)
308 {
309 // FIXME: Implement down mixing 5.1 to stereo.
310 // https://bugs.webkit.org/show_bug.cgi?id=79192
311
312 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
313 unsigned numberOfDestinationChannels = numberOfChannels();
314
315 if (numberOfDestinationChannels == 2 && numberOfSourceChannels == 1) {
316 // Handle mono -> stereo case (summing mono channel into both left and r ight).
317 const AudioChannel* sourceChannel = sourceBus.channel(0); 266 const AudioChannel* sourceChannel = sourceBus.channel(0);
318 channel(0)->sumFrom(sourceChannel); 267 channel(0)->sumFrom(sourceChannel);
319 channel(1)->sumFrom(sourceChannel); 268 channel(1)->sumFrom(sourceChannel);
320 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 2) { 269
321 // Handle stereo -> mono case. output += 0.5 * (input.L + input.R). 270 return;
322 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus); 271 }
323 272
324 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data(); 273 // Up-mixing: 1 -> 5.1
325 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data() ; 274 // output.L = 0
275 // output.R = 0
276 // output.C = input (put in center channel)
277 // output.LFE = 0
278 // output.SL = 0
279 // output.SR = 0
280 if (numberOfSourceChannels == 1 && numberOfDestinationChannels == 6) {
281 channel(2)->sumFrom(sourceBus.channel(0));
282
283 return;
284 }
285
286 // Up-mixing: 2 -> 4, 2 -> 5.1
287 // output.L = input.L
288 // output.R = input.R
289 // output.C = 0 (in the case of 2 -> 5.1)
290 // output.LFE = 0 (in the case of 2 -> 5.1)
291 // output.SL = 0
292 // output.SR = 0
293 if ((numberOfSourceChannels == 2 && numberOfDestinationChannels == 4) || (nu mberOfSourceChannels == 2 && numberOfDestinationChannels == 6)) {
294 channel(0)->sumFrom(sourceBus.channel(0));
295 channel(1)->sumFrom(sourceBus.channel(1));
296
297 return;
298 }
299
300 // Up-mixing: 4 -> 5.1
301 // output.L = input.L
302 // output.R = input.R
303 // output.C = 0
304 // output.LFE = 0
305 // output.SL = input.SL
306 // output.SR = input.SR
307 if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 6) {
308 channel(0)->sumFrom(sourceBus.channel(0));
309 channel(1)->sumFrom(sourceBus.channel(1));
310 channel(4)->sumFrom(sourceBus.channel(2));
311 channel(5)->sumFrom(sourceBus.channel(3));
312
313 return;
314 }
315
316 // All other cases, fall back to the discrete sum. This will silence the
317 // excessive channels.
318 discreteSumFrom(sourceBus);
319 }
320
321 void AudioBus::processDownMix(const AudioBus& sourceBus)
322 {
323 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
324 unsigned numberOfDestinationChannels = numberOfChannels();
325
326 // Down-mixing: 2 -> 1
327 // output = 0.5 * (input.L + input.R)
328 if (numberOfSourceChannels == 2 && numberOfDestinationChannels == 1) {
329 AudioBus& sourceBusConst = const_cast<AudioBus&>(sourceBus);
330 const float* sourceL = sourceBusConst.channelByType(ChannelLeft)->data() ;
331 const float* sourceR = sourceBusConst.channelByType(ChannelRight)->data( );
326 332
327 float* destination = channelByType(ChannelLeft)->mutableData(); 333 float* destination = channelByType(ChannelLeft)->mutableData();
328 float scale = 0.5; 334 float scale = 0.5;
335
329 vsma(sourceL, 1, &scale, destination, 1, length()); 336 vsma(sourceL, 1, &scale, destination, 1, length());
330 vsma(sourceR, 1, &scale, destination, 1, length()); 337 vsma(sourceR, 1, &scale, destination, 1, length());
331 } else if (numberOfDestinationChannels == 6 && numberOfSourceChannels == 1) { 338 return;
332 // Handle mono -> 5.1 case, sum mono channel into center. 339 }
333 channel(2)->sumFrom(sourceBus.channel(0)); 340
334 } else if (numberOfDestinationChannels == 1 && numberOfSourceChannels == 6) { 341 // Down-mixing: 4 -> 1
335 // Handle 5.1 -> mono case. 342 // output = 0.25 * (input.L + input.R + input.SL + input.SR)
336 speakersSumFrom5_1_ToMono(sourceBus); 343 if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 1) {
Raymond Toy 2016/03/09 22:14:19 I find it clearer if this set of if's were written
hongchan 2016/03/09 23:26:11 Done.
337 } else { 344 AudioBus& sourceBusConst = const_cast<AudioBus&>(sourceBus);
338 // Fallback for unknown combinations. 345 const float* sourceL = sourceBusConst.channelByType(ChannelLeft)->data() ;
339 discreteSumFrom(sourceBus); 346 const float* sourceR = sourceBusConst.channelByType(ChannelRight)->data( );
340 } 347 const float* sourceSL = sourceBusConst.channelByType(ChannelSurroundLeft )->data();
348 const float* sourceSR = sourceBusConst.channelByType(ChannelSurroundRigh t)->data();
349
350 float* destination = channelByType(ChannelLeft)->mutableData();
351 float scale = 0.25;
352
353 vsma(sourceL, 1, &scale, destination, 1, length());
354 vsma(sourceR, 1, &scale, destination, 1, length());
355 vsma(sourceSL, 1, &scale, destination, 1, length());
356 vsma(sourceSR, 1, &scale, destination, 1, length());
357 return;
358 }
359
360 // Down-mixing: 5.1 -> 1
361 // output = sqrt(1/2) * (input.L + input.R) + input.C
362 // + 0.5 * (input.SL + input.SR)
363 if (numberOfSourceChannels == 6 && numberOfDestinationChannels == 1) {
364 AudioBus& sourceBusConst = const_cast<AudioBus&>(sourceBus);
365 const float* sourceL = sourceBusConst.channelByType(ChannelLeft)->data() ;
366 const float* sourceR = sourceBusConst.channelByType(ChannelRight)->data( );
367 const float* sourceC = sourceBusConst.channelByType(ChannelCenter)->data ();
368 const float* sourceSL = sourceBusConst.channelByType(ChannelSurroundLeft )->data();
369 const float* sourceSR = sourceBusConst.channelByType(ChannelSurroundRigh t)->data();
370
371 float* destination = channelByType(ChannelLeft)->mutableData();
372 float scaleSqrtHalf = sqrtf(0.5);
373 float scaleHalf = 0.5;
374
375 vsma(sourceL, 1, &scaleSqrtHalf, destination, 1, length());
376 vsma(sourceR, 1, &scaleSqrtHalf, destination, 1, length());
377 vadd(sourceC, 1, destination, 1, destination, 1, length());
378 vsma(sourceSL, 1, &scaleHalf, destination, 1, length());
379 vsma(sourceSR, 1, &scaleHalf, destination, 1, length());
380 return;
381 }
382
383 // Down-mixing: 4 -> 2
384 // output.L = 0.5 * (input.L + input.SL)
385 // output.R = 0.5 * (input.R + input.SR)
386 if (numberOfSourceChannels == 4 && numberOfDestinationChannels == 2) {
387 AudioBus& sourceBusConst = const_cast<AudioBus&>(sourceBus);
388 const float* sourceL = sourceBusConst.channelByType(ChannelLeft)->data() ;
389 const float* sourceR = sourceBusConst.channelByType(ChannelRight)->data( );
390 const float* sourceSL = sourceBusConst.channelByType(ChannelSurroundLeft )->data();
391 const float* sourceSR = sourceBusConst.channelByType(ChannelSurroundRigh t)->data();
392
393 float* destinationL = channelByType(ChannelLeft)->mutableData();
394 float* destinationR = channelByType(ChannelRight)->mutableData();
395 float scaleHalf = 0.5;
396
397 vsma(sourceL, 1, &scaleHalf, destinationL, 1, length());
398 vsma(sourceSL, 1, &scaleHalf, destinationL, 1, length());
399 vsma(sourceR, 1, &scaleHalf, destinationR, 1, length());
400 vsma(sourceSR, 1, &scaleHalf, destinationR, 1, length());
401 return;
402 }
403
404 // Down-mixing: 5.1 -> 2
405 // output.L = input.L + sqrt(1/2) * (input.C + input.SL)
406 // output.R = input.R + sqrt(1/2) * (input.C + input.SR)
407 if (numberOfSourceChannels == 6 && numberOfDestinationChannels == 2) {
408 AudioBus& sourceBusConst = const_cast<AudioBus&>(sourceBus);
409 const float* sourceL = sourceBusConst.channelByType(ChannelLeft)->data() ;
410 const float* sourceR = sourceBusConst.channelByType(ChannelRight)->data( );
411 const float* sourceC = sourceBusConst.channelByType(ChannelCenter)->data ();
412 const float* sourceSL = sourceBusConst.channelByType(ChannelSurroundLeft )->data();
413 const float* sourceSR = sourceBusConst.channelByType(ChannelSurroundRigh t)->data();
414
415 float* destinationL = channelByType(ChannelLeft)->mutableData();
416 float* destinationR = channelByType(ChannelRight)->mutableData();
417 float scaleSqrtHalf = sqrtf(0.5);
418
419 vadd(sourceL, 1, destinationL, 1, destinationL, 1, length());
420 vsma(sourceC, 1, &scaleSqrtHalf, destinationL, 1, length());
421 vsma(sourceSL, 1, &scaleSqrtHalf, destinationL, 1, length());
422 vadd(sourceR, 1, destinationR, 1, destinationR, 1, length());
423 vsma(sourceC, 1, &scaleSqrtHalf, destinationR, 1, length());
424 vsma(sourceSR, 1, &scaleSqrtHalf, destinationR, 1, length());
425 return;
426 }
427
428 // Down-mixing: 5.1 -> 4
429 // output.L = input.L + sqrt(1/2) * input.C
430 // output.R = input.R + sqrt(1/2) * input.C
431 // output.SL = input.SL
432 // output.SR = input.SR
433 if (numberOfSourceChannels == 6 && numberOfDestinationChannels == 4) {
434 AudioBus& sourceBusConst = const_cast<AudioBus&>(sourceBus);
435 const float* sourceL = sourceBusConst.channelByType(ChannelLeft)->data() ;
436 const float* sourceR = sourceBusConst.channelByType(ChannelRight)->data( );
437 const float* sourceC = sourceBusConst.channelByType(ChannelCenter)->data ();
438
439 float* destinationL = channelByType(ChannelLeft)->mutableData();
440 float* destinationR = channelByType(ChannelRight)->mutableData();
441 float scaleSqrtHalf = sqrtf(0.5);
442
443 vadd(sourceL, 1, destinationL, 1, destinationL, 1, length());
444 vsma(sourceC, 1, &scaleSqrtHalf, destinationL, 1, length());
445 vadd(sourceR, 1, destinationR, 1, destinationR, 1, length());
446 vsma(sourceC, 1, &scaleSqrtHalf, destinationR, 1, length());
447 channel(2)->sumFrom(sourceBus.channel(4));
448 channel(3)->sumFrom(sourceBus.channel(5));
449 return;
450 }
451
452 // All other cases, fall back to the discrete sum. This will perform
453 // channel-wise sum until the destination channels run out.
454 discreteSumFrom(sourceBus);
341 } 455 }
342 456
343 void AudioBus::speakersSumFrom5_1_ToMono(const AudioBus& sourceBus)
344 {
345 AudioBus& sourceBusSafe = const_cast<AudioBus&>(sourceBus);
346
347 const float* sourceL = sourceBusSafe.channelByType(ChannelLeft)->data();
348 const float* sourceR = sourceBusSafe.channelByType(ChannelRight)->data();
349 const float* sourceC = sourceBusSafe.channelByType(ChannelCenter)->data();
350 const float* sourceSL = sourceBusSafe.channelByType(ChannelSurroundLeft)->da ta();
351 const float* sourceSR = sourceBusSafe.channelByType(ChannelSurroundRight)->d ata();
352
353 float* destination = channelByType(ChannelLeft)->mutableData();
354
355 AudioFloatArray temp(length());
356 float* tempData = temp.data();
357
358 // Sum in L and R.
359 vadd(sourceL, 1, sourceR, 1, tempData, 1, length());
360 float scale = 0.7071;
361 vsmul(tempData, 1, &scale, tempData, 1, length());
362 vadd(tempData, 1, destination, 1, destination, 1, length());
363
364 // Sum in SL and SR.
365 vadd(sourceSL, 1, sourceSR, 1, tempData, 1, length());
366 scale = 0.5;
367 vsmul(tempData, 1, &scale, tempData, 1, length());
368 vadd(tempData, 1, destination, 1, destination, 1, length());
369
370 // Sum in center.
371 vadd(sourceC, 1, destination, 1, destination, 1, length());
372 }
373
374 void AudioBus::discreteCopyFrom(const AudioBus& sourceBus) 457 void AudioBus::discreteCopyFrom(const AudioBus& sourceBus)
375 { 458 {
376 unsigned numberOfSourceChannels = sourceBus.numberOfChannels(); 459 unsigned numberOfSourceChannels = sourceBus.numberOfChannels();
377 unsigned numberOfDestinationChannels = numberOfChannels(); 460 unsigned numberOfDestinationChannels = numberOfChannels();
378 461
379 if (numberOfDestinationChannels < numberOfSourceChannels) { 462 if (numberOfDestinationChannels < numberOfSourceChannels) {
380 // Down-mix by copying channels and dropping the remaining. 463 // Down-mix by copying channels and dropping the remaining.
381 for (unsigned i = 0; i < numberOfDestinationChannels; ++i) 464 for (unsigned i = 0; i < numberOfDestinationChannels; ++i)
382 channel(i)->copyFrom(sourceBus.channel(i)); 465 channel(i)->copyFrom(sourceBus.channel(i));
383 } else if (numberOfDestinationChannels > numberOfSourceChannels) { 466 } else if (numberOfDestinationChannels > numberOfSourceChannels) {
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 759
677 // If the bus needs no conversion then return as is. 760 // If the bus needs no conversion then return as is.
678 if ((!mixToMono || audioBus->numberOfChannels() == 1) && audioBus->sampleRat e() == sampleRate) 761 if ((!mixToMono || audioBus->numberOfChannels() == 1) && audioBus->sampleRat e() == sampleRate)
679 return audioBus; 762 return audioBus;
680 763
681 return AudioBus::createBySampleRateConverting(audioBus.get(), mixToMono, sam pleRate); 764 return AudioBus::createBySampleRateConverting(audioBus.get(), mixToMono, sam pleRate);
682 } 765 }
683 766
684 } // namespace blink 767 } // namespace blink
685 768
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/audio/AudioBus.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698