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