audio_converter.h revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioConverter is a complete mixing, resampling, buffering, and channel 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// mixing solution for converting data from one set of AudioParameters to 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// another. 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// For efficiency, pieces are only invoked when necessary; i.e., 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// - The resampler is only used if sample rates differ. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The FIFO is only used if buffer sizes differ. 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - The channel mixer is only used if channel layouts differ. 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Additionally, since resampling is the most expensive operation, input mixing 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and channel down mixing are done prior to resampling. Likewise, channel up 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// mixing is performed after resampling. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_BASE_AUDIO_CONVERTER_H_ 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_BASE_AUDIO_CONVERTER_H_ 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <list> 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/time/time.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/audio/audio_parameters.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/media_export.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioBus; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AudioPullFifo; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ChannelMixer; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MultiChannelResampler; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Converts audio data between two AudioParameters formats. Sample usage: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioParameters input(...), output(...); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AudioConverter ac(input, output); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// scoped_ptr<AudioBus> output_audio_bus = AudioBus::Create(output); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ac.AddInput(<AudioConverter::InputCallback* 1>); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ac.AddInput(<AudioConverter::InputCallback* 2>); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ac.Convert(output_audio_bus.get()); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Convert() will ask for input audio data from each InputCallback and convert 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the data into the provided AudioBus. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MEDIA_EXPORT AudioConverter { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Interface for inputs into the converter. Each InputCallback is added or 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta buffer_delay) = 0; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~InputCallback() {} 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Converts audio from all inputs into the |dest|. If an |initial_delay| is 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // specified, it will be propagated to each input. 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void Convert(AudioBus* dest); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void ConvertWithDelay(const base::TimeDelta& initial_delay, AudioBus* dest); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Adds or removes an input from the converter. RemoveInput() will call 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Flushes all buffered data. 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset(); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The maximum size in frames that guarantees we will only make a single call 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to each input's ProvideInput for more data. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ChunkSize() const; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Provides input to the MultiChannelResampler. Called by the resampler when 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // more data is necessary. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ProvideInput(int resampler_frame_delay, AudioBus* audio_bus); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Provides input to the AudioPullFifo. Called by the fifo when more data is 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // necessary. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SourceCallback(int fifo_frame_delay, AudioBus* audio_bus); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (Re)creates the temporary |unmixed_audio_| buffer if necessary. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateUnmixedAudioIfNecessary(int frames); 104 105 // Set of inputs for Convert(). 106 typedef std::list<InputCallback*> InputCallbackSet; 107 InputCallbackSet transform_inputs_; 108 109 // Used to buffer data between the client and the output device in cases where 110 // the client buffer size is not the same as the output device buffer size. 111 scoped_ptr<AudioPullFifo> audio_fifo_; 112 int chunk_size_; 113 114 // Handles resampling. 115 scoped_ptr<MultiChannelResampler> resampler_; 116 117 // Handles channel transforms. |unmixed_audio_| is a temporary destination 118 // for audio data before it goes into the channel mixer. 119 scoped_ptr<ChannelMixer> channel_mixer_; 120 scoped_ptr<AudioBus> unmixed_audio_; 121 122 // Temporary AudioBus destination for mixing inputs. 123 scoped_ptr<AudioBus> mixer_input_audio_bus_; 124 125 // Since resampling is expensive, figure out if we should downmix channels 126 // before resampling. 127 bool downmix_early_; 128 129 // Used to calculate buffer delay information for InputCallbacks. 130 base::TimeDelta input_frame_duration_; 131 base::TimeDelta output_frame_duration_; 132 base::TimeDelta initial_delay_; 133 int resampler_frame_delay_; 134 135 // Number of channels of input audio data. Set during construction via the 136 // value from the input AudioParameters class. Preserved to recreate internal 137 // AudioBus structures on demand in response to varying frame size requests. 138 const int input_channel_count_; 139 140 DISALLOW_COPY_AND_ASSIGN(AudioConverter); 141}; 142 143} // namespace media 144 145#endif // MEDIA_BASE_AUDIO_CONVERTER_H_ 146