Home | History | Annotate | Download | only in audio_AudioBasicInternalMicrophone
      1 # Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 """This is a server side internal microphone test using the Chameleon board."""
      6 
      7 import logging
      8 import os
      9 import time
     10 
     11 from autotest_lib.client.cros.audio import audio_test_data
     12 from autotest_lib.client.cros.audio import cras_configs
     13 from autotest_lib.client.cros.chameleon import audio_test_utils
     14 from autotest_lib.client.cros.chameleon import chameleon_audio_helper
     15 from autotest_lib.client.cros.chameleon import chameleon_audio_ids
     16 from autotest_lib.server.cros.audio import audio_test
     17 from autotest_lib.server.cros.multimedia import remote_facade_factory
     18 
     19 
     20 class audio_AudioBasicInternalMicrophone(audio_test.AudioTest):
     21     """Server side internal microphone audio test.
     22 
     23     This test talks to a Chameleon board and a Cros device to verify
     24     internal mic audio function of the Cros device.
     25 
     26     """
     27     version = 1
     28     DELAY_BEFORE_RECORD_SECONDS = 0.5
     29     RECORD_SECONDS = 9
     30     DELAY_AFTER_BINDING = 0.5
     31 
     32     def run_once(self, host, cfm_speaker=False):
     33         """Runs Basic Audio Microphone test.
     34 
     35         @param host: device under test CrosHost
     36         @param cfm_speaker: whether cfm_speaker's audio is tested which is an
     37             external USB speaker on CFM (ChromeBox For Meetings) devices.
     38 
     39         """
     40         if (not cfm_speaker and
     41             not audio_test_utils.has_internal_microphone(host)):
     42             return
     43 
     44         golden_file = audio_test_data.SIMPLE_FREQUENCY_TEST_1330_FILE
     45 
     46         chameleon_board = host.chameleon
     47         factory = remote_facade_factory.RemoteFacadeFactory(
     48                 host, results_dir=self.resultsdir)
     49 
     50         chameleon_board.setup_and_reset(self.outputdir)
     51 
     52         widget_factory = chameleon_audio_helper.AudioWidgetFactory(
     53                 factory, host)
     54 
     55         source = widget_factory.create_widget(
     56             chameleon_audio_ids.ChameleonIds.LINEOUT)
     57         sink = widget_factory.create_widget(
     58             chameleon_audio_ids.PeripheralIds.SPEAKER)
     59         binder = widget_factory.create_binder(source, sink)
     60 
     61         recorder = widget_factory.create_widget(
     62             chameleon_audio_ids.CrosIds.INTERNAL_MIC)
     63 
     64         with chameleon_audio_helper.bind_widgets(binder):
     65             # Checks the node selected by cras is correct.
     66             time.sleep(self.DELAY_AFTER_BINDING)
     67             audio_facade = factory.create_audio_facade()
     68 
     69             audio_test_utils.dump_cros_audio_logs(
     70                     host, audio_facade, self.resultsdir, 'after_binding')
     71 
     72             expected_internal_mic_node = cras_configs.get_internal_mic_node(
     73                     audio_test_utils.get_board_name(host), host.get_platform())
     74             if not cfm_speaker:
     75                 audio_test_utils.check_audio_nodes(audio_facade,
     76                         (None, [expected_internal_mic_node]))
     77             else:
     78                 audio_test_utils.check_audio_nodes(audio_facade,
     79                         (None, ['USB']))
     80 
     81             logging.info('Setting playback data on Chameleon')
     82             source.set_playback_data(golden_file)
     83 
     84             # Starts playing, waits for some time, and then starts recording.
     85             # This is to avoid artifact caused by chameleon codec initialization
     86             # in the beginning of playback.
     87             logging.info('Start playing %s from Chameleon',
     88                          golden_file.path)
     89             source.start_playback()
     90 
     91             time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
     92             logging.info('Start recording from Cros device.')
     93             recorder.start_recording()
     94 
     95             time.sleep(self.RECORD_SECONDS)
     96 
     97             recorder.stop_recording()
     98             logging.info('Stopped recording from Cros device.')
     99 
    100             audio_test_utils.dump_cros_audio_logs(
    101                     host, audio_facade, self.resultsdir, 'after_recording')
    102 
    103             recorder.read_recorded_binary()
    104             logging.info('Read recorded binary from Cros device.')
    105 
    106         recorded_file = os.path.join(self.resultsdir, "recorded.raw")
    107         logging.info('Saving recorded data to %s', recorded_file)
    108         recorder.save_file(recorded_file)
    109 
    110         # Removes the beginning of recorded data. This is to avoid artifact
    111         # caused by Cros device codec initialization in the beginning of
    112         # recording.
    113         recorder.remove_head(1.0)
    114 
    115         # Removes noise by a lowpass filter.
    116         recorder.lowpass_filter(1500)
    117         recorded_file = os.path.join(self.resultsdir, "recorded_filtered.raw")
    118         logging.info('Saving filtered data to %s', recorded_file)
    119         recorder.save_file(recorded_file)
    120 
    121         # Cros device only records one channel data. Here we set the channel map
    122         # of the recorder to compare the recorded data with left channel of the
    123         # test data. This is fine as left and right channel of test data are
    124         # identical.
    125         recorder.channel_map = [0]
    126 
    127         # Compares data by frequency. Audio signal from Chameleon Line-Out to
    128         # speaker and finally recorded on Cros device using internal microphone
    129         # has gone through analog processing and through the air.
    130         # This suffers from codec artifacts and noise on the path.
    131         # Comparing data by frequency is more robust than comparing them by
    132         # correlation, which is suitable for fully-digital audio path like USB
    133         # and HDMI.
    134         audio_test_utils.check_recorded_frequency(golden_file, recorder,
    135                                                   second_peak_ratio=0.2)
    136