audio_converter.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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();
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const double io_sample_rate_ratio = input_params.sample_rate() /
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<double>(output_params.sample_rate());
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const int request_size = disable_fifo ? SincResampler::kDefaultRequestSize :
62b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        input_params.frames_per_buffer();
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resampler_.reset(new MultiChannelResampler(
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        downmix_early_ ? output_params.channels() :
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            input_params.channels(),
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        io_sample_rate_ratio, request_size, base::Bind(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &AudioConverter::ProvideInput, base::Unretained(this))));
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  input_frame_duration_ = base::TimeDelta::FromMicroseconds(
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond /
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<double>(input_params.sample_rate()));
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_frame_duration_ = base::TimeDelta::FromMicroseconds(
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond /
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<double>(output_params.sample_rate()));
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The resampler can be configured to work with a specific request size, so a
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // FIFO is not necessary when resampling.
79b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (disable_fifo || resampler_)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Since the output device may want a different buffer size than the caller
83b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // asked for, we need to use a FIFO to ensure that both sides read in chunk
84b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // sizes they're configured for.
85b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer()
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " to " << output_params.frames_per_buffer();
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_.reset(new AudioPullFifo(
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        downmix_early_ ? output_params.channels() :
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            input_params.channels(),
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        input_params.frames_per_buffer(), base::Bind(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &AudioConverter::SourceCallback,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Unretained(this))));
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioConverter::~AudioConverter() {}
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::AddInput(InputCallback* input) {
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TODO(dalecurtis): Speculative CHECK for http://crbug.com/233026, should be
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // converted to a DCHECK once resolved.
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) ==
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        transform_inputs_.end());
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform_inputs_.push_back(input);
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::RemoveInput(InputCallback* input) {
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) !=
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         transform_inputs_.end());
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform_inputs_.remove(input);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transform_inputs_.empty())
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Reset();
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::Reset() {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Clear();
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_)
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resampler_->Flush();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioConverter::ConvertWithDelay(const base::TimeDelta& initial_delay,
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      AudioBus* dest) {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  initial_delay_ = initial_delay;
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transform_inputs_.empty()) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dest->Zero();
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine if channel mixing should be done and if it should be done before
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // or after resampling.  If it's possible to reduce the channel count prior to
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // resampling we can save a lot of processing time.  Vice versa, we don't want
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to increase the channel count prior to resampling for the same reason.
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool needs_mixing = channel_mixer_ && !downmix_early_;
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioBus* temp_dest = needs_mixing ? unmixed_audio_.get() : dest;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(temp_dest);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Figure out which method to call based on whether we're resampling and
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // rebuffering, just resampling, or just mixing.  We want to avoid any extra
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // steps when possible since we may be converting audio data in real time.
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!resampler_ && !audio_fifo_) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SourceCallback(0, temp_dest);
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (resampler_)
147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      resampler_->Resample(temp_dest->frames(), temp_dest);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ProvideInput(0, temp_dest);
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Finally upmix the channels if we didn't do so earlier.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_mixing) {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(temp_dest->frames(), dest->frames());
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_->Transform(temp_dest, dest);
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioConverter::Convert(AudioBus* dest) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ConvertWithDelay(base::TimeDelta::FromMilliseconds(0), dest);
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool needs_downmix = channel_mixer_ && downmix_early_;
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!mixer_input_audio_bus_ ||
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      mixer_input_audio_bus_->frames() != dest->frames()) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    mixer_input_audio_bus_ =
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        AudioBus::Create(input_channel_count_, dest->frames());
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_downmix &&
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (!unmixed_audio_ || unmixed_audio_->frames() != dest->frames())) {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If we're downmixing early we need a temporary AudioBus which matches
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the the input channel count and input frame size since we're passing
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // |unmixed_audio_| directly to the |source_callback_|.
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unmixed_audio_ = AudioBus::Create(input_channel_count_, dest->frames());
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioBus* temp_dest = needs_downmix ? unmixed_audio_.get() : dest;
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check our inputs.
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(temp_dest->frames(), mixer_input_audio_bus_->frames());
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(temp_dest->channels(), mixer_input_audio_bus_->channels());
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculate the buffer delay for this callback.
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta buffer_delay = initial_delay_;
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_) {
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer_delay += base::TimeDelta::FromMicroseconds(
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        resampler_frame_delay_ * output_frame_duration_.InMicroseconds());
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer_delay += base::TimeDelta::FromMicroseconds(
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fifo_frame_delay * input_frame_duration_.InMicroseconds());
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Have each mixer render its data into an output buffer then mix the result.
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (InputCallbackSet::iterator it = transform_inputs_.begin();
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != transform_inputs_.end(); ++it) {
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InputCallback* input = *it;
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    float volume = input->ProvideInput(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mixer_input_audio_bus_.get(), buffer_delay);
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Optimize the most common single input, full volume case.
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it == transform_inputs_.begin()) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (volume == 1.0f) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        mixer_input_audio_bus_->CopyTo(temp_dest);
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (volume > 0) {
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          vector_math::FMUL(
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              mixer_input_audio_bus_->channel(i), volume,
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              mixer_input_audio_bus_->frames(), temp_dest->channel(i));
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        temp_dest->Zero();
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Volume adjust and mix each mixer input into |temp_dest| after rendering.
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (volume > 0) {
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vector_math::FMAC(
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mixer_input_audio_bus_->channel(i), volume,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mixer_input_audio_bus_->frames(), temp_dest->channel(i));
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_downmix) {
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(temp_dest->frames(), dest->frames());
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_->Transform(temp_dest, dest);
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::ProvideInput(int resampler_frame_delay, AudioBus* dest) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  resampler_frame_delay_ = resampler_frame_delay;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Consume(dest, dest->frames());
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SourceCallback(0, dest);
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace media
248