Commit 96e28685 authored by ajm@chromium.org's avatar ajm@chromium.org

Use the AudioProcessing float interface in MediaStreamAudioProcessor.

Format conversions are now handled internally by AP, allowing us to
to tear out the conversion code from MSAP. Instead, we use a simple
FIFO to buffer the incoming audio into the 10 ms chunks AP requires.

Add an AudioBus wrapper to get an array of channel pointers, since this
is the type AP deals in.

Add a few TODOs around two suspect areas: i) there appears to be an
assumption on the sink type based on the input format, and ii) don't
we want ProcessAndConsumeData() to output float data?

BUG=400933
TESTED=Audio processing behaves as expected on a MacBook, using both
44.1 and 48 kHz as the render and capture rates (set through "Audio
Midi Setup"). Audio sounds fine when processing is disabled through
constraints.

Review URL: https://codereview.chromium.org/420603004

Cr-Commit-Position: refs/heads/master@{#289653}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289653 0039d316-1c4b-4281-b951-d872f2087c98
parent 9024b640
...@@ -35,6 +35,8 @@ class TypingDetection; ...@@ -35,6 +35,8 @@ class TypingDetection;
namespace content { namespace content {
class MediaStreamAudioBus;
class MediaStreamAudioFifo;
class RTCMediaConstraints; class RTCMediaConstraints;
using webrtc::AudioProcessorInterface; using webrtc::AudioProcessorInterface;
...@@ -59,30 +61,32 @@ class CONTENT_EXPORT MediaStreamAudioProcessor : ...@@ -59,30 +61,32 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
int effects, int effects,
WebRtcPlayoutDataSource* playout_data_source); WebRtcPlayoutDataSource* playout_data_source);
// Called when format of the capture data has changed. // Called when the format of the capture data has changed.
// Called on the main render thread. The caller is responsible for stopping // Called on the main render thread. The caller is responsible for stopping
// the capture thread before calling this method. // the capture thread before calling this method.
// After this method, the capture thread will be changed to a new capture // After this method, the capture thread will be changed to a new capture
// thread. // thread.
void OnCaptureFormatChanged(const media::AudioParameters& source_params); void OnCaptureFormatChanged(const media::AudioParameters& source_params);
// Pushes capture data in |audio_source| to the internal FIFO. // Pushes capture data in |audio_source| to the internal FIFO. Each call to
// this method should be followed by calls to ProcessAndConsumeData() while
// it returns false, to pull out all available data.
// Called on the capture audio thread. // Called on the capture audio thread.
void PushCaptureData(const media::AudioBus* audio_source); void PushCaptureData(const media::AudioBus* audio_source);
// Processes a block of 10 ms data from the internal FIFO and outputs it via // Processes a block of 10 ms data from the internal FIFO and outputs it via
// |out|. |out| is the address of the pointer that will be pointed to // |out|. |out| is the address of the pointer that will be pointed to
// the post-processed data if the method is returning a true. The lifetime // the post-processed data if the method is returning a true. The lifetime
// of the data represeted by |out| is guaranteed to outlive the method call. // of the data represeted by |out| is guaranteed until this method is called
// That also says *|out| won't change until this method is called again. // again.
// |new_volume| receives the new microphone volume from the AGC. // |new_volume| receives the new microphone volume from the AGC.
// The new microphoen volume range is [0, 255], and the value will be 0 if // The new microphone volume range is [0, 255], and the value will be 0 if
// the microphone volume should not be adjusted. // the microphone volume should not be adjusted.
// Returns true if the internal FIFO has at least 10 ms data for processing, // Returns true if the internal FIFO has at least 10 ms data for processing,
// otherwise false. // otherwise false.
// |capture_delay|, |volume| and |key_pressed| will be passed to
// webrtc::AudioProcessing to help processing the data.
// Called on the capture audio thread. // Called on the capture audio thread.
//
// TODO(ajm): Don't we want this to output float?
bool ProcessAndConsumeData(base::TimeDelta capture_delay, bool ProcessAndConsumeData(base::TimeDelta capture_delay,
int volume, int volume,
bool key_pressed, bool key_pressed,
...@@ -93,10 +97,9 @@ class CONTENT_EXPORT MediaStreamAudioProcessor : ...@@ -93,10 +97,9 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// this method. // this method.
void Stop(); void Stop();
// The audio format of the input to the processor. // The audio formats of the capture input to and output from the processor.
// Must only be called on the main render or audio capture threads.
const media::AudioParameters& InputFormat() const; const media::AudioParameters& InputFormat() const;
// The audio format of the output from the processor.
const media::AudioParameters& OutputFormat() const; const media::AudioParameters& OutputFormat() const;
// Accessor to check if the audio processing is enabled or not. // Accessor to check if the audio processing is enabled or not.
...@@ -118,8 +121,6 @@ class CONTENT_EXPORT MediaStreamAudioProcessor : ...@@ -118,8 +121,6 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
FRIEND_TEST_ALL_PREFIXES(MediaStreamAudioProcessorTest, FRIEND_TEST_ALL_PREFIXES(MediaStreamAudioProcessorTest,
GetAecDumpMessageFilter); GetAecDumpMessageFilter);
class MediaStreamAudioConverter;
// WebRtcPlayoutDataSource::Sink implementation. // WebRtcPlayoutDataSource::Sink implementation.
virtual void OnPlayoutData(media::AudioBus* audio_bus, virtual void OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate, int sample_rate,
...@@ -135,64 +136,63 @@ class CONTENT_EXPORT MediaStreamAudioProcessor : ...@@ -135,64 +136,63 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
const blink::WebMediaConstraints& constraints, int effects); const blink::WebMediaConstraints& constraints, int effects);
// Helper to initialize the capture converter. // Helper to initialize the capture converter.
void InitializeCaptureConverter(const media::AudioParameters& source_params); void InitializeCaptureFifo(const media::AudioParameters& input_format);
// Helper to initialize the render converter. // Helper to initialize the render converter.
void InitializeRenderConverterIfNeeded(int sample_rate, void InitializeRenderFifoIfNeeded(int sample_rate,
int number_of_channels, int number_of_channels,
int frames_per_buffer); int frames_per_buffer);
// Called by ProcessAndConsumeData(). // Called by ProcessAndConsumeData().
// Returns the new microphone volume in the range of |0, 255]. // Returns the new microphone volume in the range of |0, 255].
// When the volume does not need to be updated, it returns 0. // When the volume does not need to be updated, it returns 0.
int ProcessData(webrtc::AudioFrame* audio_frame, int ProcessData(const float* const* process_ptrs,
int process_frames,
base::TimeDelta capture_delay, base::TimeDelta capture_delay,
int volume, int volume,
bool key_pressed); bool key_pressed,
float* const* output_ptrs);
// Cached value for the render delay latency. This member is accessed by // Cached value for the render delay latency. This member is accessed by
// both the capture audio thread and the render audio thread. // both the capture audio thread and the render audio thread.
base::subtle::Atomic32 render_delay_ms_; base::subtle::Atomic32 render_delay_ms_;
// webrtc::AudioProcessing module which does AEC, AGC, NS, HighPass filter, // Module to handle processing and format conversion.
// ..etc.
scoped_ptr<webrtc::AudioProcessing> audio_processing_; scoped_ptr<webrtc::AudioProcessing> audio_processing_;
// Converter used for the down-mixing and resampling of the capture data. // FIFO to provide 10 ms capture chunks.
scoped_ptr<MediaStreamAudioConverter> capture_converter_; scoped_ptr<MediaStreamAudioFifo> capture_fifo_;
// Receives processing output.
// AudioFrame used to hold the output of |capture_converter_|. scoped_ptr<MediaStreamAudioBus> output_bus_;
webrtc::AudioFrame capture_frame_; // Receives interleaved int16 data for output.
scoped_ptr<int16[]> output_data_;
// Converter used for the down-mixing and resampling of the render data when
// the AEC is enabled.
scoped_ptr<MediaStreamAudioConverter> render_converter_;
// AudioFrame used to hold the output of |render_converter_|. // FIFO to provide 10 ms render chunks when the AEC is enabled.
webrtc::AudioFrame render_frame_; scoped_ptr<MediaStreamAudioFifo> render_fifo_;
// Data bus to help converting interleaved data to an AudioBus. // These are mutated on the main render thread in OnCaptureFormatChanged().
scoped_ptr<media::AudioBus> render_data_bus_; // The caller guarantees this does not run concurrently with accesses on the
// capture audio thread.
media::AudioParameters input_format_;
media::AudioParameters output_format_;
// Only used on the render audio thread.
media::AudioParameters render_format_;
// Raw pointer to the WebRtcPlayoutDataSource, which is valid for the // Raw pointer to the WebRtcPlayoutDataSource, which is valid for the
// lifetime of RenderThread. // lifetime of RenderThread.
WebRtcPlayoutDataSource* playout_data_source_; WebRtcPlayoutDataSource* playout_data_source_;
// Used to DCHECK that the destructor is called on the main render thread. // Used to DCHECK that some methods are called on the main render thread.
base::ThreadChecker main_thread_checker_; base::ThreadChecker main_thread_checker_;
// Used to DCHECK that some methods are called on the capture audio thread. // Used to DCHECK that some methods are called on the capture audio thread.
base::ThreadChecker capture_thread_checker_; base::ThreadChecker capture_thread_checker_;
// Used to DCHECK that some methods are called on the render audio thread.
// Used to DCHECK that PushRenderData() is called on the render audio thread.
base::ThreadChecker render_thread_checker_; base::ThreadChecker render_thread_checker_;
// Flag to enable the stereo channels mirroring. // Flag to enable stereo channel mirroring.
bool audio_mirroring_; bool audio_mirroring_;
// Used by the typing detection.
scoped_ptr<webrtc::TypingDetection> typing_detector_; scoped_ptr<webrtc::TypingDetection> typing_detector_;
// This flag is used to show the result of typing detection. // This flag is used to show the result of typing detection.
// It can be accessed by the capture audio thread and by the libjingle thread // It can be accessed by the capture audio thread and by the libjingle thread
// which calls GetStats(). // which calls GetStats().
......
...@@ -130,7 +130,8 @@ class WebRtcAudioCapturerTest : public testing::Test { ...@@ -130,7 +130,8 @@ class WebRtcAudioCapturerTest : public testing::Test {
EXPECT_CALL(*sink, FormatIsSet()); EXPECT_CALL(*sink, FormatIsSet());
EXPECT_CALL(*sink, EXPECT_CALL(*sink,
OnDataCallback(_, _, delay_ms, expected_volume_value, OnDataCallback(_, _, delay_ms, expected_volume_value,
need_audio_processing, key_pressed)); need_audio_processing, key_pressed))
.Times(AtLeast(1));
callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed); callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
// Verify the cached values in the capturer fits what we expect. // Verify the cached values in the capturer fits what we expect.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment