190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifndef MEDIA_AUDIO_AGC_AUDIO_STREAM_H_ 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define MEDIA_AUDIO_AGC_AUDIO_STREAM_H_ 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h" 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/synchronization/lock.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/threading/thread_checker.h" 12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/timer/timer.h" 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "media/audio/audio_io.h" 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// The template based AgcAudioStream implements platform-independent parts 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// of the AudioInterface interface. Supported interfaces to pass as 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AudioInterface are AudioIntputStream and AudioOutputStream. Each platform- 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// dependent implementation should derive from this class. 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Usage example (on Windows): 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// class WASAPIAudioInputStream : public AgcAudioStream<AudioInputStream> { 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// public: 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// WASAPIAudioInputStream(); 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// ... 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// }; 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Call flow example: 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 1) User creates AgcAudioStream<AudioInputStream> 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 2) User calls AudioInputStream::SetAutomaticGainControl(true) => 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AGC usage is now initialized but not yet started. 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 3) User calls AudioInputStream::Start() => implementation calls 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AgcAudioStream<AudioInputStream>::StartAgc() which detects that AGC 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// is enabled and then starts the periodic AGC timer. 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 4) Microphone volume samples are now taken and included in all 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AudioInputCallback::OnData() callbacks. 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 5) User calls AudioInputStream::Stop() => implementation calls 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AgcAudioStream<AudioInputStream>::StopAgc() which stops the timer. 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Note that, calling AudioInputStream::SetAutomaticGainControl(false) while 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AGC measurements are active will not have an effect until StopAgc(), 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// StartAgc() are called again since SetAutomaticGainControl() only sets a 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// a state. 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Calling SetAutomaticGainControl(true) enables the AGC and StartAgc() starts 47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// a periodic timer which calls QueryAndStoreNewMicrophoneVolume() 48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// approximately once every second. QueryAndStoreNewMicrophoneVolume() asks 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// the actual microphone about its current volume level. This value is 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// normalized and stored so it can be read by GetAgcVolume() when the real-time 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// audio thread needs the value. The main idea behind this scheme is to avoid 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// accessing the audio hardware from the real-time audio thread and to ensure 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// that we don't take new microphone-level samples too often (~1 Hz is a 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// suitable compromise). The timer will be active until StopAgc() is called. 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This class should be created and destroyed on the audio manager thread and 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// a thread checker is added to ensure that this is the case (uses DCHECK). 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// All methods except GetAgcVolume() should be called on the creating thread 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// as well to ensure that thread safety is maintained. It will also guarantee 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// that the periodic timer runs on the audio manager thread. 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// |normalized_volume_|, which is updated by QueryAndStoreNewMicrophoneVolume() 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// and read in GetAgcVolume(), is protected by a lock to ensure that it can 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// be accessed from any real-time audio thread that needs it to update the its 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// AGC volume. 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace media { 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)template <typename AudioInterface> 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class MEDIA_EXPORT AgcAudioStream : public AudioInterface { 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Time between two successive timer events. 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static const int kIntervalBetweenVolumeUpdatesMs = 1000; 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AgcAudioStream() 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) : agc_is_enabled_(false), max_volume_(0.0), normalized_volume_(0.0) { 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual ~AgcAudioStream() { 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) protected: 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Starts the periodic timer which periodically checks and updates the 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // current microphone volume level. 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The timer is only started if AGC mode is first enabled using the 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // SetAutomaticGainControl() method. 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void StartAgc() { 8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!agc_is_enabled_ || timer_.IsRunning()) 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Query and cache the volume to avoid sending 0 as volume to AGC at the 93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // beginning of the audio stream, otherwise AGC will try to raise the 94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // volume from 0. 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) QueryAndStoreNewMicrophoneVolume(); 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) timer_.Start(FROM_HERE, 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::TimeDelta::FromMilliseconds(kIntervalBetweenVolumeUpdatesMs), 99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) this, &AgcAudioStream::QueryAndStoreNewMicrophoneVolume); 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Stops the periodic timer which periodically checks and updates the 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // current microphone volume level. 10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void StopAgc() { 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (timer_.IsRunning()) 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) timer_.Stop(); 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Stores a new microphone volume level by checking the audio input device. 11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Called on the audio manager thread. 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void UpdateAgcVolume() { 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!timer_.IsRunning()) 116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return; 117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // We take new volume samples once every second when the AGC is enabled. 11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // To ensure that a new setting has an immediate effect, the new volume 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // setting is cached here. It will ensure that the next OnData() callback 12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // will contain a new valid volume level. If this approach was not taken, 12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // we could report invalid volume levels to the client for a time period 12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // of up to one second. 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) QueryAndStoreNewMicrophoneVolume(); 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Gets the latest stored volume level if AGC is enabled. 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Called at each capture callback on a real-time capture thread (platform 12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // dependent). 13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void GetAgcVolume(double* normalized_volume) { 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::AutoLock lock(lock_); 13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *normalized_volume = normalized_volume_; 13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Sets the automatic gain control (AGC) to on or off. When AGC is enabled, 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the microphone volume is queried periodically and the volume level can 13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // be read in each AudioInputCallback::OnData() callback and fed to the 13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // render-side AGC. User must call StartAgc() as well to start measuring 14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the microphone level. 14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void SetAutomaticGainControl(bool enabled) OVERRIDE { 14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DVLOG(1) << "SetAutomaticGainControl(enabled=" << enabled << ")"; 14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) agc_is_enabled_ = enabled; 14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Gets the current automatic gain control state. 14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool GetAutomaticGainControl() OVERRIDE { 14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return agc_is_enabled_; 15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Takes a new microphone volume sample and stores it in |normalized_volume_|. 15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Range is normalized to [0.0,1.0] or [0.0, 1.5] on Linux. 155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // This method is called periodically when AGC is enabled and always on the 156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // audio manager thread. We use it to read the current microphone level and 157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // to store it so it can be read by the main capture thread. By using this 158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // approach, we can avoid accessing audio hardware from a real-time audio 159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // thread and it leads to a more stable capture performance. 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void QueryAndStoreNewMicrophoneVolume() { 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Cach the maximum volume if this is the first time we ask for it. 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (max_volume_ == 0.0) 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) max_volume_ = static_cast<AudioInterface*>(this)->GetMaxVolume(); 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Retrieve the current volume level by asking the audio hardware. 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Range is normalized to [0.0,1.0] or [0.0, 1.5] on Linux. 16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (max_volume_ != 0.0) { 17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) double normalized_volume = 17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static_cast<AudioInterface*>(this)->GetVolume() / max_volume_; 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::AutoLock auto_lock(lock_); 17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) normalized_volume_ = normalized_volume; 17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Ensures that this class is created and destroyed on the same thread. 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::ThreadChecker thread_checker_; 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Repeating timer which cancels itself when it goes out of scope. 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Used to check the microphone volume periodically. 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::RepeatingTimer<AgcAudioStream<AudioInterface> > timer_; 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // True when automatic gain control is enabled, false otherwise. 18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool agc_is_enabled_; 18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Stores the maximum volume which is used for normalization to a volume 18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // range of [0.0, 1.0]. 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) double max_volume_; 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Contains last result of internal call to GetVolume(). We save resources 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // by not querying the capture volume for each callback. Guarded by |lock_|. 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The range is normalized to [0.0, 1.0]. 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) double normalized_volume_; 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Protects |normalized_volume_| . 19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Lock lock_; 19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(AgcAudioStream<AudioInterface>); 20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} // namespace media 20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif // MEDIA_AUDIO_AGC_AUDIO_STREAM_H_ 205