| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // AudioConverter is a complete mixing, resampling, buffering, and channel |
| // mixing solution for converting data from one set of AudioParameters to |
| // another. |
| // |
| // For efficiency, pieces are only invoked when necessary; i.e., |
| // - The resampler is only used if sample rates differ. |
| // - The FIFO is only used if buffer sizes differ. |
| // - The channel mixer is only used if channel layouts differ. |
| // |
| // Additionally, since resampling is the most expensive operation, input mixing |
| // and channel down mixing are done prior to resampling. Likewise, channel up |
| // mixing is performed after resampling. |
| |
| #ifndef MEDIA_BASE_AUDIO_CONVERTER_H_ |
| #define MEDIA_BASE_AUDIO_CONVERTER_H_ |
| |
| #include <list> |
| #include <memory> |
| |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "media/base/audio_parameters.h" |
| #include "media/base/media_export.h" |
| |
| namespace media { |
| |
| class AudioBus; |
| class AudioPullFifo; |
| class ChannelMixer; |
| class MultiChannelResampler; |
| |
| // Converts audio data between two AudioParameters formats. Sample usage: |
| // AudioParameters input(...), output(...); |
| // AudioConverter ac(input, output); |
| // std::unique_ptr<AudioBus> output_audio_bus = AudioBus::Create(output); |
| // ac.AddInput(<AudioConverter::InputCallback* 1>); |
| // ac.AddInput(<AudioConverter::InputCallback* 2>); |
| // ac.Convert(output_audio_bus.get()); |
| // |
| // Convert() will ask for input audio data from each InputCallback and convert |
| // the data into the provided AudioBus. |
| class MEDIA_EXPORT AudioConverter { |
| public: |
| // Interface for inputs into the converter. Each InputCallback is added or |
| // removed from Convert() processing via AddInput() and RemoveInput(). |
| class MEDIA_EXPORT InputCallback { |
| public: |
| // Method for providing more data into the converter. Expects |audio_bus| |
| // to be completely filled with data upon return; zero padded if not enough |
| // frames are available to satisfy the request. The return value is the |
| // volume level of the provided audio data. If a volume level of zero is |
| // returned no further processing will be done on the provided data, else |
| // the volume level will be used to scale the provided audio data. |
| // |frames_delayed| is given in terms of the input sample rate. |
| virtual double ProvideInput(AudioBus* audio_bus, |
| uint32_t frames_delayed) = 0; |
| |
| protected: |
| virtual ~InputCallback() {} |
| }; |
| |
| // Constructs an AudioConverter for converting between the given input and |
| // output parameters. Specifying |disable_fifo| means all InputCallbacks are |
| // capable of handling arbitrary buffer size requests; i.e. one call might ask |
| // for 10 frames of data (indicated by the size of AudioBus provided) and the |
| // next might ask for 20. In synthetic testing, disabling the FIFO yields a |
| // ~20% speed up for common cases. |
| AudioConverter(const AudioParameters& input_params, |
| const AudioParameters& output_params, |
| bool disable_fifo); |
| ~AudioConverter(); |
| |
| // Converts audio from all inputs into the |dest|. If |frames_delayed| is |
| // specified, it will be propagated to each input. Count of frames must be |
| // given in terms of the output sample rate. |
| void Convert(AudioBus* dest); |
| void ConvertWithDelay(uint32_t frames_delayed, AudioBus* dest); |
| |
| // Adds or removes an input from the converter. RemoveInput() will call |
| // Reset() if no inputs remain after the specified input is removed. |
| void AddInput(InputCallback* input); |
| void RemoveInput(InputCallback* input); |
| |
| // Flushes all buffered data. |
| void Reset(); |
| |
| // The maximum size in frames that guarantees we will only make a single call |
| // to each input's ProvideInput for more data. |
| int ChunkSize() const; |
| |
| // See SincResampler::PrimeWithSilence. |
| void PrimeWithSilence(); |
| |
| // Maximum number of frames requested via InputCallback::ProvideInput, when |
| // trying to convert |output_frames_requested| at a time. |
| // Returns |output_frames_requested| when we are not resampling, and a |
| // multiple of the request size when we are. |
| int GetMaxInputFramesRequested(int output_frames_requested); |
| |
| bool empty() const { return transform_inputs_.empty(); } |
| |
| private: |
| // Provides input to the MultiChannelResampler. Called by the resampler when |
| // more data is necessary. |
| void ProvideInput(int resampler_frame_delay, AudioBus* audio_bus); |
| |
| // Provides input to the AudioPullFifo. Called by the fifo when more data is |
| // necessary. |
| void SourceCallback(int fifo_frame_delay, AudioBus* audio_bus); |
| |
| // (Re)creates the temporary |unmixed_audio_| buffer if necessary. |
| void CreateUnmixedAudioIfNecessary(int frames); |
| |
| // Set of inputs for Convert(). |
| typedef std::list<InputCallback*> InputCallbackSet; |
| InputCallbackSet transform_inputs_; |
| |
| // Used to buffer data between the client and the output device in cases where |
| // the client buffer size is not the same as the output device buffer size. |
| std::unique_ptr<AudioPullFifo> audio_fifo_; |
| int chunk_size_; |
| |
| // Handles resampling. |
| std::unique_ptr<MultiChannelResampler> resampler_; |
| |
| // Handles channel transforms. |unmixed_audio_| is a temporary destination |
| // for audio data before it goes into the channel mixer. |
| std::unique_ptr<ChannelMixer> channel_mixer_; |
| std::unique_ptr<AudioBus> unmixed_audio_; |
| |
| // Temporary AudioBus destination for mixing inputs. |
| std::unique_ptr<AudioBus> mixer_input_audio_bus_; |
| |
| // Since resampling is expensive, figure out if we should downmix channels |
| // before resampling. |
| bool downmix_early_; |
| |
| // Used to calculate buffer delay information for InputCallbacks. |
| uint32_t initial_frames_delayed_; |
| uint32_t resampler_frames_delayed_; |
| const double io_sample_rate_ratio_; |
| |
| // Number of channels of input audio data. Set during construction via the |
| // value from the input AudioParameters class. Preserved to recreate internal |
| // AudioBus structures on demand in response to varying frame size requests. |
| const int input_channel_count_; |
| |
| DISALLOW_COPY_AND_ASSIGN(AudioConverter); |
| }; |
| |
| } // namespace media |
| |
| #endif // MEDIA_BASE_AUDIO_CONVERTER_H_ |