Move total audio energy and duration tracking to AudioLevel and protect with existing critial section.

BUG=webrtc:7982

Review-Url: https://codereview.webrtc.org/2984473002
Cr-Commit-Position: refs/heads/master@{#19105}
diff --git a/webrtc/voice_engine/audio_level.cc b/webrtc/voice_engine/audio_level.cc
index 27a7dde..ab41149 100644
--- a/webrtc/voice_engine/audio_level.cc
+++ b/webrtc/voice_engine/audio_level.cc
@@ -48,7 +48,17 @@
   current_level_full_range_ = 0;
 }
 
-void AudioLevel::ComputeLevel(const AudioFrame& audioFrame) {
+double AudioLevel::TotalEnergy() const {
+  rtc::CritScope cs(&crit_sect_);
+  return total_energy_;
+}
+
+double AudioLevel::TotalDuration() const {
+  rtc::CritScope cs(&crit_sect_);
+  return total_duration_;
+}
+
+void AudioLevel::ComputeLevel(const AudioFrame& audioFrame, double duration) {
   // Check speech level (works for 2 channels as well)
   int16_t abs_value = audioFrame.muted() ? 0 :
       WebRtcSpl_MaxAbsValueW16(
@@ -83,6 +93,18 @@
     // Decay the absolute maximum (divide by 4)
     abs_max_ >>= 2;
   }
+
+  // See the description for "totalAudioEnergy" in the WebRTC stats spec
+  // (https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy)
+  // for an explanation of these formulas. In short, we need a value that can
+  // be used to compute RMS audio levels over different time intervals, by
+  // taking the difference between the results from two getStats calls. To do
+  // this, the value needs to be of units "squared sample value * time".
+  double additional_energy =
+      static_cast<double>(current_level_full_range_) / INT16_MAX;
+  additional_energy *= additional_energy;
+  total_energy_ += additional_energy * duration;
+  total_duration_ += duration;
 }
 
 }  // namespace voe
diff --git a/webrtc/voice_engine/audio_level.h b/webrtc/voice_engine/audio_level.h
index 3bcb0d9..caecf40 100644
--- a/webrtc/voice_engine/audio_level.h
+++ b/webrtc/voice_engine/audio_level.h
@@ -29,11 +29,15 @@
   int8_t Level() const;
   int16_t LevelFullRange() const;
   void Clear();
+  // See the description for "totalAudioEnergy" in the WebRTC stats spec
+  // (https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy)
+  double TotalEnergy() const;
+  double TotalDuration() const;
 
   // Called on a native capture audio thread (platform dependent) from the
   // AudioTransport::RecordedDataIsAvailable() callback.
   // In Chrome, this method is called on the AudioInputDevice thread.
-  void ComputeLevel(const AudioFrame& audioFrame);
+  void ComputeLevel(const AudioFrame& audioFrame, double duration);
 
  private:
   enum { kUpdateFrequency = 10 };
@@ -44,6 +48,9 @@
   int16_t count_;
   int8_t current_level_;
   int16_t current_level_full_range_;
+
+  double total_energy_ = 0.0;
+  double total_duration_ = 0.0;
 };
 
 }  // namespace voe
diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index 02001ba..5c2525c 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -697,20 +697,9 @@
 
   // Measure audio level (0-9)
   // TODO(henrik.lundin) Use the |muted| information here too.
-  // TODO(deadbeef): Use RmsLevel for |_outputAudioLevel| as well (see
+  // TODO(deadbeef): Use RmsLevel for |_outputAudioLevel| (see
   // https://crbug.com/webrtc/7517).
