audio_loop

Source code: audio_loop.py

A factory test for the audio function.

Description

This test perform tests on audio playback and recording devices. It supports 2 loopback modes:

  1. Loop from headphone out to headphone in.

  2. Loop from speaker to digital microphone.

And 3 test scenarios:

  1. Audiofun test, which plays different tones and checks recorded frequency. This test can be conducted simultaneously on different devices. This test can not be conducted with dongle inserted.

  2. Sinewav test, which plays simple sine wav and checks if the recorded frequency is in the range specified. Optionally checks the RMS and amplitude thresholds.

  3. Noise test, which plays nothing and record, then checks the RMS and amplitude thresholds.

Since this test is sensitive to different loopback dongles, user can set a list of output volume candidates. The test can pass if it can pass at any one of output volume candidates.

Test Procedure

  1. Operator inserts the dongle (if required).

  2. The playback starts automatically, and analyze recordings afterward.

Dependency

  • Device API cros.factory.device.audio.

Examples

Here are some test list examples for different test cases. First, you need to figure out the particular input/output device you want to perform test on.

To find the audio card name, use the command arecord -l or aplay -l.

For instance, if arecord -l shows as card 0: kblrt5514rt5663 [kblrt5514rt5663max], device 1: Audio Record (*), then your audio card name is kblrt5514rt5663max or 0 and your device index is 1. In test list argument, input_dev is [“kblrt5514rt5663max”, “1”] or [“0”, “1”].

We also have some alias for common input and output devices:

  • The input_dev can be [“kblrt5514rt5663max”, “Dmic”], [“kblrt5514rt5663max”, “Dmic2”], or [“kblrt5514rt5663max”, “Extmic”].

  • The output_dev can be [“kblrt5514rt5663max”, “Headphone”], or [“kblrt5514rt5663max”, “Speaker”].

We use the minimal volume_gain and lower frequency to protect ears in the examples. Use default volume_gain and frequency in production to achieve higher accuracy.

To run Audiofuntest on external mic (default) and speakers:

{
  "pytest_name": "audio_loop",
  "label": "Speaker/External Microphone",
  "related_components": [
    "test_tags.TestCategory.AUDIOCODEC",
    "test_tags.TestCategory.SMART_SPEAKER_AMPLIFIER",
    "test_tags.TestCategory.SPEAKERAMPLIFIER"
  ],
  "args": {
    "input_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Extmic"
    ],
    "output_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Speaker"
    ],
    "mic_source": "Extmic",
    "require_dongle": false,
    "check_dongle": false,
    "tests_to_conduct": [
      {
        "threshold": 80,
        "type": "audiofun",
        "volume_gain": 1,
        "min_frequency": 500,
        "max_frequency": 1000
      }
    ]
  }
}

To run Audiofuntest on internal mics and speaker channel 0:

{
  "pytest_name": "audio_loop",
  "label": "Speaker (Only Channel 0)/Microphone",
  "related_components": [
    "test_tags.TestCategory.AUDIOCODEC",
    "test_tags.TestCategory.SMART_SPEAKER_AMPLIFIER",
    "test_tags.TestCategory.SPEAKERAMPLIFIER"
  ],
  "args": {
    "input_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Dmic"
    ],
    "output_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Speaker"
    ],
    "mic_source": "Dmic",
    "require_dongle": false,
    "check_dongle": true,
    "tests_to_conduct": [
      {
        "threshold": 80,
        "type": "audiofun",
        "output_channels": [
          0
        ],
        "volume_gain": 1,
        "min_frequency": 500,
        "max_frequency": 1000
      }
    ]
  }
}

To run noise test on internal mics and speaker:

{
  "pytest_name": "audio_loop",
  "label": "Speaker/Microphone Noise Test",
  "related_components": [
    "test_tags.TestCategory.AUDIOCODEC",
    "test_tags.TestCategory.SMART_SPEAKER_AMPLIFIER",
    "test_tags.TestCategory.SPEAKERAMPLIFIER"
  ],
  "args": {
    "input_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Dmic"
    ],
    "output_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Speaker"
    ],
    "mic_source": "Dmic",
    "require_dongle": false,
    "check_dongle": true,
    "tests_to_conduct": [
      {
        "duration": 2,
        "amplitude_threshold": [
          -0.9,
          0.9
        ],
        "type": "noise",
        "rms_threshold": [
          null,
          0.5
        ]
      }
    ]
  }
}

To run sine wave test on internal mics and speaker:

{
  "pytest_name": "audio_loop",
  "label": "Speaker/Microphone Sine Wave Test",
  "related_components": [
    "test_tags.TestCategory.AUDIOCODEC",
    "test_tags.TestCategory.SMART_SPEAKER_AMPLIFIER",
    "test_tags.TestCategory.SPEAKERAMPLIFIER"
  ],
  "args": {
    "input_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Dmic"
    ],
    "output_dev": [
      "eval! device.component.audio_card_name or constants.audio.card_name",
      "Speaker"
    ],
    "mic_source": "Dmic",
    "require_dongle": false,
    "check_dongle": true,
    "tests_to_conduct": [
      {
        "freq_threshold": 300,
        "type": "sinewav",
        "rms_threshold": [
          0.08,
          null
        ]
      }
    ]
  }
}

Test Arguments

Name

Type

Description

audio_conf

str, None

(optional; default: None) Audio config file path

