blob: 03cd8ff76e0acdf912fd2a2a59892e9d2665a512 [file] [log] [blame]
# Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging, os, tempfile
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.audio import audio_helper
from autotest_lib.client.cros.audio import alsa_utils
from autotest_lib.client.cros.audio import cmd_utils
from autotest_lib.client.cros.audio import cras_utils
from autotest_lib.client.cros.audio import sox_utils
TEST_DURATION = 1
VOLUME_LEVEL = 100
CAPTURE_GAIN = 2500
RMS_THRESHOLD = 0.05
class audiovideo_LineOutToMicInLoopback(test.test):
"""Verifies audio playback and capture function."""
version = 1
preserve_srcdir = True
def run_once(self):
"""Entry point of this test."""
# Multitone wav file lasts 10 seconds
self._wav_path = os.path.join(self.srcdir, '10SEC.wav')
# Config the playback volume and recording gain.
cras_utils.set_system_volume(VOLUME_LEVEL)
output_node, _ = cras_utils.get_selected_nodes()
cras_utils.set_node_volume(output_node, VOLUME_LEVEL)
cras_utils.set_capture_gain(CAPTURE_GAIN)
# CRAS does not apply the volume and capture gain to ALSA until
# streams are added. Do that to ensure the values have been set.
cras_utils.playback('-')
cras_utils.capture('/dev/null', duration=0.1)
if not audio_helper.check_loopback_dongle():
raise error.TestError('Audio loopback dongle is in bad state.')
self.loopback_test_hw()
self.loopback_test_cras()
def _check_rms(self, noise_file, recorded_file):
with tempfile.NamedTemporaryFile() as noise_profile,\
tempfile.NamedTemporaryFile() as reduced_file:
sox_utils.noise_profile(noise_file, noise_profile.name)
sox_utils.noise_reduce(
recorded_file, reduced_file.name, noise_profile.name)
stat = sox_utils.get_stat(reduced_file.name)
logging.info('stat: %s', str(stat))
if stat.rms < RMS_THRESHOLD:
raise error.TestFail('RMS: %s' % stat.rms)
def loopback_test_hw(self):
logging.info('loopback_test_hw')
noise_file = os.path.join(self.resultsdir, 'hw_noise.wav')
recorded_file = os.path.join(self.resultsdir, 'hw_recorded.wav')
# Record a sample of "silence" to use as a noise profile.
alsa_utils.record(noise_file, duration=TEST_DURATION)
p1 = cmd_utils.popen(alsa_utils.playback_cmd(
self._wav_path, duration=TEST_DURATION))
p2 = cmd_utils.popen(alsa_utils.record_cmd(
recorded_file, duration=TEST_DURATION))
cmd_utils.wait_and_check_returncode(p1, p2)
self._check_rms(noise_file, recorded_file)
# Keep the file if the above check fails
os.unlink(noise_file)
os.unlink(recorded_file)
def loopback_test_cras(self):
"""Uses cras_test_client to test audio on CRAS."""
logging.info('loopback_test_cras')
noise_file = os.path.join(self.resultsdir, 'cras_noise.wav')
recorded_file = os.path.join(self.resultsdir, 'cras_recorded.wav')
# Record a sample of "silence" to use as a noise profile.
cras_utils.capture(noise_file, duration=TEST_DURATION)
p1 = cmd_utils.popen(cras_utils.playback_cmd(
self._wav_path, duration=TEST_DURATION))
p2 = cmd_utils.popen(cras_utils.capture_cmd(
recorded_file, duration=TEST_DURATION))
cmd_utils.wait_and_check_returncode(p1, p2)
self._check_rms(noise_file, recorded_file)
# Keep these files if the above check failed
os.unlink(noise_file)
os.unlink(recorded_file)