audio_converter.h revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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