Better silence detection in audio capturers

Previously audio capturers were dropping silent packets too aggressively
and that would disrupt playback on the client side when there are short
silence pauses in the stream.

BUG=164308

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@174886 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/remoting/host/audio_capturer_win.cc b/remoting/host/audio_capturer_win.cc
index 977bdaf..cca276b 100644
--- a/remoting/host/audio_capturer_win.cc
+++ b/remoting/host/audio_capturer_win.cc
@@ -16,8 +16,8 @@
 
 namespace {
 const int kChannels = 2;
-const int kBitsPerSample = 16;
-const int kBitsPerByte = 8;
+const int kBytesPerSample = 2;
+const int kBitsPerSample = kBytesPerSample * 8;
 // Conversion factor from 100ns to 1ms.
 const int k100nsPerMillisecond = 10000;
 
@@ -38,7 +38,8 @@
 namespace remoting {
 
 AudioCapturerWin::AudioCapturerWin()
-    : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID) {
+    : sampling_rate_(AudioPacket::SAMPLING_RATE_INVALID),
+      silence_detector_(kSilenceThreshold){
       thread_checker_.DetachFromThread();
 }
 
@@ -120,9 +121,9 @@
       wave_format_ex_->wFormatTag = WAVE_FORMAT_PCM;
       wave_format_ex_->nChannels = kChannels;
       wave_format_ex_->wBitsPerSample = kBitsPerSample;
-      wave_format_ex_->nBlockAlign = kChannels * kBitsPerSample / kBitsPerByte;
+      wave_format_ex_->nBlockAlign = kChannels * kBytesPerSample;
       wave_format_ex_->nAvgBytesPerSec =
-          sampling_rate_ * kChannels * kBitsPerSample / kBitsPerByte;
+          sampling_rate_ * kChannels * kBytesPerSample;
       break;
     case WAVE_FORMAT_EXTENSIBLE: {
       PWAVEFORMATEXTENSIBLE wave_format_extensible =
@@ -145,9 +146,9 @@
         wave_format_extensible->Format.nSamplesPerSec = sampling_rate_;
         wave_format_extensible->Format.wBitsPerSample = kBitsPerSample;
         wave_format_extensible->Format.nBlockAlign =
-            kChannels * kBitsPerSample / kBitsPerByte;
+            kChannels * kBytesPerSample;
         wave_format_extensible->Format.nAvgBytesPerSec =
-            sampling_rate_ * kChannels * kBitsPerSample / kBitsPerByte;
+            sampling_rate_ * kChannels * kBytesPerSample;
       } else {
         LOG(ERROR) << "Failed to force 16-bit samples";
         return false;
@@ -188,6 +189,8 @@
     return false;
   }
 
+  silence_detector_.Reset(sampling_rate_, kChannels);
+
   // Start capturing.
   capture_timer_->Start(FROM_HERE,
                         audio_device_period_,
@@ -235,16 +238,14 @@
     BYTE* data;
     UINT32 frames;
     DWORD flags;
-    hr = audio_capture_client_->GetBuffer(
-        &data, &frames, &flags, NULL, NULL);
+    hr = audio_capture_client_->GetBuffer(&data, &frames, &flags, NULL, NULL);
     if (FAILED(hr)) {
       LOG(ERROR) << "Failed to GetBuffer. Error " << hr;
       return;
     }
 
-    if (!IsPacketOfSilence(
-            reinterpret_cast<const int16*>(data),
-            frames * kChannels)) {
+    if (!silence_detector_.IsSilence(
+            reinterpret_cast<const int16*>(data), frames * kChannels)) {
       scoped_ptr<AudioPacket> packet =
           scoped_ptr<AudioPacket>(new AudioPacket());
       packet->add_data(data, frames * wave_format_ex_->nBlockAlign);
@@ -264,19 +265,6 @@
   }
 }
 
-// Detects whether there is audio playing in a packet of samples.
-// Windows can give nonzero samples, even when there is no audio playing, so
-// extremely low amplitude samples are counted as silence.
-// static
-bool AudioCapturerWin::IsPacketOfSilence(
-    const int16* samples, int number_of_samples) {
-  for (int i = 0; i < number_of_samples; i++) {
-    if (abs(samples[i]) > kSilenceThreshold)
-      return false;
-  }
-  return true;
-}
-
 bool AudioCapturer::IsSupported() {
   return true;
 }