xref: /aosp_15_r20/external/autotest/client/cros/chameleon/audio_level.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Copyright 2015 The Chromium OS Authors. All rights reserved.
2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be
3*9c5db199SXin Li# found in the LICENSE file.
4*9c5db199SXin Li
5*9c5db199SXin Li
6*9c5db199SXin Li"""This module provides the level control for audio widgets."""
7*9c5db199SXin Li
8*9c5db199SXin Li
9*9c5db199SXin Lifrom autotest_lib.client.cros.chameleon import chameleon_audio_ids as ids
10*9c5db199SXin Li
11*9c5db199SXin Li
12*9c5db199SXin Liclass _AudioLevel(object):
13*9c5db199SXin Li    """Audio signal level on audio widgets."""
14*9c5db199SXin Li    # Line level signal on consumer equipment is typically -10 dBV, or
15*9c5db199SXin Li    # 0.316 Volt RMS.
16*9c5db199SXin Li    LINE_LEVEL = 'Line level'
17*9c5db199SXin Li    # Mic level signal on microphone is typically -60 dBV, or
18*9c5db199SXin Li    # 1 mV RMS.
19*9c5db199SXin Li    MIC_LEVEL = 'Mic level'
20*9c5db199SXin Li    # Digital signal, e.g., USB, HDMI. is not subjected to bias level or
21*9c5db199SXin Li    # full swing constraints. The signal is guranteed to be transmitted to the
22*9c5db199SXin Li    # other end without noise introduced on the path.
23*9c5db199SXin Li    # Signal level is relative to full swing of data width.
24*9c5db199SXin Li    # E.g. 2^12 is 1/8 of maximum amplitude, that is, 2^15 - 1, of signed
25*9c5db199SXin Li    # 16 bit data format.
26*9c5db199SXin Li    # TODO(cychiang) Check if we need to do level scaling for digital signal.
27*9c5db199SXin Li    DIGITAL = 'Digital'
28*9c5db199SXin Li    # The signal level of input of bluetooth module on the audio board is
29*9c5db199SXin Li    # slightly higher than mic level.
30*9c5db199SXin Li    BLUETOOTH_SIGNAL_INPUT_LEVEL = 'Bluetooth signal input level'
31*9c5db199SXin Li
32*9c5db199SXin Li
33*9c5db199SXin Li# The relative level of audio levels. This is used to compute scale between
34*9c5db199SXin Li# two levels.
35*9c5db199SXin Li_RELATIVE_LEVEL = {
36*9c5db199SXin Li    _AudioLevel.LINE_LEVEL: 1.0,
37*9c5db199SXin Li    _AudioLevel.MIC_LEVEL: 0.033,
38*9c5db199SXin Li    _AudioLevel.BLUETOOTH_SIGNAL_INPUT_LEVEL: 0.05,
39*9c5db199SXin Li}
40*9c5db199SXin Li
41*9c5db199SXin Li_SOURCE_LEVEL_TABLE = {
42*9c5db199SXin Li        ids.ChameleonIds.LINEOUT: _AudioLevel.LINE_LEVEL,
43*9c5db199SXin Li        ids.ChameleonIds.USBOUT: _AudioLevel.DIGITAL,
44*9c5db199SXin Li        ids.CrosIds.HDMI: _AudioLevel.DIGITAL,
45*9c5db199SXin Li        ids.CrosIds.HEADPHONE: _AudioLevel.LINE_LEVEL,
46*9c5db199SXin Li        ids.CrosIds.SPEAKER: _AudioLevel.LINE_LEVEL,
47*9c5db199SXin Li        ids.CrosIds.BLUETOOTH_HEADPHONE: _AudioLevel.DIGITAL,
48*9c5db199SXin Li        ids.CrosIds.USBOUT: _AudioLevel.DIGITAL,
49*9c5db199SXin Li        ids.PeripheralIds.MIC: _AudioLevel.MIC_LEVEL,
50*9c5db199SXin Li        ids.PeripheralIds.BLUETOOTH_DATA_RX: _AudioLevel.LINE_LEVEL,
51*9c5db199SXin Li        ids.PeripheralIds.BLUETOOTH_DATA_TX: _AudioLevel.DIGITAL,
52*9c5db199SXin Li}
53*9c5db199SXin Li
54*9c5db199SXin Li_SINK_LEVEL_TABLE = {
55*9c5db199SXin Li        ids.ChameleonIds.HDMI: _AudioLevel.DIGITAL,
56*9c5db199SXin Li        ids.ChameleonIds.LINEIN: _AudioLevel.LINE_LEVEL,
57*9c5db199SXin Li        ids.ChameleonIds.USBIN: _AudioLevel.DIGITAL,
58*9c5db199SXin Li        ids.CrosIds.EXTERNAL_MIC: _AudioLevel.MIC_LEVEL,
59*9c5db199SXin Li        ids.CrosIds.INTERNAL_MIC: _AudioLevel.MIC_LEVEL,
60*9c5db199SXin Li        ids.CrosIds.BLUETOOTH_MIC: _AudioLevel.DIGITAL,
61*9c5db199SXin Li        ids.CrosIds.USBIN: _AudioLevel.DIGITAL,
62*9c5db199SXin Li        ids.PeripheralIds.SPEAKER: _AudioLevel.LINE_LEVEL,
63*9c5db199SXin Li        ids.PeripheralIds.BLUETOOTH_DATA_RX: _AudioLevel.DIGITAL,
64*9c5db199SXin Li        ids.PeripheralIds.BLUETOOTH_DATA_TX:
65*9c5db199SXin Li                _AudioLevel.BLUETOOTH_SIGNAL_INPUT_LEVEL,
66*9c5db199SXin Li}
67*9c5db199SXin Li
68*9c5db199SXin Li
69*9c5db199SXin Liclass LevelController(object):
70*9c5db199SXin Li    """The controller which sets scale between widgets of different levels."""
71*9c5db199SXin Li    def __init__(self, source, sink):
72*9c5db199SXin Li        """Initializes a LevelController.
73*9c5db199SXin Li
74*9c5db199SXin Li        @param source: An AudioWidget for source.
75*9c5db199SXin Li        @param sink: An AudioWidget for sink.
76*9c5db199SXin Li
77*9c5db199SXin Li        """
78*9c5db199SXin Li        self._source = source
79*9c5db199SXin Li        self._sink = sink
80*9c5db199SXin Li
81*9c5db199SXin Li
82*9c5db199SXin Li    def _get_needed_scale(self):
83*9c5db199SXin Li        """Gets the needed scale for _source and _sink to balance the level.
84*9c5db199SXin Li
85*9c5db199SXin Li        @returns: A number for scaling on source widget.
86*9c5db199SXin Li
87*9c5db199SXin Li        """
88*9c5db199SXin Li        source_level = _SOURCE_LEVEL_TABLE[self._source.port_id]
89*9c5db199SXin Li        sink_level = _SINK_LEVEL_TABLE[self._sink.port_id]
90*9c5db199SXin Li        if source_level == sink_level:
91*9c5db199SXin Li            return 1
92*9c5db199SXin Li        else:
93*9c5db199SXin Li            return _RELATIVE_LEVEL[sink_level] / _RELATIVE_LEVEL[source_level]
94*9c5db199SXin Li
95*9c5db199SXin Li
96*9c5db199SXin Li    def reset(self):
97*9c5db199SXin Li        """Resets scale of _source."""
98*9c5db199SXin Li        self._source.handler.scale = 1
99*9c5db199SXin Li
100*9c5db199SXin Li
101*9c5db199SXin Li    def set_scale(self):
102*9c5db199SXin Li        """Sets scale of _source to balance the level."""
103*9c5db199SXin Li        self._source.handler.scale = self._get_needed_scale()
104*9c5db199SXin Li        self._sink.handler.scale = 1
105