-  _outputAudioLevel.ComputeLevel(*audioFrame);
-  // See the description for "totalAudioEnergy" in the WebRTC stats spec
-  // (https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy)
-  // for an explanation of these formulas. In short, we need a value that can
-  // be used to compute RMS audio levels over different time intervals, by
-  // taking the difference between the results from two getStats calls. To do
-  // this, the value needs to be of units "squared sample value * time".
-  double additional_energy =
-      static_cast<double>(_outputAudioLevel.LevelFullRange()) / INT16_MAX;
-  additional_energy *= additional_energy;
-  totalOutputEnergy_ += additional_energy * kAudioSampleDurationSeconds;
-  totalOutputDuration_ += kAudioSampleDurationSeconds;
+  _outputAudioLevel.ComputeLevel(*audioFrame, kAudioSampleDurationSeconds);
 
   if (capture_start_rtp_time_stamp_ < 0 && audioFrame->timestamp_ != 0) {
     // The first frame with a valid rtp timestamp.
@@ -2385,11 +2374,11 @@
 }
 
 double Channel::GetTotalOutputEnergy() const {
-  return totalOutputEnergy_;
+  return _outputAudioLevel.TotalEnergy();
 }
 
 double Channel::GetTotalOutputDuration() const {
-  return totalOutputDuration_;
+  return _outputAudioLevel.TotalDuration();
 }
 
 void Channel::SetInputMute(bool enable) {
diff --git a/webrtc/voice_engine/channel.h b/webrtc/voice_engine/channel.h
index 7fb8ae8..9ec3eba 100644
--- a/webrtc/voice_engine/channel.h
+++ b/webrtc/voice_engine/channel.h
@@ -474,8 +474,6 @@
   acm2::RentACodec rent_a_codec_;
   std::unique_ptr<AudioSinkInterface> audio_sink_;
   AudioLevel _outputAudioLevel;
-  double totalOutputEnergy_ = 0.0;
-  double totalOutputDuration_ = 0.0;
   bool _externalTransport;
   // Downsamples to the codec rate if necessary.
   PushResampler<int16_t> input_resampler_;
diff --git a/webrtc/voice_engine/transmit_mixer.cc b/webrtc/voice_engine/transmit_mixer.cc
index 06f37c2..32f4848 100644
--- a/webrtc/voice_engine/transmit_mixer.cc
+++ b/webrtc/voice_engine/transmit_mixer.cc
@@ -313,20 +313,8 @@
     }
 
     // --- Measure audio level of speech after all processing.
-    _audioLevel.ComputeLevel(_audioFrame);
-
-    // See the description for "totalAudioEnergy" in the WebRTC stats spec
-    // (https://w3c.github.io/webrtc-stats/#dom-rtcmediastreamtrackstats-totalaudioenergy)
-    // for an explanation of these formulas. In short, we need a value that can
-    // be used to compute RMS audio levels over different time intervals, by
-    // taking the difference between the results from two getStats calls. To do
-    // this, the value needs to be of units "squared sample value * time".
-    double additional_energy =
-        static_cast<double>(_audioLevel.LevelFullRange()) / INT16_MAX;
-    additional_energy *= additional_energy;
     double sample_duration = static_cast<double>(nSamples) / samplesPerSec;
-    totalInputEnergy_ += additional_energy * sample_duration;
-    totalInputDuration_ += sample_duration;
+    _audioLevel.ComputeLevel(_audioFrame, sample_duration);
 
     return 0;
 }
@@ -872,11 +860,11 @@
 }
 
 double TransmitMixer::GetTotalInputEnergy() const {
-  return totalInputEnergy_;
+  return _audioLevel.TotalEnergy();
 }
 
 double TransmitMixer::GetTotalInputDuration() const {
-  return totalInputDuration_;
+  return _audioLevel.TotalDuration();
 }
 
 bool TransmitMixer::IsRecordingCall()
diff --git a/webrtc/voice_engine/transmit_mixer.h b/webrtc/voice_engine/transmit_mixer.h
index 6fcb86e..0ba99cf 100644
--- a/webrtc/voice_engine/transmit_mixer.h
+++ b/webrtc/voice_engine/transmit_mixer.h
@@ -197,8 +197,6 @@
     bool _fileRecording = false;
     bool _fileCallRecording = false;
     voe::AudioLevel _audioLevel;
-    double totalInputEnergy_ = 0.0;
-    double totalInputDuration_ = 0.0;
     // protect file instances and their variables in MixedParticipants()
     rtc::CriticalSection _critSect;
     rtc::CriticalSection _callbackCritSect;