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 is a complete mixing, resampling, buffering, and channel
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// mixing solution for converting data from one set of AudioParameters to
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// another.
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// For efficiency, pieces are only invoked when necessary; i.e.,
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    - The resampler is only used if sample rates differ.
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    - The FIFO is only used if buffer sizes differ.
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//    - The channel mixer is only used if channel layouts differ.
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Additionally, since resampling is the most expensive operation, input mixing
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// and channel down mixing are done prior to resampling.  Likewise, channel up
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// mixing is performed after resampling.
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef MEDIA_BASE_AUDIO_CONVERTER_H_
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define MEDIA_BASE_AUDIO_CONVERTER_H_
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list>
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/media_export.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace media {
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AudioBus;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class AudioPullFifo;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ChannelMixer;
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MultiChannelResampler;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts audio data between two AudioParameters formats.  Sample usage:
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   AudioParameters input(...), output(...);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   AudioConverter ac(input, output);
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   scoped_ptr<AudioBus> output_audio_bus = AudioBus::Create(output);
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   ac.AddInput(<AudioConverter::InputCallback* 1>);
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   ac.AddInput(<AudioConverter::InputCallback* 2>);
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//   ac.Convert(output_audio_bus.get());
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Convert() will ask for input audio data from each InputCallback and convert
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// the data into the provided AudioBus.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class MEDIA_EXPORT AudioConverter {
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Interface for inputs into the converter.  Each InputCallback is added or
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // removed from Convert() processing via AddInput() and RemoveInput().
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  class MEDIA_EXPORT InputCallback {
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   public:
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Method for providing more data into the converter.  Expects |audio_bus|
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to be completely filled with data upon return; zero padded if not enough
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // frames are available to satisfy the request.  The return value is the
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // volume level of the provided audio data.  If a volume level of zero is
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // returned no further processing will be done on the provided data, else
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the volume level will be used to scale the provided audio data.
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual double ProvideInput(AudioBus* audio_bus,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                base::TimeDelta buffer_delay) = 0;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)   protected:
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    virtual ~InputCallback() {}
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Constructs an AudioConverter for converting between the given input and
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // output parameters.  Specifying |disable_fifo| means all InputCallbacks are
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // capable of handling arbitrary buffer size requests; i.e. one call might ask
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for 10 frames of data (indicated by the size of AudioBus provided) and the
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // next might ask for 20.  In synthetic testing, disabling the FIFO yields a
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ~20% speed up for common cases.
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AudioConverter(const AudioParameters& input_params,
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 const AudioParameters& output_params,
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 bool disable_fifo);
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~AudioConverter();
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Converts audio from all inputs into the |dest|. If an |initial_delay| is
7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // specified, it will be propagated to each input.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Convert(AudioBus* dest);
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ConvertWithDelay(const base::TimeDelta& initial_delay, AudioBus* dest);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Adds or removes an input from the converter.  RemoveInput() will call
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Reset() if no inputs remain after the specified input is removed.
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AddInput(InputCallback* input);
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RemoveInput(InputCallback* input);
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Flushes all buffered data.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Reset();
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // The maximum size in frames that guarantees we will only make a single call
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // to each input's ProvideInput for more data.
9123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int ChunkSize() const;
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool empty() const { return transform_inputs_.empty(); }
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Provides input to the MultiChannelResampler.  Called by the resampler when
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // more data is necessary.
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ProvideInput(int resampler_frame_delay, AudioBus* audio_bus);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Provides input to the AudioPullFifo.  Called by the fifo when more data is
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // necessary.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SourceCallback(int fifo_frame_delay, AudioBus* audio_bus);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // (Re)creates the temporary |unmixed_audio_| buffer if necessary.
10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  void CreateUnmixedAudioIfNecessary(int frames);
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set of inputs for Convert().
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::list<InputCallback*> InputCallbackSet;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  InputCallbackSet transform_inputs_;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used to buffer data between the client and the output device in cases where
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the client buffer size is not the same as the output device buffer size.
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioPullFifo> audio_fifo_;
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  int chunk_size_;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handles resampling.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<MultiChannelResampler> resampler_;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handles channel transforms.  |unmixed_audio_| is a temporary destination
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // for audio data before it goes into the channel mixer.
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ChannelMixer> channel_mixer_;
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioBus> unmixed_audio_;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Temporary AudioBus destination for mixing inputs.
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<AudioBus> mixer_input_audio_bus_;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Since resampling is expensive, figure out if we should downmix channels
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // before resampling.
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool downmix_early_;
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used to calculate buffer delay information for InputCallbacks.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta input_frame_duration_;
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta output_frame_duration_;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::TimeDelta initial_delay_;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int resampler_frame_delay_;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Number of channels of input audio data.  Set during construction via the
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // value from the input AudioParameters class.  Preserved to recreate internal
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // AudioBus structures on demand in response to varying frame size requests.
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int input_channel_count_;
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AudioConverter);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace media
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif  // MEDIA_BASE_AUDIO_CONVERTER_H_
148