[autotest] audio_quality: Add support for converting file format

Convert wav file with format WAVE_FORMAT_EXTENSIBLE to WAVE_FORMAT_PCM
since python wave library only supports WAVE_FORMAT_PCM.

BUG=chromium:714066
TEST=run check_quality.py on a wav file that is not wavpcm format.
     see the script uses sox to convert the file format.
Change-Id: I5405eacd402238e816626d60eefc1b75898eb2f2
Reviewed-on: https://chromium-review.googlesource.com/501689
Commit-Ready: Cheng-Yi Chiang <cychiang@chromium.org>
Tested-by: Cheng-Yi Chiang <cychiang@chromium.org>
Reviewed-by: Wai-Hong Tam <waihong@google.com>
diff --git a/client/cros/audio/check_quality.py b/client/cros/audio/check_quality.py
index c8f1de1..9b093f9 100755
--- a/client/cros/audio/check_quality.py
+++ b/client/cros/audio/check_quality.py
@@ -10,7 +10,10 @@
 import logging
 import math
 import numpy
+import os
 import pprint
+import subprocess
+import tempfile
 import wave
 
 import common
@@ -46,6 +49,11 @@
     pass
 
 
+class WaveFormatExtensibleException(Exception):
+    """Wave file is in WAVE_FORMAT_EXTENSIBLE format which is not supported."""
+    pass
+
+
 class WaveFile(object):
     """Class which handles wave file reading.
 
@@ -63,33 +71,67 @@
         self.raw_data = None
         self.rate = None
 
-        self._filename = filename
         self._wave_reader = None
         self._n_channels = None
         self._sample_width_bits = None
         self._n_frames = None
         self._binary = None
 
-        self._read_wave_file()
+        try:
+            self._read_wave_file(filename)
+        except WaveFormatExtensibleException:
+            logging.warning(
+                    'WAVE_FORMAT_EXTENSIBLE is not supproted. '
+                    'Try command "sox in.wav -t wavpcm out.wav" to convert '
+                    'the file to WAVE_FORMAT_PCM format.')
+            self._convert_and_read_wav_file(filename)
 
 
-    def _read_wave_file(self):
+    def _convert_and_read_wav_file(self, filename):
+        """Converts the wav file and read it.
+
+        Converts the file into WAVE_FORMAT_PCM format using sox command and
+        reads its content.
+
+        @param filename: The wave file to be read.
+
+        @raises: RuntimeError: sox is not installed.
+
+        """
+        # Checks if sox is installed.
+        try:
+            subprocess.check_output(['sox', '--version'])
+        except:
+            raise RuntimeError('sox command is not installed. '
+                               'Try sudo apt-get install sox')
+
+        with tempfile.NamedTemporaryFile(suffix='.wav') as converted_file:
+            command = ['sox', filename, '-t', 'wavpcm', converted_file.name]
+            logging.debug('Convert the file using sox: %s', command)
+            subprocess.check_call(command)
+            self._read_wave_file(converted_file.name)
+
+
+    def _read_wave_file(self, filename):
         """Reads wave file header and samples.
 
-        @raises:
-            WaveFileException: Wave format is not supported.
+        @param filename: The wave file to be read.
+
+        @raises WaveFormatExtensibleException: Wave file is in
+                                               WAVE_FORMAT_EXTENSIBLE format.
+        @raises WaveFileException: Wave file format is not supported.
 
         """
         try:
-            self._wave_reader = wave.open(self._filename, 'r')
+            self._wave_reader = wave.open(filename, 'r')
             self._read_wave_header()
             self._read_wave_binary()
         except wave.Error as e:
             if 'unknown format: 65534' in str(e):
-                raise WaveFileException(
-                        'WAVE_FORMAT_EXTENSIBLE is not supproted. '
-                        'Try command "sox in.wav -t wavpcm out.wav" to convert '
-                        'the file to WAVE_FORMAT_PCM format.')
+                raise WaveFormatExtensibleException()
+            else:
+                logging.exception('Unsupported wave format')
+                raise WaveFileException()
         finally:
             if self._wave_reader:
                 self._wave_reader.close()