summaryrefslogtreecommitdiff
path: root/media/base/audio_converter.cc
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-05-09 18:35:53 +0100
committerTorne (Richard Coles) <torne@google.com>2013-05-13 13:57:14 +0100
commitc2e0dbddbe15c98d52c4786dac06cb8952a8ae6d (patch)
tree1dbdbb0624cc869ab25ee7f46971984c6fee3e7a /media/base/audio_converter.cc
parent2d519ce2457219605d4f472da8d2ffd469796035 (diff)
downloadchromium_org-c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d.tar.gz
Merge from Chromium at DEPS revision r198571
This commit was generated by merge_to_master.py. Change-Id: I951118a03836157090561764dd2627f0add8118f
Diffstat (limited to 'media/base/audio_converter.cc')
-rw-r--r--media/base/audio_converter.cc42
1 files changed, 37 insertions, 5 deletions
diff --git a/media/base/audio_converter.cc b/media/base/audio_converter.cc
index 5fda460a61..7ffc9aea4a 100644
--- a/media/base/audio_converter.cc
+++ b/media/base/audio_converter.cc
@@ -1,6 +1,12 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+//
+// AudioConverter implementation. Uses MultiChannelSincResampler for resampling
+// audio, ChannelMixer for channel mixing, and AudioPullFifo for buffering.
+//
+// Delay estimates are provided to InputCallbacks based on the frame delay
+// information reported via the resampler and FIFO units.
#include "media/base/audio_converter.h"
@@ -88,6 +94,10 @@ AudioConverter::AudioConverter(const AudioParameters& input_params,
AudioConverter::~AudioConverter() {}
void AudioConverter::AddInput(InputCallback* input) {
+ // TODO(dalecurtis): Speculative CHECK for http://crbug.com/233026, should be
+ // converted to a DCHECK once resolved.
+ CHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) ==
+ transform_inputs_.end());
transform_inputs_.push_back(input);
}
@@ -107,16 +117,26 @@ void AudioConverter::Reset() {
resampler_->Flush();
}
-void AudioConverter::Convert(AudioBus* dest) {
+void AudioConverter::ConvertWithDelay(const base::TimeDelta& initial_delay,
+ AudioBus* dest) {
+ initial_delay_ = initial_delay;
+
if (transform_inputs_.empty()) {
dest->Zero();
return;
}
+ // Determine if channel mixing should be done and if it should be done before
+ // or after resampling. If it's possible to reduce the channel count prior to
+ // resampling we can save a lot of processing time. Vice versa, we don't want
+ // to increase the channel count prior to resampling for the same reason.
bool needs_mixing = channel_mixer_ && !downmix_early_;
AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest;
DCHECK(temp_dest);
+ // Figure out which method to call based on whether we're resampling and
+ // rebuffering, just resampling, or just mixing. We want to avoid any extra
+ // steps when possible since we may be converting audio data in real time.
if (!resampler_ && !audio_fifo_) {
SourceCallback(0, temp_dest);
} else {
@@ -126,12 +146,17 @@ void AudioConverter::Convert(AudioBus* dest) {
ProvideInput(0, temp_dest);
}
+ // Finally upmix the channels if we didn't do so earlier.
if (needs_mixing) {
DCHECK_EQ(temp_dest->frames(), dest->frames());
channel_mixer_->Transform(temp_dest, dest);
}
}
+void AudioConverter::Convert(AudioBus* dest) {
+ ConvertWithDelay(base::TimeDelta::FromMilliseconds(0), dest);
+}
+
void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
bool needs_downmix = channel_mixer_ && downmix_early_;
@@ -156,7 +181,7 @@ void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
DCHECK_EQ(temp_dest->channels(), mixer_input_audio_bus_->channels());
// Calculate the buffer delay for this callback.
- base::TimeDelta buffer_delay;
+ base::TimeDelta buffer_delay = initial_delay_;
if (resampler_) {
buffer_delay += base::TimeDelta::FromMicroseconds(
resampler_frame_delay_ * output_frame_duration_.InMicroseconds());
@@ -178,11 +203,18 @@ void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
if (it == transform_inputs_.begin()) {
if (volume == 1.0f) {
mixer_input_audio_bus_->CopyTo(temp_dest);
- continue;
+ } else if (volume > 0) {
+ for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
+ vector_math::FMUL(
+ mixer_input_audio_bus_->channel(i), volume,
+ mixer_input_audio_bus_->frames(), temp_dest->channel(i));
+ }
+ } else {
+ // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
+ temp_dest->Zero();
}
- // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
- temp_dest->Zero();
+ continue;
}
// Volume adjust and mix each mixer input into |temp_dest| after rendering.