initial_actions

list, None

(optional; default: None) List of [card, actions]. If actions is None, the Initialize method will be invoked.

input_dev

list

(optional; default: ['0', '0']) Input ALSA device. [card_name, sub_device]. For example: [“audio_card”, “0”]. The sub_device could be a string of an integer or one of [‘Dmic’, ‘Dmic2’, ‘MLBDmic’, ‘Extmic’].If this argument is a string of an integer then it represents the PCM Id. Otherwise the test will find the PCM Id from UCM config using this argument as the keyword.

num_input_channels

int

(optional; default: 2) Number of input channels.

output_dev

list

(optional; default: ['0', '0']) Output ALSA device. [card_name, sub_device]. For example: [“audio_card”, “0”]. The sub_device could be a string of an integer or one of [‘Speaker’, ‘Headphone’].If this argument is a string of an integer then it represents the PCM Id. Otherwise the test will find the PCM Id from UCM config using this argument as the keyword.

num_output_channels

int

(optional; default: 2) Number of output channels.

output_volume

int, list, None

(optional; default: None) An int of output volume or a list of output volume candidates

autostart

bool

(optional; default: False) Auto start option

require_dongle

bool

(optional; default: False) Require dongle option

check_dongle

bool

(optional; default: False) Check dongle status whether match require_dongle

check_cras

bool

(optional; default: True) Do we need to check if CRAS is running

cras_enabled

bool

(optional; default: True) Whether cras should be running or not

mic_source

[‘Dmic’, ‘Dmic2’, ‘Extmic’, ‘MLBDmic’]

(optional; default: <InputDevices.Extmic: 'Extmic'>) Microphone source

test_title

str

(optional; default: '') Title on the test screen.It can be used to tell operators the test infoFor example: “LRGM Mic”, “LRMG Mic”

mic_jack_type

str

(optional; default: 'nocheck') Microphone jack Type: nocheck, lrgm, lrmg

audiofuntest_run_delay

int, float, None

(optional; default: None) Delay between consecutive calls to audiofuntest

input_rate

int

(optional; default: 48000) The input sample rate for audio test. The value should be determined by input device.

output_rate

int

(optional; default: 48000) The output sample rate for audio test. The value should be determined by output device.

check_conformance

bool

(optional; default: True) Check conformance or not.

conformance_rate_criteria

float

(optional; default: 0.1) The pass criteria of rate. The value is a percentage of rate. See more detail in alsa_conformance.go.

conformance_rate_err_criteria

int

(optional; default: 100) The pass criteria of rate error. See more detail in alsa_conformance.go.

tests_to_conduct

list

A list of dicts. A dict should contain at least one key named type indicating the test type, which can be audiofun, sinewav, or noise.

If type is audiofun, the dict can optionally contain:
  • iteration: Iterations to run the test.

  • threshold: The minimum success rate to pass the test.

  • input_channels: A list of input channels to be tested.

  • output_channels: A list of output channels to be tested.

  • volume_gain: The volume gain set to audiofuntest for

    controlling the volume of generated audio frames. The range is from 0 to 100.

  • input_gain: The volume gain for sox recorder command.

    The value should be in “dB”, you can see the value suggested by CRAS with command cras_test_client –dump_server_info, check the “Gain” column. - sample_format: The sample format for audiofuntest. See -t section in audiofuntest manual.

  • player_format: The sample format for output device.

  • min_frequency: The minimum frequency set to audiofuntest.

  • max_frequency: The maximum frequency set to audiofuntest.

  • frequency_sample_strategy: One of serial, low_hi_uniform, random, pure_random, step, or low_hi_uni_rand_variation. See audiofuntest -h for explanations.
    • low_hi_uniform is an alias of serial

    • pure_random is an alias of random

    • low_hi_uni_rand_variation is an alias of step

If type is sinewav, the dict can optionally contain:
  • duration: The test duration, in seconds.

  • input_channels: A list of input channels to be tested.

  • freq_threshold: Acceptable frequency margin.

  • rms_threshold: [min, max] that will make

    sure the following inequality is true: min <= recorded audio RMS (root mean square) value <= max, otherwise, fail the test. Both of min and max can be set to None, which means no limit.

  • amplitude_threshold: [min, max] and it will

    make sure the inequality is true: min <= minimum measured amplitude <= maximum measured amplitude <= max, otherwise, fail the test. Both of min and max can be set to None, which means no limit.

  • max_delta_threshold: [min, max] and it will

    make sure the inequality is true: min <= maximum measured delta <= max, otherwise, fail the test. Both of min and max can be set to None, which means no limit.

If type is noise, the dict can optionally contain:
  • duration: The test duration, in seconds.

  • rms_threshold: [min, max] that will make

    sure the following inequality is true: min <= recorded audio RMS (root mean square) value <= max, otherwise, fail the test. Both of min and max can be set to None, which means no limit.

  • amplitude_threshold: [min, max] and it will

    make sure the inequality is true: min <= minimum measured amplitude <= maximum measured amplitude <= max, otherwise, fail the test. Both of min and max can be set to None, which means no limit. - max_delta_threshold: [min, max] and it will make sure the inequality is true: min <= maximum measured delta <= max, otherwise, fail the test. Both of min and max can be set to None, which means no limit.

keep_raw_logs

bool

(optional; default: True) Whether to attach the audio by Testlog when the test fail.