Chromium Code Reviews| Index: webrtc/modules/audio_processing/include/audio_processing.h | 
| diff --git a/webrtc/modules/audio_processing/include/audio_processing.h b/webrtc/modules/audio_processing/include/audio_processing.h | 
| index 6fa1c96c0771c14d141836dc0c88bf69ec9f5aea..849aa251959f90f322d3bca7d85b05de1dd4b59d 100644 | 
| --- a/webrtc/modules/audio_processing/include/audio_processing.h | 
| +++ b/webrtc/modules/audio_processing/include/audio_processing.h | 
| @@ -29,6 +29,9 @@ class AudioFrame; | 
| template<typename T> | 
| class Beamformer; | 
| +class StreamConfig; | 
| +class ProcessingConfig; | 
| + | 
| class EchoCancellation; | 
| class EchoControlMobile; | 
| class GainControl; | 
| @@ -84,7 +87,7 @@ static const int kAgcStartupMinVolume = 0; | 
| #endif // defined(WEBRTC_CHROMIUM_BUILD) | 
| struct ExperimentalAgc { | 
| ExperimentalAgc() : enabled(true), startup_min_volume(kAgcStartupMinVolume) {} | 
| - ExperimentalAgc(bool enabled) | 
| + explicit ExperimentalAgc(bool enabled) | 
| : enabled(enabled), startup_min_volume(kAgcStartupMinVolume) {} | 
| ExperimentalAgc(bool enabled, int startup_min_volume) | 
| : enabled(enabled), startup_min_volume(startup_min_volume) {} | 
| @@ -236,10 +239,15 @@ class AudioProcessing { | 
| // The int16 interfaces require: | 
| // - only |NativeRate|s be used | 
| // - that the input, output and reverse rates must match | 
| - // - that |output_layout| matches |input_layout| | 
| + // - that |processing_config.output_stream()| matches | 
| + // |processing_config.input_stream()|. | 
| // | 
| - // The float interfaces accept arbitrary rates and support differing input | 
| - // and output layouts, but the output may only remove channels, not add. | 
| + // The float interfaces accept arbitrary rates and support differing input and | 
| + // output layouts, but the output must have either one channel or the same | 
| + // number of channels as the input. | 
| + virtual int Initialize(const ProcessingConfig& processing_config) = 0; | 
| + | 
| + // Initialize with unpacked parameters. See Initialize() above for details. | 
| virtual int Initialize(int input_sample_rate_hz, | 
| int output_sample_rate_hz, | 
| int reverse_sample_rate_hz, | 
| @@ -292,8 +300,8 @@ class AudioProcessing { | 
| // |input_layout|. At output, the channels will be arranged according to | 
| // |output_layout| at |output_sample_rate_hz| in |dest|. | 
| // | 
| - // The output layout may only remove channels, not add. |src| and |dest| | 
| - // may use the same memory, if desired. | 
| + // The output layout must have one channel or as many channels as the input. | 
| + // |src| and |dest| may use the same memory, if desired. | 
| virtual int ProcessStream(const float* const* src, | 
| 
 
ajm
2015/07/15 05:21:20
Can you add a TODO here and on the deprecated Anal
 
mgraczyk
2015/07/15 20:03:20
Done.
 
 | 
| int samples_per_channel, | 
| int input_sample_rate_hz, | 
| @@ -302,6 +310,17 @@ class AudioProcessing { | 
| ChannelLayout output_layout, | 
| float* const* dest) = 0; | 
| + // Accepts deinterleaved float audio with the range [-1, 1]. Each element of | 
| + // |src| points to a channel buffer, arranged according to | 
| + // |processing_config.input_stream()|. At output, the channels will be | 
| + // arranged according to |processing_config.output_stream()| in |dest|. | 
| + // | 
| + // The output must have one channel or as many channels as the input. |src| | 
| + // and |dest| may use the same memory, if desired. | 
| + virtual int ProcessStream(const float* const* src, | 
| + const ProcessingConfig& processing_config, | 
| + float* const* dest) = 0; | 
| + | 
| // Analyzes a 10 ms |frame| of the reverse direction audio stream. The frame | 
| // will not be modified. On the client-side, this is the far-end (or to be | 
| // rendered) audio. | 
| @@ -326,6 +345,11 @@ class AudioProcessing { | 
| int sample_rate_hz, | 
| ChannelLayout layout) = 0; | 
| + // Accepts deinterleaved float audio with the range [-1, 1]. Each element of | 
| + // |data| points to a channel buffer, arranged according to |reverse_config|. | 
| + virtual int AnalyzeReverseStream(const float* const* data, | 
| + const StreamConfig& reverse_config) = 0; | 
| + | 
| // This must be called if and only if echo processing is enabled. | 
| // | 
| // Sets the |delay| in ms between AnalyzeReverseStream() receiving a far-end | 
| @@ -432,6 +456,92 @@ class AudioProcessing { | 
| static const int kChunkSizeMs = 10; | 
| }; | 
| +class StreamConfig { | 
| + public: | 
| + StreamConfig(int sample_rate_hz = 0, | 
| + int num_channels = 0, | 
| + bool has_keyboard = false) | 
| + : sample_rate_hz_(sample_rate_hz), | 
| + num_channels_(num_channels), | 
| + has_keyboard_(has_keyboard), | 
| + samples_per_channel_(calculate_samples_per_channel(sample_rate_hz)) {} | 
| 
 
ajm
2015/07/15 05:21:20
Alex, Michael: I know it breaks convention in this
 
aluebs-webrtc
2015/07/15 16:42:17
It is unfortunate that we used "frames" to refer t
 
mgraczyk
2015/07/15 20:03:20
Done, although I think there are plenty of better
 
 | 
| + | 
| + void set_sample_rate_hz(int value) { | 
| + sample_rate_hz_ = value; | 
| + samples_per_channel_ = calculate_samples_per_channel(value); | 
| + } | 
| + void set_num_channels(int value) { num_channels_ = value; } | 
| + void set_has_keyboard(bool value) { has_keyboard_ = value; } | 
| + | 
| + int sample_rate_hz() const { return sample_rate_hz_; } | 
| + int num_channels() const { return num_channels_; } | 
| + bool has_keyboard() const { return has_keyboard_; } | 
| + int samples_per_channel() const { return samples_per_channel_; } | 
| + | 
| + bool operator==(const StreamConfig& other) const { | 
| + return sample_rate_hz_ == other.sample_rate_hz_ && | 
| + num_channels_ == other.num_channels_ && | 
| + has_keyboard_ == other.has_keyboard_; | 
| + } | 
| + | 
| + bool operator!=(const StreamConfig& other) const { return !(*this == other); } | 
| + | 
| + private: | 
| + static int calculate_samples_per_channel(int sample_rate_hz) { | 
| + return AudioProcessing::kChunkSizeMs * sample_rate_hz / 1000; | 
| + } | 
| + | 
| + int sample_rate_hz_; | 
| + int num_channels_; | 
| + bool has_keyboard_; | 
| + int samples_per_channel_; | 
| +}; | 
| + | 
| +class ProcessingConfig { | 
| + public: | 
| + enum StreamName { | 
| + kInputStream, | 
| + kOutputStream, | 
| + kReverseStream, | 
| + kNumStreamNames, | 
| + }; | 
| + | 
| + const StreamConfig& input_stream() const { | 
| + return streams[StreamName::kInputStream]; | 
| + } | 
| + const StreamConfig& output_stream() const { | 
| + return streams[StreamName::kOutputStream]; | 
| + } | 
| + const StreamConfig& reverse_stream() const { | 
| + return streams[StreamName::kReverseStream]; | 
| + } | 
| + | 
| + StreamConfig& input_stream() { | 
| + return streams[StreamName::kInputStream]; | 
| + } | 
| + StreamConfig& output_stream() { | 
| + return streams[StreamName::kOutputStream]; | 
| + } | 
| + StreamConfig& reverse_stream() { | 
| + return streams[StreamName::kReverseStream]; | 
| + } | 
| + | 
| + bool operator==(const ProcessingConfig& other) const { | 
| + for (int i = 0; i < StreamName::kNumStreamNames; ++i) { | 
| + if (this->streams[i] != other.streams[i]) { | 
| + return false; | 
| + } | 
| + } | 
| + return true; | 
| + } | 
| + | 
| + bool operator!=(const ProcessingConfig& other) const { | 
| + return !(*this == other); | 
| + } | 
| + | 
| + StreamConfig streams[StreamName::kNumStreamNames]; | 
| +}; | 
| + | 
| // The acoustic echo cancellation (AEC) component provides better performance | 
| // than AECM but also requires more processing power and is dependent on delay | 
| // stability and reporting accuracy. As such it is well-suited and recommended |