audio_converter.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// AudioConverter implementation.  Uses MultiChannelSincResampler for resampling
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// audio, ChannelMixer for channel mixing, and AudioPullFifo for buffering.
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Delay estimates are provided to InputCallbacks based on the frame delay
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// information reported via the resampler and FIFO units.
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_converter.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind_helpers.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_pull_fifo.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_mixer.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/multi_channel_resampler.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/vector_math.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioConverter::AudioConverter(const AudioParameters& input_params,
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const AudioParameters& output_params,
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               bool disable_fifo)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : downmix_early_(false),
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      resampler_frame_delay_(0),
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_channel_count_(input_params.channels()) {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(input_params.IsValid());
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(output_params.IsValid());
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handle different input and output channel layouts.
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (input_params.channel_layout() != output_params.channel_layout()) {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout()
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " to " << output_params.channel_layout() << "; from "
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << input_params.channels() << " channels to "
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << output_params.channels() << " channels.";
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_.reset(new ChannelMixer(input_params, output_params));
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Pare off data as early as we can for efficiency.
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    downmix_early_ = input_params.channels() > output_params.channels();
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (downmix_early_) {
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DVLOG(1) << "Remixing channel layout prior to resampling.";
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // |unmixed_audio_| will be allocated on the fly.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Instead, if we're not downmixing early we need a temporary AudioBus
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // which matches the input channel count but uses the output frame size
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // since we'll mix into the AudioBus from the output stream.
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unmixed_audio_ = AudioBus::Create(
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          input_params.channels(), output_params.frames_per_buffer());
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only resample if necessary since it's expensive.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (input_params.sample_rate() != output_params.sample_rate()) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << output_params.sample_rate();
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    double io_sample_rate_ratio = input_params.sample_rate() /
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<double>(output_params.sample_rate());
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resampler_.reset(new MultiChannelResampler(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        downmix_early_ ? output_params.channels() :
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            input_params.channels(),
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        io_sample_rate_ratio, base::Bind(
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &AudioConverter::ProvideInput, base::Unretained(this))));
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  input_frame_duration_ = base::TimeDelta::FromMicroseconds(
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond /
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<double>(input_params.sample_rate()));
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_frame_duration_ = base::TimeDelta::FromMicroseconds(
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond /
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<double>(output_params.sample_rate()));
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (disable_fifo)
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since the resampler / output device may want a different buffer size than
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the caller asked for, we need to use a FIFO to ensure that both sides
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // read in chunk sizes they're configured for.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_.get() ||
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer()
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " to " << output_params.frames_per_buffer();
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_.reset(new AudioPullFifo(
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        downmix_early_ ? output_params.channels() :
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            input_params.channels(),
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        input_params.frames_per_buffer(), base::Bind(
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &AudioConverter::SourceCallback,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Unretained(this))));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioConverter::~AudioConverter() {}
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::AddInput(InputCallback* input) {
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dalecurtis): Speculative CHECK for http://crbug.com/233026, should be
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // converted to a DCHECK once resolved.
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) ==
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        transform_inputs_.end());
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform_inputs_.push_back(input);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::RemoveInput(InputCallback* input) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) !=
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         transform_inputs_.end());
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform_inputs_.remove(input);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transform_inputs_.empty())
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Reset();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::Reset() {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Clear();
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resampler_->Flush();
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioConverter::ConvertWithDelay(const base::TimeDelta& initial_delay,
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      AudioBus* dest) {
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  initial_delay_ = initial_delay;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transform_inputs_.empty()) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dest->Zero();
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine if channel mixing should be done and if it should be done before
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // or after resampling.  If it's possible to reduce the channel count prior to
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // resampling we can save a lot of processing time.  Vice versa, we don't want
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to increase the channel count prior to resampling for the same reason.
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool needs_mixing = channel_mixer_ && !downmix_early_;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(temp_dest);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Figure out which method to call based on whether we're resampling and
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // rebuffering, just resampling, or just mixing.  We want to avoid any extra
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // steps when possible since we may be converting audio data in real time.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!resampler_ && !audio_fifo_) {
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SourceCallback(0, temp_dest);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (resampler_)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      resampler_->Resample(temp_dest, temp_dest->frames());
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProvideInput(0, temp_dest);
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Finally upmix the channels if we didn't do so earlier.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_mixing) {
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(temp_dest->frames(), dest->frames());
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_->Transform(temp_dest, dest);
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioConverter::Convert(AudioBus* dest) {
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConvertWithDelay(base::TimeDelta::FromMilliseconds(0), dest);
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool needs_downmix = channel_mixer_ && downmix_early_;
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!mixer_input_audio_bus_ ||
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mixer_input_audio_bus_->frames() != dest->frames()) {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_input_audio_bus_ =
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AudioBus::Create(input_channel_count_, dest->frames());
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_downmix &&
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (!unmixed_audio_ || unmixed_audio_->frames() != dest->frames())) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If we're downmixing early we need a temporary AudioBus which matches
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the the input channel count and input frame size since we're passing
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |unmixed_audio_| directly to the |source_callback_|.
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unmixed_audio_ = AudioBus::Create(input_channel_count_, dest->frames());
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioBus* temp_dest = needs_downmix ? unmixed_audio_.get() : dest;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check our inputs.
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(temp_dest->frames(), mixer_input_audio_bus_->frames());
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(temp_dest->channels(), mixer_input_audio_bus_->channels());
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculate the buffer delay for this callback.
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta buffer_delay = initial_delay_;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_) {
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer_delay += base::TimeDelta::FromMicroseconds(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        resampler_frame_delay_ * output_frame_duration_.InMicroseconds());
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_) {
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer_delay += base::TimeDelta::FromMicroseconds(
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fifo_frame_delay * input_frame_duration_.InMicroseconds());
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Have each mixer render its data into an output buffer then mix the result.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (InputCallbackSet::iterator it = transform_inputs_.begin();
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != transform_inputs_.end(); ++it) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InputCallback* input = *it;
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float volume = input->ProvideInput(
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mixer_input_audio_bus_.get(), buffer_delay);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Optimize the most common single input, full volume case.
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it == transform_inputs_.begin()) {
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (volume == 1.0f) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mixer_input_audio_bus_->CopyTo(temp_dest);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (volume > 0) {
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          vector_math::FMUL(
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              mixer_input_audio_bus_->channel(i), volume,
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              mixer_input_audio_bus_->frames(), temp_dest->channel(i));
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        temp_dest->Zero();
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Volume adjust and mix each mixer input into |temp_dest| after rendering.
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (volume > 0) {
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vector_math::FMAC(
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mixer_input_audio_bus_->channel(i), volume,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mixer_input_audio_bus_->frames(), temp_dest->channel(i));
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_downmix) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(temp_dest->frames(), dest->frames());
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_->Transform(temp_dest, dest);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::ProvideInput(int resampler_frame_delay, AudioBus* dest) {
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  resampler_frame_delay_ = resampler_frame_delay;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Consume(dest, dest->frames());
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SourceCallback(0, dest);
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace media
245