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