audio_converter.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/base/audio_bus.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/audio_pull_fifo.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_mixer.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/multi_channel_resampler.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/vector_math.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioConverter::AudioConverter(const AudioParameters& input_params,
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               const AudioParameters& output_params,
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               bool disable_fifo)
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : chunk_size_(input_params.frames_per_buffer()),
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      downmix_early_(false),
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      resampler_frame_delay_(0),
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      input_channel_count_(input_params.channels()) {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(input_params.IsValid());
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(output_params.IsValid());
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handle different input and output channel layouts.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (input_params.channel_layout() != output_params.channel_layout()) {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Remixing channel layout from " << input_params.channel_layout()
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " to " << output_params.channel_layout() << "; from "
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << input_params.channels() << " channels to "
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << output_params.channels() << " channels.";
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_.reset(new ChannelMixer(input_params, output_params));
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Pare off data as early as we can for efficiency.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    downmix_early_ = input_params.channels() > output_params.channels();
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only resample if necessary since it's expensive.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (input_params.sample_rate() != output_params.sample_rate()) {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << output_params.sample_rate();
51b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const int request_size = disable_fifo ? SincResampler::kDefaultRequestSize :
52b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        input_params.frames_per_buffer();
53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const double io_sample_rate_ratio =
54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        input_params.sample_rate() /
55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        static_cast<double>(output_params.sample_rate());
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resampler_.reset(new MultiChannelResampler(
57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        downmix_early_ ? output_params.channels() : input_params.channels(),
58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        io_sample_rate_ratio,
59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        request_size,
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(&AudioConverter::ProvideInput, base::Unretained(this))));
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  input_frame_duration_ = base::TimeDelta::FromMicroseconds(
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond /
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<double>(input_params.sample_rate()));
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  output_frame_duration_ = base::TimeDelta::FromMicroseconds(
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Time::kMicrosecondsPerSecond /
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<double>(output_params.sample_rate()));
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
70b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // The resampler can be configured to work with a specific request size, so a
71b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // FIFO is not necessary when resampling.
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (disable_fifo || resampler_)
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
75b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Since the output device may want a different buffer size than the caller
76b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // asked for, we need to use a FIFO to ensure that both sides read in chunk
77b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // sizes they're configured for.
78b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (input_params.frames_per_buffer() != output_params.frames_per_buffer()) {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DVLOG(1) << "Rebuffering from " << input_params.frames_per_buffer()
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             << " to " << output_params.frames_per_buffer();
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    chunk_size_ = input_params.frames_per_buffer();
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_.reset(new AudioPullFifo(
8323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        downmix_early_ ? output_params.channels() : input_params.channels(),
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        chunk_size_,
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)        base::Bind(&AudioConverter::SourceCallback, base::Unretained(this))));
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AudioConverter::~AudioConverter() {}
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::AddInput(InputCallback* input) {
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) ==
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         transform_inputs_.end());
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform_inputs_.push_back(input);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::RemoveInput(InputCallback* input) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(std::find(transform_inputs_.begin(), transform_inputs_.end(), input) !=
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         transform_inputs_.end());
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  transform_inputs_.remove(input);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transform_inputs_.empty())
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Reset();
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::Reset() {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Clear();
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resampler_->Flush();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)int AudioConverter::ChunkSize() const {
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!resampler_)
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return chunk_size_;
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return resampler_->ChunkSize();
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AudioConverter::ConvertWithDelay(const base::TimeDelta& initial_delay,
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      AudioBus* dest) {
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  initial_delay_ = initial_delay;
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (transform_inputs_.empty()) {
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    dest->Zero();
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Determine if channel mixing should be done and if it should be done before
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // or after resampling.  If it's possible to reduce the channel count prior to
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // resampling we can save a lot of processing time.  Vice versa, we don't want
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // to increase the channel count prior to resampling for the same reason.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool needs_mixing = channel_mixer_ && !downmix_early_;
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (needs_mixing)
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    CreateUnmixedAudioIfNecessary(dest->frames());
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
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) {
164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const 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)
17223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // If we're downmixing early we need a temporary AudioBus which matches
17323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // the the input channel count and input frame size since we're passing
17423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |unmixed_audio_| directly to the |source_callback_|.
17523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (needs_downmix)
17623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    CreateUnmixedAudioIfNecessary(dest->frames());
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AudioBus* const temp_dest = needs_downmix ? unmixed_audio_.get() : dest;
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sanity check our inputs.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(temp_dest->frames(), mixer_input_audio_bus_->frames());
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(temp_dest->channels(), mixer_input_audio_bus_->channels());
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calculate the buffer delay for this callback.
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta buffer_delay = initial_delay_;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (resampler_) {
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer_delay += base::TimeDelta::FromMicroseconds(
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        resampler_frame_delay_ * output_frame_duration_.InMicroseconds());
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_) {
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    buffer_delay += base::TimeDelta::FromMicroseconds(
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        fifo_frame_delay * input_frame_duration_.InMicroseconds());
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // If we only have a single input, avoid an extra copy.
196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  AudioBus* const provide_input_dest =
197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      transform_inputs_.size() == 1 ? temp_dest : mixer_input_audio_bus_.get();
198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Have each mixer render its data into an output buffer then mix the result.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (InputCallbackSet::iterator it = transform_inputs_.begin();
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != transform_inputs_.end(); ++it) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InputCallback* input = *it;
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const float volume = input->ProvideInput(provide_input_dest, buffer_delay);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Optimize the most common single input, full volume case.
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (it == transform_inputs_.begin()) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (volume == 1.0f) {
209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        if (temp_dest != provide_input_dest)
210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch          provide_input_dest->CopyTo(temp_dest);
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (volume > 0) {
212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        for (int i = 0; i < provide_input_dest->channels(); ++i) {
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          vector_math::FMUL(
214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              provide_input_dest->channel(i), volume,
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch              provide_input_dest->frames(), temp_dest->channel(i));
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        }
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        temp_dest->Zero();
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Volume adjust and mix each mixer input into |temp_dest| after rendering.
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (volume > 0) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        vector_math::FMAC(
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mixer_input_audio_bus_->channel(i), volume,
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            mixer_input_audio_bus_->frames(), temp_dest->channel(i));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (needs_downmix) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(temp_dest->frames(), dest->frames());
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    channel_mixer_->Transform(temp_dest, dest);
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AudioConverter::ProvideInput(int resampler_frame_delay, AudioBus* dest) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  resampler_frame_delay_ = resampler_frame_delay;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (audio_fifo_)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    audio_fifo_->Consume(dest, dest->frames());
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SourceCallback(0, dest);
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void AudioConverter::CreateUnmixedAudioIfNecessary(int frames) {
25023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!unmixed_audio_ || unmixed_audio_->frames() != frames)
25123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    unmixed_audio_ = AudioBus::Create(input_channel_count_, frames);
25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace media
255