19b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang# Copyright 2015 The Chromium OS Authors. All rights reserved.
29b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang# Use of this source code is governed by a BSD-style license that can be
39b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang# found in the LICENSE file.
49b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
59b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang"""This is a server side external microphone test using the Chameleon board."""
69b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
79b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangimport logging
89b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangimport os
99b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangimport time
109b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
119b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangfrom autotest_lib.client.common_lib import error
129b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangfrom autotest_lib.client.cros.audio import audio_test_data
1308529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiangfrom autotest_lib.client.cros.chameleon import audio_test_utils
149b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangfrom autotest_lib.client.cros.chameleon import chameleon_audio_ids
159b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiangfrom autotest_lib.client.cros.chameleon import chameleon_audio_helper
1651876573ba85aedf3bf6c7f8f94388f7fb12f4d2Cheng-Yi Chiangfrom autotest_lib.server.cros.audio import audio_test
17ad78170c346b5abb156841452cdd75d9f30422c2Moja Hsufrom autotest_lib.server.cros.multimedia import remote_facade_factory
189b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
199b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
2051876573ba85aedf3bf6c7f8f94388f7fb12f4d2Cheng-Yi Chiangclass audio_AudioBasicExternalMicrophone(audio_test.AudioTest):
219b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang    """Server side external microphone audio test.
229b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
239b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang    This test talks to a Chameleon board and a Cros device to verify
249b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang    external mic audio function of the Cros device.
259b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
269b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang    """
279b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang    version = 1
289b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang    DELAY_BEFORE_RECORD_SECONDS = 0.5
2989c49169d9c37f8775a03d4951a7901d39ece16cSridhar Sonti    RECORD_SECONDS = 9
30b3520e614e86db0380b1eeeed428dac731b78ef4Cheng-Yi Chiang    DELAY_AFTER_BINDING = 0.5
319b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
329da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang    def run_once(self, host, check_quality=False):
339da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang        """Running basic headphone audio tests.
349da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang
359da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang        @param host: device under test host
369da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang        @param check_quality: flag to check audio quality.
379da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang
389da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang        """
399b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        golden_file = audio_test_data.SIMPLE_FREQUENCY_TEST_FILE
409b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
419b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        chameleon_board = host.chameleon
42ad78170c346b5abb156841452cdd75d9f30422c2Moja Hsu        factory = remote_facade_factory.RemoteFacadeFactory(
43ad78170c346b5abb156841452cdd75d9f30422c2Moja Hsu                host, results_dir=self.resultsdir)
449b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
452f46422e7c73d027f284eaafe1dadc7b50314434Moja Hsu        chameleon_board.setup_and_reset(self.outputdir)
469b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
479b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        widget_factory = chameleon_audio_helper.AudioWidgetFactory(
48981a0ae6eb8914b6355245a913eac00494c2f65aCheng-Yi Chiang                factory, host)
499b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
509b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        source = widget_factory.create_widget(
519b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            chameleon_audio_ids.ChameleonIds.LINEOUT)
529b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        recorder = widget_factory.create_widget(
539b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            chameleon_audio_ids.CrosIds.EXTERNAL_MIC)
549b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        binder = widget_factory.create_binder(source, recorder)
559b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
569b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        with chameleon_audio_helper.bind_widgets(binder):
57b3520e614e86db0380b1eeeed428dac731b78ef4Cheng-Yi Chiang            # Checks the node selected by cras is correct.
58b3520e614e86db0380b1eeeed428dac731b78ef4Cheng-Yi Chiang            time.sleep(self.DELAY_AFTER_BINDING)
59b3520e614e86db0380b1eeeed428dac731b78ef4Cheng-Yi Chiang            audio_facade = factory.create_audio_facade()
6008529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang
6108529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang            audio_test_utils.dump_cros_audio_logs(
6208529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang                    host, audio_facade, self.resultsdir, 'after_binding')
6308529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang
64bb052f834fe0a51fb81be4e4e40995964edf51d6Cheng-Yi Chiang            _, input_nodes = audio_facade.get_selected_node_types()
65bb052f834fe0a51fb81be4e4e40995964edf51d6Cheng-Yi Chiang            if input_nodes != ['MIC']:
66fc41c8e8b1520157890d2abb3db1464d9172e27fCheng-Yi Chiang                raise error.TestFail(
67b3520e614e86db0380b1eeeed428dac731b78ef4Cheng-Yi Chiang                        '%s rather than external mic is selected on Cros '
68bb052f834fe0a51fb81be4e4e40995964edf51d6Cheng-Yi Chiang                        'device' % input_nodes)
69b3520e614e86db0380b1eeeed428dac731b78ef4Cheng-Yi Chiang
7021833f5fb416171df282cd3d2176db6e55a8c6aeCheng-Yi Chiang            logging.info('Setting playback data on Chameleon')
7121833f5fb416171df282cd3d2176db6e55a8c6aeCheng-Yi Chiang            source.set_playback_data(golden_file)
7221833f5fb416171df282cd3d2176db6e55a8c6aeCheng-Yi Chiang
739b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            # Starts playing, waits for some time, and then starts recording.
749b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            # This is to avoid artifact caused by chameleon codec initialization
759b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            # in the beginning of playback.
769b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            logging.info('Start playing %s from Chameleon',
779b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang                         golden_file.path)
7821833f5fb416171df282cd3d2176db6e55a8c6aeCheng-Yi Chiang            source.start_playback()
799b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
809b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
819b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            logging.info('Start recording from Cros device.')
829b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            recorder.start_recording()
839b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
849b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            time.sleep(self.RECORD_SECONDS)
859b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
869b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            recorder.stop_recording()
879b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang            logging.info('Stopped recording from Cros device.')
889b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
8908529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang            audio_test_utils.dump_cros_audio_logs(
9008529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang                    host, audio_facade, self.resultsdir, 'after_recording')
9108529c0d4b5a19d4628c38b5a52f3a80220d5dbdCheng-Yi Chiang
9221833f5fb416171df282cd3d2176db6e55a8c6aeCheng-Yi Chiang            recorder.read_recorded_binary()
9321833f5fb416171df282cd3d2176db6e55a8c6aeCheng-Yi Chiang            logging.info('Read recorded binary from Cros device.')
949b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
959b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        recorded_file = os.path.join(self.resultsdir, "recorded.raw")
969b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        logging.info('Saving recorded data to %s', recorded_file)
979b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        recorder.save_file(recorded_file)
989b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
999b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # Removes the beginning of recorded data. This is to avoid artifact
1009b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # caused by Cros device codec initialization in the beginning of
1019b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # recording.
10289c49169d9c37f8775a03d4951a7901d39ece16cSridhar Sonti        recorder.remove_head(4.5)
1039b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
1045bbea9a6d52185b9de17a321667899b27ddb3849Cheng-Yi Chiang        recorded_file = os.path.join(self.resultsdir, "recorded_clipped.raw")
1055bbea9a6d52185b9de17a321667899b27ddb3849Cheng-Yi Chiang        logging.info('Saving clipped data to %s', recorded_file)
1069b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        recorder.save_file(recorded_file)
1079b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang
1089b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # Compares data by frequency. Audio signal from Chameleon Line-Out to
1099b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # Cros device external microphone has gone through analog processing.
1109b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # This suffers from codec artifacts and noise on the path.
1119b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # Comparing data by frequency is more robust than comparing them by
1129b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # correlation, which is suitable for fully-digital audio path like USB
1139b2d499937877b7b79c8148226ebc3410f4a884bCheng-Yi Chiang        # and HDMI.
1149da3fda8d20b6daa86215bca2e79794ce0e5742aCheng-Yi Chiang        audio_test_utils.check_recorded_frequency(
115431e9e68df2c9be67d13cb54ffc5ae32542cfdd1Cheng-Yi Chiang                golden_file, recorder, check_artifacts=check_quality,
116431e9e68df2c9be67d13cb54ffc5ae32542cfdd1Cheng-Yi Chiang                ignore_frequencies=[50, 60])
117