• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // AudioConverter is a complete mixing, resampling, buffering, and channel
6 // mixing solution for converting data from one set of AudioParameters to
7 // another.
8 //
9 // For efficiency, pieces are only invoked when necessary; i.e.,
10 //    - The resampler is only used if sample rates differ.
11 //    - The FIFO is only used if buffer sizes differ.
12 //    - The channel mixer is only used if channel layouts differ.
13 //
14 // Additionally, since resampling is the most expensive operation, input mixing
15 // and channel down mixing are done prior to resampling.  Likewise, channel up
16 // mixing is performed after resampling.
17 
18 #ifndef MEDIA_BASE_AUDIO_CONVERTER_H_
19 #define MEDIA_BASE_AUDIO_CONVERTER_H_
20 
21 #include <list>
22 
23 #include "base/callback.h"
24 #include "base/memory/scoped_ptr.h"
25 #include "base/time/time.h"
26 #include "media/audio/audio_parameters.h"
27 #include "media/base/media_export.h"
28 
29 namespace media {
30 
31 class AudioBus;
32 class AudioPullFifo;
33 class ChannelMixer;
34 class MultiChannelResampler;
35 
36 // Converts audio data between two AudioParameters formats.  Sample usage:
37 //   AudioParameters input(...), output(...);
38 //   AudioConverter ac(input, output);
39 //   scoped_ptr<AudioBus> output_audio_bus = AudioBus::Create(output);
40 //   ac.AddInput(<AudioConverter::InputCallback* 1>);
41 //   ac.AddInput(<AudioConverter::InputCallback* 2>);
42 //   ac.Convert(output_audio_bus.get());
43 //
44 // Convert() will ask for input audio data from each InputCallback and convert
45 // the data into the provided AudioBus.
46 class MEDIA_EXPORT AudioConverter {
47  public:
48   // Interface for inputs into the converter.  Each InputCallback is added or
49   // removed from Convert() processing via AddInput() and RemoveInput().
50   class MEDIA_EXPORT InputCallback {
51    public:
52     // Method for providing more data into the converter.  Expects |audio_bus|
53     // to be completely filled with data upon return; zero padded if not enough
54     // frames are available to satisfy the request.  The return value is the
55     // volume level of the provided audio data.  If a volume level of zero is
56     // returned no further processing will be done on the provided data, else
57     // the volume level will be used to scale the provided audio data.
58     virtual double ProvideInput(AudioBus* audio_bus,
59                                 base::TimeDelta buffer_delay) = 0;
60 
61    protected:
~InputCallback()62     virtual ~InputCallback() {}
63   };
64 
65   // Constructs an AudioConverter for converting between the given input and
66   // output parameters.  Specifying |disable_fifo| means all InputCallbacks are
67   // capable of handling arbitrary buffer size requests; i.e. one call might ask
68   // for 10 frames of data (indicated by the size of AudioBus provided) and the
69   // next might ask for 20.  In synthetic testing, disabling the FIFO yields a
70   // ~20% speed up for common cases.
71   AudioConverter(const AudioParameters& input_params,
72                  const AudioParameters& output_params,
73                  bool disable_fifo);
74   ~AudioConverter();
75 
76   // Converts audio from all inputs into the |dest|. If an |initial_delay| is
77   // specified, it will be propagated to each input.
78   void Convert(AudioBus* dest);
79   void ConvertWithDelay(const base::TimeDelta& initial_delay, AudioBus* dest);
80 
81   // Adds or removes an input from the converter.  RemoveInput() will call
82   // Reset() if no inputs remain after the specified input is removed.
83   void AddInput(InputCallback* input);
84   void RemoveInput(InputCallback* input);
85 
86   // Flushes all buffered data.
87   void Reset();
88 
89   // The maximum size in frames that guarantees we will only make a single call
90   // to each input's ProvideInput for more data.
91   int ChunkSize() const;
92 
empty()93   bool empty() const { return transform_inputs_.empty(); }
94 
95  private:
96   // Provides input to the MultiChannelResampler.  Called by the resampler when
97   // more data is necessary.
98   void ProvideInput(int resampler_frame_delay, AudioBus* audio_bus);
99 
100   // Provides input to the AudioPullFifo.  Called by the fifo when more data is
101   // necessary.
102   void SourceCallback(int fifo_frame_delay, AudioBus* audio_bus);
103 
104   // (Re)creates the temporary |unmixed_audio_| buffer if necessary.
105   void CreateUnmixedAudioIfNecessary(int frames);
106 
107   // Set of inputs for Convert().
108   typedef std::list<InputCallback*> InputCallbackSet;
109   InputCallbackSet transform_inputs_;
110 
111   // Used to buffer data between the client and the output device in cases where
112   // the client buffer size is not the same as the output device buffer size.
113   scoped_ptr<AudioPullFifo> audio_fifo_;
114   int chunk_size_;
115 
116   // Handles resampling.
117   scoped_ptr<MultiChannelResampler> resampler_;
118 
119   // Handles channel transforms.  |unmixed_audio_| is a temporary destination
120   // for audio data before it goes into the channel mixer.
121   scoped_ptr<ChannelMixer> channel_mixer_;
122   scoped_ptr<AudioBus> unmixed_audio_;
123 
124   // Temporary AudioBus destination for mixing inputs.
125   scoped_ptr<AudioBus> mixer_input_audio_bus_;
126 
127   // Since resampling is expensive, figure out if we should downmix channels
128   // before resampling.
129   bool downmix_early_;
130 
131   // Used to calculate buffer delay information for InputCallbacks.
132   base::TimeDelta input_frame_duration_;
133   base::TimeDelta output_frame_duration_;
134   base::TimeDelta initial_delay_;
135   int resampler_frame_delay_;
136 
137   // Number of channels of input audio data.  Set during construction via the
138   // value from the input AudioParameters class.  Preserved to recreate internal
139   // AudioBus structures on demand in response to varying frame size requests.
140   const int input_channel_count_;
141 
142   DISALLOW_COPY_AND_ASSIGN(AudioConverter);
143 };
144 
145 }  // namespace media
146 
147 #endif  // MEDIA_BASE_AUDIO_CONVERTER_H_
148