[autotest] audio_quality_measurement: Ignore false alarm

Ignore false alarm of "noise before/after sine wave" when it is too
close to the start/end of the sine wave.
We determine start/end of sine wave by frequency of a block.
We detect noise before/after sine wave by magnitude of a block.
The block near start/end of sine wave will have magnitude that
might be incorrectly treated as noise. Add a 0.01 duration to account
for that edge effect.
This is especially easy to seen in WebRTC loopback test because the
magnitude of sine wave is large in the beginning, and then it becomes
much smaller when it stablizes.

Also add debug message for start/end detection.

BUG=chromium:667674
TEST=run audio_AudioWebRTCLoopback test.

Change-Id: Ibd9bc95c896b290e83e7651093db121d2388b6f1
Reviewed-on: https://chromium-review.googlesource.com/414966
Commit-Ready: Cheng-Yi Chiang <cychiang@chromium.org>
Tested-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Shyh-In Hwang <josephsih@chromium.org>
(cherry picked from commit 64e95aee0a0ad4ceed37e500ee0e02a81b65b122)
Reviewed-on: https://chromium-review.googlesource.com/422124
Reviewed-by: Ting Shen <phoenixshen@chromium.org>
Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Tested-by: Ting Shen <phoenixshen@chromium.org>
diff --git a/client/cros/audio/audio_quality_measurement.py b/client/cros/audio/audio_quality_measurement.py
index 8d9b972..cda1dc4 100644
--- a/client/cros/audio/audio_quality_measurement.py
+++ b/client/cros/audio/audio_quality_measurement.py
@@ -5,6 +5,7 @@
 """This module provides utilities to detect some artifacts and measure the
     quality of audio."""
 
+import logging
 import math
 import numpy
 
@@ -115,6 +116,19 @@
 # at [0, 0.11] and [10.09, 10.1] will be ignored.
 NEAR_DATA_START_OR_END_SECS = 0.01
 
+# If the noise event is too close to the start or the end of the sine wave in
+# the data, we consider its noise as part of artifacts caused by edge effect of
+# Hilbert transform.
+# A |-------------|vvvvvvvvvvvvvvvvvvvvvvv|-------------|
+# B |ooooooooo| d |                       | d |ooooooooo|
+#
+# A is full signal. It contains a sine wave and silence before and after sine
+# wave.
+# In B, |oooo| shows the parts that we are going to check for noise before/after
+# sine wave. | d | is determined by NEAR_SINE_START_OR_END_SECS.
+NEAR_SINE_START_OR_END_SECS = 0.01
+
+
 class SineWaveNotFound(Exception):
     """Error when there's no sine wave found in the signal"""
     pass
@@ -418,8 +432,12 @@
     previous_noise_index = None
     times = 0
     for index in xrange(0, length):
-        if start_index <= index and index < end_index:
+        # Ignore noise too close to the beginning or the end of sine wave.
+        # Check the docstring of NEAR_SINE_START_OR_END_SECS.
+        if ((start_index - rate * NEAR_SINE_START_OR_END_SECS) <= index and
+            (index < end_index + rate * NEAR_SINE_START_OR_END_SECS)):
             continue
+
         # Ignore noise too close to the beginning or the end of original data.
         # Check the docstring of NEAR_DATA_START_OR_END_SECS.
         if (float(index) / rate <=
@@ -823,6 +841,10 @@
     if start_index > end_index:
         raise SineWaveNotFound('No sine wave found in signal')
 
+    logging.debug('Found sine wave: start: %s, end: %s',
+                  float(start_index) / rate - APPEND_ZEROS_SECS,
+                  float(end_index) / rate - APPEND_ZEROS_SECS)
+
     sum_of_amplitude = float(sum(amplitude[start_index:end_index]))
     # Finds average amplitude of sine wave.
     average_amplitude = sum_of_amplitude / (end_index - start_index)