// Copyright 2012 The Chromium Authors // 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 <atomic> #include "base/logging.h" #include "base/threading/thread_checker.h" #include "base/timer/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 QueryAndStoreNewMicrophoneVolume() // approximately once every second. QueryAndStoreNewMicrophoneVolume() 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 atomic 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 { … }; } // namespace media #endif // MEDIA_AUDIO_AGC_AUDIO_STREAM_H_