blob: d3b4a0da2b4c95c5359f0ee485b8ddd2a9fe797e [file] [log] [blame]
// 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(https://fxbug.dev/42143529): Complete parameters and types for processing elements.
alias ElementId = uint64;
alias TopologyId = uint64;
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;
@available(added=HEAD)
const MAX_BYTES_ELEMENT_VENDOR_SPECIFIC uint32 = 4096;
type ElementType = flexible enum {
/// Vendor Specific. A type of processing element not covered by any subsequent type definition.
VENDOR_SPECIFIC = 1;
/// The start/end of a pipeline.
@available(removed=12)
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;
/// The start/end of a pipeline.
@available(added=12)
ENDPOINT = 12;
};
/// 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;
// See endpoint.fidl.
@available(added=12)
5: endpoint Endpoint;
};
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 ElementId;
/// Processing element type.
///
/// Required.
2: type ElementType;
/// If included, type-specific parameters for the processing element.
///
/// Optional.
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.
///
/// Optional.
///
/// # Deprecation
///
/// Use `can_bypass` instead.
@available(deprecated=20)
4: can_disable bool;
/// If included, a textual description of the processing element.
///
/// Optional.
5: description string:MAX_STRING_SIZE;
/// If included and true, the processing element can be stopped via `ElementSetState`.
/// If not included or false, the processing element is always started.
///
/// Optional.
@available(added=20)
6: can_stop bool;
/// If included and true, the processing element can be bypassed via `ElementSetState`.
/// If not included or false, the processing element cannot be bypassed.
///
/// Optional.
@available(added=20)
7: can_bypass bool;
};
/// 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;
// See endpoint.fidl.
@available(added=12)
5: endpoint EndpointElementState;
};
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.
///
/// Optional.
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.
///
/// Optional.
///
/// # Deprecation
///
/// Use `bypassed` instead.
@available(deprecated=20)
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.
///
/// Optional.
3: latency Latency;
/// If included, an opaque object of octets for exchanging vendor specific information.
///
/// Optional.
@available(added=HEAD)
4: vendor_specific_data vector<uint8>:MAX_BYTES_ELEMENT_VENDOR_SPECIFIC;
/// The started/stopped state for this processing element.
/// If true, the hardware associated with the element is started. If false, stopped.
///
/// By default processing elements are started.
/// If the corresponding `Element` returned `can_stop` equals to `false`, then
/// this field can't be set to `false`.
///
/// A stopped processing element does not provide its abstracted functionality.
/// Specifically, no audio data flows through a stopped element.
///
/// Required.
@available(added=20)
5: started bool;
/// The bypassed state for this processing element.
/// If true, the hardware associated with the element is bypassed. If false, not bypassed.
///
/// By default processing elements are not bypassed.
/// If the corresponding `Element` returned `can_bypass` equals to `false`, then
/// this field can't be set to `true`.
///
/// A bypassed element does not affect the flow of audio through the topology.
///
/// Optional.
@available(added=20)
6: bypassed bool;
/// If included, the driver's best estimate of the amount of time (in nanoseconds) it takes
/// the element hardware to get into fully operational mode after `started` has changed from
/// false to true.
///
/// This field should not be present in a `SetElementState` `state` since the `turn_on_delay`
/// can't be set by a client. It may be provided by the server in a `WatchElementState` reply.
///
/// It may take some time for the hardware to get into fully operational mode, for example due
/// a power state change. This delay must be taken into account if not getting the initial audio
/// samples played or captured is not acceptable.
/// If not included `turn_on_delay` is unknown.
///
/// Optional.
@available(added=20)
7: turn_on_delay zx.Duration;
/// If included, the driver's best estimate of the amount of time (in nanoseconds) it takes
/// the element hardware to get into fully disabled mode after the `ElementState` has
/// changed `started` from true to false.
///
/// This field should not be present in a `SetElementState` `state` since the `turn_off_delay`
/// can't be set by a client. It may be provided by the server in a `WatchElementState` reply.
///
/// It may take some time for the hardware to get into fully disabled mode, for example due to
/// a power state change. This delay must be taken into account if audio processing of audio
/// samples after disabling a processing element is not acceptable.
/// If not included, the turn off delay is unknown.
///
/// Optional.
@available(added=20)
8: turn_off_delay zx.Duration;
};
/// Edge pairs between processing elements used to define ordering in processing elements
/// arrangements.
type EdgePair = struct {
processing_element_id_from ElementId;
processing_element_id_to ElementId;
};
/// 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 TopologyId;
/// 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).
closed 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.
strict SetElementState(struct {
processing_element_id ElementId;
state ElementState;
}) -> () error zx.Status;
/// Sets the topology to be used using an id to the vector returned by `GetTopologies`.
/// The current topology is communicated by `WatchTopology` responses. To change which topology
/// is active, a client uses `SetTopology`.
/// If the specified `topology_id` is not within the`topologies` returned by `GetTopologies`,
/// this call will return `ZX_ERR_INVALID_ARGS`.
/// 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.
strict SetTopology(struct {
topology_id TopologyId;
}) -> () error zx.Status;
};
/// For an overview see
/// [[Signal Processing Interface]](https://fuchsia.dev/fuchsia-src/concepts/drivers/driver_architectures/audio_drivers/audio_signal_processing).
closed protocol Reader {
/// Returns a vector of supported processing elements.
/// Must return one or more processing elements, or `ZX_ERR_NOT_SUPPORTED`.
strict 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 `WatchElementState` sent by the client.
/// The driver will not respond to subsequent client `WatchElementState` 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`.
/// The driver will close the protocol channel with an error of `ZX_ERR_BAD_STATE`, if this
/// method is called again while there is already a pending `WatchElementState` for this client
/// and processing_element_id.
strict WatchElementState(struct {
processing_element_id ElementId;
}) -> (struct {
state ElementState;
});
/// Returns a vector of supported topologies.
/// Must return one or more topologies, or `ZX_ERR_NOT_SUPPORTED`.
/// 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.
strict GetTopologies() -> (struct {
topologies vector<Topology>:MAX_COUNT_TOPOLOGIES;
}) error zx.Status;
/// Get the current topology via a hanging get.
/// The driver will immediately reply to the first `WatchTopology` sent by each client. The
/// driver will not respond to subsequent `WatchTopology` calls from that client until the
/// signal-processing topology changes, which occurs as a result of a `SetTopology` call.
/// The driver will close the protocol channel with an error of `ZX_ERR_BAD_STATE`, if this
/// method is called again while there is already a pending `WatchTopology` for this client.
@available(added=HEAD)
strict WatchTopology() -> (struct {
topology_id TopologyId;
});
};