diff options
author | henrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-28 11:51:42 +0000 |
---|---|---|
committer | henrika@chromium.org <henrika@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-28 11:51:42 +0000 |
commit | affb228b3addc94ecb7a049fbd93412d7390f4b4 (patch) | |
tree | ed1468cd2525a9cfec0dd5befb8e6922bdc3b1e6 /media/audio | |
parent | a26740dd0887ed17898c965ad42e789a9525a9df (diff) | |
download | chromium_src-affb228b3addc94ecb7a049fbd93412d7390f4b4.zip chromium_src-affb228b3addc94ecb7a049fbd93412d7390f4b4.tar.gz chromium_src-affb228b3addc94ecb7a049fbd93412d7390f4b4.tar.bz2 |
Improved AGC update scheme for the audio backend in Chrome.
This CL serves two purposes:
1) Improve the existing "mic-volume-checking"-scheme by ensuring that we no longer calls native audio functions from the core capture thread.
2) Prepare for adding AGC to the live-audio backend.
TBR=tommi@chromium.org
BUG=none
TEST=WebRTC loopback tests in Chrome where I monitor the microphone volume while speaking into the mic.
Review URL: https://codereview.chromium.org/15563004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202538 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/audio')
-rw-r--r-- | media/audio/agc_audio_stream.h | 205 | ||||
-rw-r--r-- | media/audio/audio_input_stream_impl.cc | 71 | ||||
-rw-r--r-- | media/audio/audio_input_stream_impl.h | 71 | ||||
-rw-r--r-- | media/audio/cras/cras_input.cc | 6 | ||||
-rw-r--r-- | media/audio/cras/cras_input.h | 4 | ||||
-rw-r--r-- | media/audio/linux/alsa_input.cc | 5 | ||||
-rw-r--r-- | media/audio/linux/alsa_input.h | 4 | ||||
-rw-r--r-- | media/audio/mac/audio_low_latency_input_mac.cc | 10 | ||||
-rw-r--r-- | media/audio/mac/audio_low_latency_input_mac.h | 4 | ||||
-rw-r--r-- | media/audio/pulse/pulse_input.cc | 9 | ||||
-rw-r--r-- | media/audio/pulse/pulse_input.h | 4 | ||||
-rw-r--r-- | media/audio/win/audio_low_latency_input_win.cc | 15 | ||||
-rw-r--r-- | media/audio/win/audio_low_latency_input_win.h | 4 |
13 files changed, 247 insertions, 165 deletions
diff --git a/media/audio/agc_audio_stream.h b/media/audio/agc_audio_stream.h new file mode 100644 index 0000000..ebf0da6 --- /dev/null +++ b/media/audio/agc_audio_stream.h @@ -0,0 +1,205 @@ +// 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. + +#ifndef MEDIA_AUDIO_AGC_AUDIO_STREAM_H_ +#define MEDIA_AUDIO_AGC_AUDIO_STREAM_H_ + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" +#include "base/timer.h" +#include "media/audio/audio_io.h" + +// The template based AgcAudioStream implements platform-independent parts +// of the AudioInterface interface. Supported interfaces to pass as +// AudioInterface are AudioIntputStream and AudioOutputStream. Each platform- +// dependent implementation should derive from this class. +// +// Usage example (on Windows): +// +// class WASAPIAudioInputStream : public AgcAudioStream<AudioInputStream> { +// public: +// WASAPIAudioInputStream(); +// ... +// }; +// +// Call flow example: +// +// 1) User creates AgcAudioStream<AudioInputStream> +// 2) User calls AudioInputStream::SetAutomaticGainControl(true) => +// AGC usage is now initialized but not yet started. +// 3) User calls AudioInputStream::Start() => implementation calls +// AgcAudioStream<AudioInputStream>::StartAgc() which detects that AGC +// is enabled and then starts the periodic AGC timer. +// 4) Microphone volume samples are now taken and included in all +// AudioInputCallback::OnData() callbacks. +// 5) User calls AudioInputStream::Stop() => implementation calls +// AgcAudioStream<AudioInputStream>::StopAgc() which stops the timer. +// +// Note that, calling AudioInputStream::SetAutomaticGainControl(false) while +// AGC measurements are active will not have an effect until StopAgc(), +// StartAgc() are called again since SetAutomaticGainControl() only sets a +// a state. +// +// Calling SetAutomaticGainControl(true) enables the AGC and StartAgc() starts +// a periodic timer which calls OnTimer() approximately once every second. +// OnTimer() calls the QueryAndStoreNewMicrophoneVolume() method which asks +// the actual microphone about its current volume level. This value is +// normalized and stored so it can be read by GetAgcVolume() when the real-time +// audio thread needs the value. The main idea behind this scheme is to avoid +// accessing the audio hardware from the real-time audio thread and to ensure +// that we don't take new microphone-level samples too often (~1 Hz is a +// suitable compromise). The timer will be active until StopAgc() is called. +// +// This class should be created and destroyed on the audio manager thread and +// a thread checker is added to ensure that this is the case (uses DCHECK). +// All methods except GetAgcVolume() should be called on the creating thread +// as well to ensure that thread safety is maintained. It will also guarantee +// that the periodic timer runs on the audio manager thread. +// |normalized_volume_|, which is updated by QueryAndStoreNewMicrophoneVolume() +// and read in GetAgcVolume(), is protected by a lock to ensure that it can +// be accessed from any real-time audio thread that needs it to update the its +// AGC volume. + +namespace media { + +template <typename AudioInterface> +class MEDIA_EXPORT AgcAudioStream : public AudioInterface { + public: + // Time between two successive timer events. + static const int kIntervalBetweenVolumeUpdatesMs = 1000; + + AgcAudioStream() + : agc_is_enabled_(false), max_volume_(0.0), normalized_volume_(0.0) { + DVLOG(1) << __FUNCTION__; + } + + virtual ~AgcAudioStream() { + DCHECK(thread_checker_.CalledOnValidThread()); + DVLOG(1) << __FUNCTION__; + } + + protected: + // Starts the periodic timer which periodically checks and updates the + // current microphone volume level. + // The timer is only started if AGC mode is first enabled using the + // SetAutomaticGainControl() method. + void StartAgc() { + DVLOG(1) << "StartAgc()"; + DCHECK(thread_checker_.CalledOnValidThread()); + if (!agc_is_enabled_ || timer_.IsRunning()) + return; + timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(kIntervalBetweenVolumeUpdatesMs), + this, &AgcAudioStream::OnTimer); + } + + // Stops the periodic timer which periodically checks and updates the + // current microphone volume level. + void StopAgc() { + DVLOG(1) << "StopAgc()"; + DCHECK(thread_checker_.CalledOnValidThread()); + if (timer_.IsRunning()) + timer_.Stop(); + } + + // Stores a new microphone volume level by checking the audio input device. + // Called on the audio manager thread. + void UpdateAgcVolume() { + DCHECK(thread_checker_.CalledOnValidThread()); + + // We take new volume samples once every second when the AGC is enabled. + // To ensure that a new setting has an immediate effect, the new volume + // setting is cached here. It will ensure that the next OnData() callback + // will contain a new valid volume level. If this approach was not taken, + // we could report invalid volume levels to the client for a time period + // of up to one second. + QueryAndStoreNewMicrophoneVolume(); + } + + // Gets the latest stored volume level if AGC is enabled. + // Called at each capture callback on a real-time capture thread (platform + // dependent). + void GetAgcVolume(double* normalized_volume) { + base::AutoLock lock(lock_); + *normalized_volume = normalized_volume_; + } + + private: + // Sets the automatic gain control (AGC) to on or off. When AGC is enabled, + // the microphone volume is queried periodically and the volume level can + // be read in each AudioInputCallback::OnData() callback and fed to the + // render-side AGC. User must call StartAgc() as well to start measuring + // the microphone level. + virtual void SetAutomaticGainControl(bool enabled) OVERRIDE { + DVLOG(1) << "SetAutomaticGainControl(enabled=" << enabled << ")"; + DCHECK(thread_checker_.CalledOnValidThread()); + agc_is_enabled_ = enabled; + } + + // Gets the current automatic gain control state. + virtual bool GetAutomaticGainControl() OVERRIDE { + DCHECK(thread_checker_.CalledOnValidThread()); + return agc_is_enabled_; + } + + // Takes a new microphone volume sample and stores it in |normalized_volume_|. + // Range is normalized to [0.0,1.0] or [0.0, 1.5] on Linux. + void QueryAndStoreNewMicrophoneVolume() { + DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK(timer_.IsRunning()); + + // Cach the maximum volume if this is the first time we ask for it. + if (max_volume_ == 0.0) + max_volume_ = static_cast<AudioInterface*>(this)->GetMaxVolume(); + + // Retrieve the current volume level by asking the audio hardware. + // Range is normalized to [0.0,1.0] or [0.0, 1.5] on Linux. + if (max_volume_ != 0.0) { + double normalized_volume = + static_cast<AudioInterface*>(this)->GetVolume() / max_volume_; + base::AutoLock auto_lock(lock_); + normalized_volume_ = normalized_volume; + } + } + + // This method is called periodically when AGC is enabled and always on the + // audio manager thread. We use it to read the current microphone level and + // to store it so it can be read by the main capture thread. By using this + // approach, we can avoid accessing audio hardware from a real-time audio + // thread and it leads to a more stable capture performance. + void OnTimer() { + DCHECK(thread_checker_.CalledOnValidThread()); + QueryAndStoreNewMicrophoneVolume(); + } + + // Ensures that this class is created and destroyed on the same thread. + base::ThreadChecker thread_checker_; + + // Repeating timer which cancels itself when it goes out of scope. + // Used to check the microphone volume periodically. + base::RepeatingTimer<AgcAudioStream<AudioInterface> > timer_; + + // True when automatic gain control is enabled, false otherwise. + bool agc_is_enabled_; + + // Stores the maximum volume which is used for normalization to a volume + // range of [0.0, 1.0]. + double max_volume_; + + // Contains last result of internal call to GetVolume(). We save resources + // by not querying the capture volume for each callback. Guarded by |lock_|. + // The range is normalized to [0.0, 1.0]. + double normalized_volume_; + + // Protects |normalized_volume_| . + base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(AgcAudioStream<AudioInterface>); +}; + +} // namespace media + +#endif // MEDIA_AUDIO_AGC_AUDIO_STREAM_H_ diff --git a/media/audio/audio_input_stream_impl.cc b/media/audio/audio_input_stream_impl.cc deleted file mode 100644 index f68317c..0000000 --- a/media/audio/audio_input_stream_impl.cc +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -#include "base/logging.h" -#include "media/audio/audio_input_stream_impl.h" - -namespace media { - -static const int kMinIntervalBetweenVolumeUpdatesMs = 1000; - -AudioInputStreamImpl::AudioInputStreamImpl() - : agc_is_enabled_(false), - max_volume_(0.0), - normalized_volume_(0.0) { -} - -AudioInputStreamImpl::~AudioInputStreamImpl() {} - -void AudioInputStreamImpl::SetAutomaticGainControl(bool enabled) { - agc_is_enabled_ = enabled; -} - -bool AudioInputStreamImpl::GetAutomaticGainControl() { - return agc_is_enabled_; -} - -void AudioInputStreamImpl::UpdateAgcVolume() { - base::AutoLock lock(lock_); - - // We take new volume samples once every second when the AGC is enabled. - // To ensure that a new setting has an immediate effect, the new volume - // setting is cached here. It will ensure that the next OnData() callback - // will contain a new valid volume level. If this approach was not taken, - // we could report invalid volume levels to the client for a time period - // of up to one second. - if (agc_is_enabled_) { - GetNormalizedVolume(); - } -} - -void AudioInputStreamImpl::QueryAgcVolume(double* normalized_volume) { - base::AutoLock lock(lock_); - - // Only modify the |volume| output reference if AGC is enabled and if - // more than one second has passed since the volume was updated the last time. - if (agc_is_enabled_) { - base::Time now = base::Time::Now(); - if ((now - last_volume_update_time_).InMilliseconds() > - kMinIntervalBetweenVolumeUpdatesMs) { - GetNormalizedVolume(); - last_volume_update_time_ = now; - } - *normalized_volume = normalized_volume_; - } -} - -void AudioInputStreamImpl::GetNormalizedVolume() { - if (max_volume_ == 0.0) { - // Cach the maximum volume if this is the first time we ask for it. - max_volume_ = GetMaxVolume(); - } - - if (max_volume_ != 0.0) { - // Retrieve the current volume level by asking the audio hardware. - // Range is normalized to [0.0,1.0] or [0.0, 1.5] on Linux. - normalized_volume_ = GetVolume() / max_volume_; - } -} - -} // namespace media diff --git a/media/audio/audio_input_stream_impl.h b/media/audio/audio_input_stream_impl.h deleted file mode 100644 index 64980a9..0000000 --- a/media/audio/audio_input_stream_impl.h +++ /dev/null @@ -1,71 +0,0 @@ -// 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. - -#ifndef MEDIA_AUDIO_AUDIO_INPUT_STREAM_IMPL_H_ -#define MEDIA_AUDIO_AUDIO_INPUT_STREAM_IMPL_H_ - -#include "base/compiler_specific.h" -#include "base/synchronization/lock.h" -#include "base/time.h" -#include "media/audio/audio_io.h" - -namespace media { - -// AudioInputStreamImpl implements platform-independent parts of the -// AudioInputStream interface. Each platform dependent implementation -// should derive from this class. -// TODO(henrika): we can probably break out more parts from our current -// AudioInputStream implementation and move out to this class. -class MEDIA_EXPORT AudioInputStreamImpl : public AudioInputStream { - public: - AudioInputStreamImpl(); - virtual ~AudioInputStreamImpl(); - - // Sets the automatic gain control (AGC) to on or off. When AGC is enabled, - // the microphone volume is queried periodically and the volume level is - // provided in each AudioInputCallback::OnData() callback and fed to the - // render-side AGC. - virtual void SetAutomaticGainControl(bool enabled) OVERRIDE; - - // Gets the current automatic gain control state. - virtual bool GetAutomaticGainControl() OVERRIDE; - - protected: - // Stores a new volume level by asking the audio hardware. - // This method only has an effect if AGC is enabled. - void UpdateAgcVolume(); - - // Gets the latest stored volume level if AGC is enabled and if - // more than one second has passed since the volume was updated the last time. - void QueryAgcVolume(double* normalized_volume); - - private: - // Takes a volume sample and stores it in |normalized_volume_|. - void GetNormalizedVolume(); - - // True when automatic gain control is enabled, false otherwise. - // Guarded by |lock_|. - bool agc_is_enabled_; - - // Stores the maximum volume which is used for normalization to a volume - // range of [0.0, 1.0]. - double max_volume_; - - // Contains last result of internal call to GetVolume(). We save resources - // but not querying the capture volume for each callback. Guarded by |lock_|. - // The range is normalized to [0.0, 1.0]. - double normalized_volume_; - - // Protects |agc_is_enabled_| and |volume_| . - base::Lock lock_; - - // Keeps track of the last time the microphone volume level was queried. - base::Time last_volume_update_time_; - - DISALLOW_COPY_AND_ASSIGN(AudioInputStreamImpl); -}; - -} // namespace media - -#endif // MEDIA_AUDIO_AUDIO_INPUT_STREAM_IMPL_H_ diff --git a/media/audio/cras/cras_input.cc b/media/audio/cras/cras_input.cc index aa398b6..c080ac6 100644 --- a/media/audio/cras/cras_input.cc +++ b/media/audio/cras/cras_input.cc @@ -107,6 +107,8 @@ void CrasInputStream::Start(AudioInputCallback* callback) { if (started_) return; + StartAgc(); + callback_ = callback; LOG(ERROR) << "Input Start"; @@ -169,6 +171,8 @@ void CrasInputStream::Stop() { if (!callback_ || !started_) return; + StopAgc(); + // Removing the stream from the client stops audio. cras_client_rm_stream(client_, stream_id_); @@ -222,7 +226,7 @@ void CrasInputStream::ReadAudio(size_t frames, // also updated each time SetVolume() is called through IPC by the // render-side AGC. double normalized_volume = 0.0; - QueryAgcVolume(&normalized_volume); + GetAgcVolume(&normalized_volume); callback_->OnData(this, buffer, diff --git a/media/audio/cras/cras_input.h b/media/audio/cras/cras_input.h index 37772bf..1b2a611 100644 --- a/media/audio/cras/cras_input.h +++ b/media/audio/cras/cras_input.h @@ -12,7 +12,7 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "media/audio/audio_input_stream_impl.h" +#include "media/audio/agc_audio_stream.h" #include "media/audio/audio_io.h" #include "media/audio/audio_parameters.h" @@ -23,7 +23,7 @@ class AudioManagerCras; // Provides an input stream for audio capture based on CRAS, the ChromeOS Audio // Server. This object is not thread safe and all methods should be invoked in // the thread that created the object. -class CrasInputStream : public AudioInputStreamImpl { +class CrasInputStream : public AgcAudioStream<AudioInputStream> { public: // The ctor takes all the usual parameters, plus |manager| which is the // audio manager who is creating this object. diff --git a/media/audio/linux/alsa_input.cc b/media/audio/linux/alsa_input.cc index 8f78530..ce337d3 100644 --- a/media/audio/linux/alsa_input.cc +++ b/media/audio/linux/alsa_input.cc @@ -102,6 +102,7 @@ bool AlsaPcmInputStream::Open() { void AlsaPcmInputStream::Start(AudioInputCallback* callback) { DCHECK(!callback_ && callback); callback_ = callback; + StartAgc(); int error = wrapper_->PcmPrepare(device_handle_); if (error < 0) { HandleError("PcmPrepare", error); @@ -203,7 +204,7 @@ void AlsaPcmInputStream::ReadAudio() { // Update the AGC volume level once every second. Note that, |volume| is // also updated each time SetVolume() is called through IPC by the // render-side AGC. - QueryAgcVolume(&normalized_volume); + GetAgcVolume(&normalized_volume); while (num_buffers--) { int frames_read = wrapper_->PcmReadi(device_handle_, audio_buffer_.get(), @@ -240,6 +241,8 @@ void AlsaPcmInputStream::Stop() { if (!device_handle_ || !callback_) return; + StopAgc(); + // Stop is always called before Close. In case of error, this will be // also called when closing the input controller. audio_manager_->DecreaseActiveInputStreamCount(); diff --git a/media/audio/linux/alsa_input.h b/media/audio/linux/alsa_input.h index df2b471..57092eb 100644 --- a/media/audio/linux/alsa_input.h +++ b/media/audio/linux/alsa_input.h @@ -13,7 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time.h" -#include "media/audio/audio_input_stream_impl.h" +#include "media/audio/agc_audio_stream.h" #include "media/audio/audio_io.h" #include "media/audio/audio_parameters.h" @@ -25,7 +25,7 @@ class AudioManagerLinux; // Provides an input stream for audio capture based on the ALSA PCM interface. // This object is not thread safe and all methods should be invoked in the // thread that created the object. -class AlsaPcmInputStream : public AudioInputStreamImpl { +class AlsaPcmInputStream : public AgcAudioStream<AudioInputStream> { public: // Pass this to the constructor if you want to attempt auto-selection // of the audio recording device. diff --git a/media/audio/mac/audio_low_latency_input_mac.cc b/media/audio/mac/audio_low_latency_input_mac.cc index cf9d180..ff2f83f 100644 --- a/media/audio/mac/audio_low_latency_input_mac.cc +++ b/media/audio/mac/audio_low_latency_input_mac.cc @@ -268,6 +268,7 @@ void AUAudioInputStream::Start(AudioInputCallback* callback) { if (started_ || !audio_unit_) return; sink_ = callback; + StartAgc(); OSStatus result = AudioOutputUnitStart(audio_unit_); if (result == noErr) { started_ = true; @@ -279,6 +280,7 @@ void AUAudioInputStream::Start(AudioInputCallback* callback) { void AUAudioInputStream::Stop() { if (!started_) return; + StopAgc(); OSStatus result = AudioOutputUnitStop(audio_unit_); if (result == noErr) { started_ = false; @@ -483,11 +485,11 @@ OSStatus AUAudioInputStream::Provide(UInt32 number_of_frames, // Update the capture latency. double capture_latency_frames = GetCaptureLatency(time_stamp); - // Update the AGC volume level once every second. Note that, |volume| is - // also updated each time SetVolume() is called through IPC by the - // render-side AGC. + // The AGC volume level is updated once every second on a separate thread. + // Note that, |volume| is also updated each time SetVolume() is called + // through IPC by the render-side AGC. double normalized_volume = 0.0; - QueryAgcVolume(&normalized_volume); + GetAgcVolume(&normalized_volume); AudioBuffer& buffer = io_data->mBuffers[0]; uint8* audio_data = reinterpret_cast<uint8*>(buffer.mData); diff --git a/media/audio/mac/audio_low_latency_input_mac.h b/media/audio/mac/audio_low_latency_input_mac.h index 04a4ff8..07a727b 100644 --- a/media/audio/mac/audio_low_latency_input_mac.h +++ b/media/audio/mac/audio_low_latency_input_mac.h @@ -42,8 +42,8 @@ #include "base/atomicops.h" #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" +#include "media/audio/agc_audio_stream.h" #include "media/audio/audio_io.h" -#include "media/audio/audio_input_stream_impl.h" #include "media/audio/audio_parameters.h" #include "media/base/seekable_buffer.h" @@ -52,7 +52,7 @@ namespace media { class AudioManagerMac; class DataBuffer; -class AUAudioInputStream : public AudioInputStreamImpl { +class AUAudioInputStream : public AgcAudioStream<AudioInputStream> { public: // The ctor takes all the usual parameters, plus |manager| which is the // the audio manager who is creating this object. diff --git a/media/audio/pulse/pulse_input.cc b/media/audio/pulse/pulse_input.cc index 4e48e10..c365c47 100644 --- a/media/audio/pulse/pulse_input.cc +++ b/media/audio/pulse/pulse_input.cc @@ -66,6 +66,8 @@ void PulseAudioInputStream::Start(AudioInputCallback* callback) { if (stream_started_) return; + StartAgc(); + // Clean up the old buffer. pa_stream_drop(handle_); buffer_->Clear(); @@ -86,6 +88,8 @@ void PulseAudioInputStream::Stop() { if (!stream_started_) return; + StopAgc(); + // Set the flag to false to stop filling new data to soundcard. stream_started_ = false; @@ -246,11 +250,10 @@ void PulseAudioInputStream::ReadData() { // Update the AGC volume level once every second. Note that, // |volume| is also updated each time SetVolume() is called // through IPC by the render-side AGC. - // QueryAgcVolume() will trigger a callback to asynchronously update the - // |volume_|, we disregard the |normalized_volume| from QueryAgcVolume() + // We disregard the |normalized_volume| from GetAgcVolume() // and use the value calculated by |volume_|. double normalized_volume = 0.0; - QueryAgcVolume(&normalized_volume); + GetAgcVolume(&normalized_volume); normalized_volume = volume_ / GetMaxVolume(); do { diff --git a/media/audio/pulse/pulse_input.h b/media/audio/pulse/pulse_input.h index 00bc03f..7566eac 100644 --- a/media/audio/pulse/pulse_input.h +++ b/media/audio/pulse/pulse_input.h @@ -8,8 +8,8 @@ #include <string> #include "base/threading/thread_checker.h" +#include "media/audio/agc_audio_stream.h" #include "media/audio/audio_device_name.h" -#include "media/audio/audio_input_stream_impl.h" #include "media/audio/audio_io.h" #include "media/audio/audio_parameters.h" @@ -23,7 +23,7 @@ namespace media { class AudioManagerPulse; class SeekableBuffer; -class PulseAudioInputStream : public AudioInputStreamImpl { +class PulseAudioInputStream : public AgcAudioStream<AudioInputStream> { public: PulseAudioInputStream(AudioManagerPulse* audio_manager, const std::string& device_name, diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc index ae4c630..a57a1cb 100644 --- a/media/audio/win/audio_low_latency_input_win.cc +++ b/media/audio/win/audio_low_latency_input_win.cc @@ -127,6 +127,10 @@ void WASAPIAudioInputStream::Start(AudioInputCallback* callback) { sink_ = callback; + // Starts periodic AGC microphone measurements if the AGC has been enabled + // using SetAutomaticGainControl(). + StartAgc(); + // Create and start the thread that will drive the capturing by waiting for // capture events. capture_thread_ = @@ -146,6 +150,9 @@ void WASAPIAudioInputStream::Stop() { if (!started_) return; + // Stops periodic AGC microphone measurements. + StopAgc(); + // Shut down the capture thread. if (stop_capture_event_.IsValid()) { SetEvent(stop_capture_event_.Get()); @@ -387,10 +394,10 @@ void WASAPIAudioInputStream::Run() { first_audio_frame_timestamp) / 10000.0) * ms_to_frame_count_ + buffer_frame_index - num_frames_to_read; - // Update the AGC volume level once every second. Note that, - // |volume| is also updated each time SetVolume() is called - // through IPC by the render-side AGC. - QueryAgcVolume(&volume); + // Get a cached AGC volume level which is updated once every second + // on the audio manager thread. Note that, |volume| is also updated + // each time SetVolume() is called through IPC by the render-side AGC. + GetAgcVolume(&volume); // Deliver captured data to the registered consumer using a packet // size which was specified at construction. diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h index 68b0c61..4f9c7fb 100644 --- a/media/audio/win/audio_low_latency_input_win.h +++ b/media/audio/win/audio_low_latency_input_win.h @@ -69,7 +69,7 @@ #include "base/win/scoped_com_initializer.h" #include "base/win/scoped_comptr.h" #include "base/win/scoped_handle.h" -#include "media/audio/audio_input_stream_impl.h" +#include "media/audio/agc_audio_stream.h" #include "media/audio/audio_parameters.h" #include "media/base/media_export.h" @@ -79,7 +79,7 @@ class AudioManagerWin; // AudioInputStream implementation using Windows Core Audio APIs. class MEDIA_EXPORT WASAPIAudioInputStream - : public AudioInputStreamImpl, + : public AgcAudioStream<AudioInputStream>, public base::DelegateSimpleThread::Delegate, NON_EXPORTED_BASE(public base::NonThreadSafe) { public: |