| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library fuchsia.hardware.audio.signalprocessing; |
| |
| using zx; |
| |
| // TODO(fxbug.dev/64877): Complete parameters and types for processing elements. |
| |
| const MAX_COUNT_PROCESSING_ELEMENTS uint32 = 64; |
| const MAX_COUNT_TOPOLOGIES uint32 = 64; |
| const MAX_COUNT_PROCESSING_ELEMENTS_EDGE_PAIRS uint32 = 64; |
| const MAX_STRING_SIZE uint32 = 256; |
| |
| type ElementType = flexible enum { |
| /// Vendor Specific. A type of processing element not covered by any subsequent type definition. |
| VENDOR_SPECIFIC = 1; |
| |
| /// Define pipelines start/end. |
| END_POINT = 2; |
| |
| /// Controls pipelines channel mixing and routing. |
| CONNECTION_POINT = 3; |
| |
| /// Gain control, a.k.a. Volume control. |
| GAIN = 4; |
| |
| /// Automatic Gain Control. |
| /// Automatically maintains a suitable signal level regardless of variation of its input. |
| AUTOMATIC_GAIN_CONTROL = 5; |
| |
| /// Automatic Gain Limiter. |
| /// Automatically maintains a signal level below a level specified. |
| /// Input below the level is unaffected, and peaks above the level are attenuated. |
| AUTOMATIC_GAIN_LIMITER = 6; |
| |
| /// Alters the dynamic range of the signal, e.g. dynamic range compression. |
| DYNAMICS = 7; |
| |
| /// Mute. |
| MUTE = 8; |
| |
| /// Delay. |
| DELAY = 9; |
| |
| /// Equalizer. |
| EQUALIZER = 10; |
| |
| /// Sample Rate Conversion. |
| SAMPLE_RATE_CONVERSION = 11; |
| }; |
| |
| /// Type specific Parameters for an `Element`. |
| type TypeSpecificElement = flexible union { |
| // See vendor_specific.fidl. |
| 1: vendor_specific VendorSpecific; |
| |
| // See gain.fidl. |
| 2: gain Gain; |
| |
| // See equalizer.fidl. |
| 3: equalizer Equalizer; |
| |
| // See dynamics.fidl. |
| 4: dynamics Dynamics; |
| }; |
| |
| type Latency = flexible union { |
| /// Latency added to the pipeline as a zx.duration. |
| 1: latency_time zx.duration; |
| |
| /// Latency added to the pipeline as a number of frames. |
| 2: latency_frames uint32; |
| }; |
| |
| type Element = table { |
| /// Unique ID for this element. The scope of this id is only within the `SignalProcessing` |
| /// protocol lifespan, i.e. until the channel associated with the protocol is closed. |
| /// Required. |
| 1: id uint64; |
| |
| /// Processing element type. Required. |
| 2: type ElementType; |
| |
| /// If included, type specific parameters for the processing element. |
| 3: type_specific TypeSpecificElement; |
| |
| /// If included and true, the processing element can be disabled via |
| /// `ElementSetState`. |
| /// If not included or false, the processing element is always enabled. |
| 4: can_disable bool; |
| |
| /// If included, a textual description of the processing element. |
| 5: description string:MAX_STRING_SIZE; |
| }; |
| |
| /// Type specific processing element state. |
| /// The type of processing element control is defined by the type of parameters provided in this |
| /// union. Must match the type returned in the corresponding `ElementType` entry in the |
| /// corresponding `Element`. |
| type TypeSpecificElementState = flexible union { |
| // See vendor_specific.fidl. |
| 1: vendor_specific VendorSpecificState; |
| |
| // See gain.fidl. |
| 2: gain GainElementState; |
| |
| // See equalizer.fidl. |
| 3: equalizer EqualizerElementState; |
| |
| // See dynamics.fidl. |
| 4: dynamics DynamicsElementState; |
| }; |
| |
| type ElementState = table { |
| /// If included, type specific state parameters for the processing element. |
| /// |
| /// If this processing element is disabled and its type specific state is provided, then the |
| /// type specific state is only informational, for instance if a `SetElementState` enables a |
| /// disabled processing element providing a `TypeSpecificElementState`, then any previous |
| /// informational `TypeSpecificElementState` is superceded. |
| 1: type_specific TypeSpecificElementState; |
| |
| /// Process element enable/disable state. Optional. By default processing elements are enabled. |
| /// If the corresponding `Element` returned `can_disable` equals to `false`, then |
| /// this field can't be set to `false`. |
| /// If `enabled` is not included, then `state` must be included if and only if the processing |
| /// element is currently enabled. |
| 2: enabled bool; |
| |
| /// If included, how much latency is added to the pipeline if this processing element is |
| /// enabled. This field must not be present in a `SetElementState` `state` since |
| /// the latency can't be set by a client, it can only provided by the server in a |
| /// `WatchElementState` reply. |
| 3: latency Latency; |
| }; |
| |
| /// Edge pairs between processing elements used to define ordering in processing elements |
| /// arrangements. |
| type EdgePair = struct { |
| processing_element_id_from uint64; |
| processing_element_id_to uint64; |
| }; |
| |
| /// A `Topology` specifies one way processing elements are arranged within the hardware. |
| type Topology = table { |
| /// Unique ID for this topology. The scope of this id is only within the `SignalProcessing` |
| /// protocol lifespan, i.e. until the channel associated with the protocol is closed. |
| /// Required. |
| 1: id uint64; |
| |
| /// Vector of processing elements edge pairs in this order. |
| /// The ordering of processing elements with edge pairs form pipelines. |
| /// To define multiple possible pipelines, return more `Topology` entries in `GetTopologies`. |
| /// Required. |
| 2: processing_elements_edge_pairs vector<EdgePair>:MAX_COUNT_PROCESSING_ELEMENTS_EDGE_PAIRS; |
| }; |
| |
| /// For an overview see |
| /// [[Signal Processing Interface]](https://fuchsia.dev/fuchsia-src/concepts/drivers/driver_architectures/audio_drivers/audio_signal_processing). |
| protocol SignalProcessing { |
| /// Exposes read-only signal processing properties. |
| compose Reader; |
| |
| /// Controls a processing element using a unique id returned by `GetElements`. |
| /// Returns `ZX_ERR_INVALID_ARGS` if the `processing_element_id` does not match an id returned |
| /// by `GetElements` or the type of `TypeSpecificElementState` does not |
| /// match the `ElementType` of the processing element returned by |
| /// `GetElements` for this id. |
| /// The driver may return `ZX_ERR_INVALID_ARGS` if the `state` values are invalid, i.e. any |
| /// of the values violates rules specified in this protocol, e.g. trying to change an |
| /// `EQUALIZER` processing element's `EqualizerBandState` `frequency` when this processing |
| /// element did not advertise `CAN_CONTROL_FREQUENCY` in its `supported_controls`. |
| /// |
| /// `SetElementState` may be called before or after non-`SignalProcessing` protocol |
| /// calls. If called after non-`SignalProcessing` protocol calls then |
| /// `SetElementState` may or may not require renegotiation of the driver state as |
| /// reached with calls of the protocol composing `SignalProcessing`, e.g. `Dai`. |
| /// For instance, `SetElementState` changing an `AGL` processing element's parameters |
| /// may not require renegotiation of the `Dai` state because changing a gain parameter usually |
| /// does not change the set of supported audio formats. |
| /// By contrast, if `SetElementState` changes the parameters of a `CONNECTION_POINT` |
| /// element, the change may require renegotiation because it may invalidate the set of |
| /// supported formats returned in a previous `GetDaiFormats` `Dai` protocol call. |
| /// |
| /// It is the driver's job to determine when renegotiation is required. If renegotiation is |
| /// required, then `SetElementState` must return ZX_ERR_BAD_STATE and the client must |
| /// close the protocol channel such that the protocol negotiations are started over. |
| /// The client then must make the `SetElementState` call that returned |
| /// ZX_ERR_BAD_STATE before any non-`SignalProcessing` protocol calls. |
| SetElementState(struct { |
| processing_element_id uint64; |
| state ElementState; |
| }) -> (struct {}) error zx.status; |
| |
| /// Sets the topology to be used using an id to the vector returned by `GetTopologies`. |
| /// If `GetTopologies` returns more than one `Topology`, `SetTopology` must be called to put the |
| /// driver in an initialized state. If `GetTopologies` returns only one `Topology`, |
| /// `SetTopology` is optional and has no effect. |
| /// |
| /// `SetTopology` may be called before or after non-`SignalProcessing` protocol calls. |
| /// If called after non-`SignalProcessing` protocol calls, then `SetTopology` may return |
| /// ZX_ERR_BAD_STATE to indicate that the operation can not proceed without renegotiation of the |
| /// driver state. See `SetElementState` for further discussion. |
| SetTopology(struct { |
| topology_id uint64; |
| }) -> (struct {}) error zx.status; |
| }; |
| |
| /// For an overview see |
| /// [[Signal Processing Interface]](https://fuchsia.dev/fuchsia-src/concepts/drivers/driver_architectures/audio_drivers/audio_signal_processing). |
| protocol Reader { |
| /// Returns a vector of supported processing elements. |
| /// Must return one or more processing elements, or ZX_ERR_NOT_SUPORTED. |
| GetElements() -> (struct { |
| processing_elements vector<Element>:MAX_COUNT_PROCESSING_ELEMENTS; |
| }) error zx.status; |
| |
| /// Get the processing element state via a hanging get. For a given `processing_element_id`, |
| /// the driver will reply to the first `WatchElement` sent by the client. |
| /// The driver will not respond to subsequent client `WatchElement` calls for a |
| /// given `processing_element_id` until any field of the `Element` table |
| /// changes from what was most recently reported for that `processing_element_id`. |
| WatchElementState(struct { |
| processing_element_id uint64; |
| }) -> (struct { |
| state ElementState; |
| }); |
| |
| /// Returns a vector of supported topologies. |
| /// Must return one or more topologies, or ZX_ERR_NOT_SUPORTED. |
| /// If more than one topology is returned, then the client may choose any of the topologies from |
| /// the list with `SetTopology`. |
| /// If only one topology is returned, then the topology definition is informational only since |
| /// the one and only topology used can't be changed with `SetTopology`. |
| /// If `GetElements` returns one or more elements, `GetTopologies` must return one or |
| /// more topologies. |
| GetTopologies() -> (struct { |
| topologies vector<Topology>:MAX_COUNT_TOPOLOGIES; |
| }) error zx.status; |
| }; |