| // 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.audio.effects; |
| |
| using fuchsia.mediastreams; |
| using fuchsia.mem; |
| using zx; |
| |
| /// The maximum number of input and output streams. |
| /// These bounds are somewhat arbitrary; in practice we don't expect more than 1 |
| /// or 2 inputs and outputs in the vast majority of cases. |
| const MAX_INPUT_STREAMS uint32 = 8; |
| const MAX_OUTPUT_STREAMS uint32 = 8; |
| |
| /// The maximum size of the per_stage_metrics array. |
| const MAX_PROCESS_STAGES uint32 = 8; |
| |
| /// The maximum length of the name of a process stage. |
| const MAX_PROCESS_STAGE_NAME_LENGTH uint32 = 64; |
| |
| /// An audio effect processor. Consumes one or more input streams, producing one |
| /// or more output streams. On creation, this protocol must be tied to a |
| /// [`fuchsia.audio.effects.Processor/ProcessorConfiguration`], which defines |
| /// the processor's input and output streams. |
| protocol Processor { |
| /// Processes the given number of frames. This will consume `num_frames` from |
| /// each `ProcessorConfiguration.inputs[i]` and produce an equivalent number of |
| /// frames in each `ProcessorConfiguration.outputs[i]`. |
| /// |
| /// ## Execution model |
| /// |
| /// All inputs and outputs must have identical frame rates. This simplifies |
| /// the problem of matching input and output frames, as described below. |
| /// |
| /// At each call to `Process`, the effect collects audio from a set of input buffers |
| /// and produces a set of output buffers. The input buffers should be aligned by |
| /// time. That means: the first frame in each input buffer, input[i].buffer[0], |
| /// should have the same presentation time as all other frames input[j].buffer[0]. |
| /// |
| /// Output buffers with non-zero latency may be shifted relative to input buffers. |
| /// For each output k, input frame 0 has the same presentation time as the frame at |
| /// output[k].buffer[output[k].latency_frames]. |
| /// |
| /// + request `num_frames` The number of frames to process. |
| /// + request `options` Extra options. |
| /// - response `per_stage_metrics `Metrics about this process call, possibly |
| /// subdivided into multiple stages. |
| /// * error A zx.status value indicating success or failure. |
| Process(struct { |
| num_frames uint64; |
| options ProcessOptions; |
| }) -> (struct { |
| per_stage_metrics vector<ProcessMetrics>:MAX_PROCESS_STAGES; |
| }) error zx.status; |
| }; |
| |
| /// An extensible container of options for Processor.Process. |
| type ProcessOptions = table { |
| /// The total gain that has been applied to each input stream by prior |
| /// processing steps. For example, given an audio pipeline of the form input -> |
| /// ProcessorA -> ProcessorB, if input is a sine wave with unity amplitude and |
| /// ProcessorA applies a gain of -5.0dB, then ProcessorB should be called with |
| /// total_applied_gain_db_per_input[0] = -5.0dB and ProcessorB's input buffer |
| /// should contain a sine wave with amplitude -5.0dB. |
| /// |
| /// If not specified, the applied gain is 0 dB for each input. |
| 1: total_applied_gain_db_per_input vector<float32>:MAX_INPUT_STREAMS; |
| |
| /// All fuchsia.media.AudioRenderUsages that contribute to each input |
| /// stream. This is a bitmask of (1 << r), for each AudioRenderUsage that |
| /// contributes. For example, if an input stream contains BACKGROUND (== 0) |
| /// and INTERRUPTION (== 2), the bitmask is ((1<<0)|(1<<2)) = 0x5. |
| /// |
| /// Note: this field may be removed once we have transitions to the new |
| /// Fuchsia media APIs. |
| 2: usage_mask_per_input vector<uint32>:MAX_INPUT_STREAMS; |
| }; |
| |
| /// An extensible container of metrics about a single Processor.Process call. |
| /// All fields are optional. |
| type ProcessMetrics = table { |
| /// Each process call may be (optionally) divided into multiple stages, |
| /// each with their own ProcessMetrics. This field names the stage described |
| /// by this table. |
| 1: name string:MAX_PROCESS_STAGE_NAME_LENGTH; |
| |
| /// Total wall-clock time from the moment the Process call is received to |
| /// the moment a response is returned. |
| 2: wall_time zx.duration; |
| |
| /// Total amount of time spent running on the CPU. |
| /// See zx_info_task_runtime.cpu_time. |
| 3: cpu_time zx.duration; |
| |
| /// Total amount of time spent waiting to run. Only counts "ready" time. |
| /// See zx_info_task_runtime.queue_time. |
| 4: queue_time zx.duration; |
| |
| /// Total amount of time spent handling page faults. |
| /// See zx_info_task_runtime.page_fault_time. |
| 5: page_fault_time zx.duration; |
| |
| /// Total amount of time spent waiting on contended kernel locks. |
| /// See zx_info_task_runtime.lock_contention_time. |
| 6: kernel_lock_contention_time zx.duration; |
| }; |
| |
| /// Configures a Processor. |
| type ProcessorConfiguration = resource table { |
| /// Dedicated FIDL channel for this processor. |
| /// Required. |
| 1: processor client_end:Processor; |
| |
| /// A description of all input streams for this processor. |
| /// Must have at least one input. |
| /// |
| /// Each input stream can have a different sample format or channel count, but |
| /// all inputs must have the same frame rate. |
| 2: inputs vector<InputConfiguration>:MAX_INPUT_STREAMS; |
| |
| /// A description of all output streams for this processor. |
| /// Must have at least one output. |
| /// |
| /// Each output stream can have a different sample format or channel count, |
| /// but all outputs must have the same frame rate as the input(s) -- effects |
| /// are allowed to perform sample format conversion and rechannelization as |
| /// long as the frame rate does not change. |
| 3: outputs vector<OutputConfiguration>:MAX_OUTPUT_STREAMS; |
| |
| /// The maximum number of frames that may be processed per call to |
| /// [`fuchsia.audio.effects/Processor.Process`]. The default limit is the |
| /// number of frames that can fit in the smallest input buffer. If specified, |
| /// this must be smaller than the default limit. |
| 4: max_frames_per_call uint64; |
| |
| /// If specified, all calls to [`fuchsia.audio.effects/Processor.Process`]. |
| /// must set `num_frames` to a multiple of this number. Must be less than or |
| /// equal to `max_frames_per_call`. If not specified, then any block size is |
| /// allowed. |
| 5: block_size_frames uint64; |
| }; |
| |
| /// Configures a single input stream. |
| type InputConfiguration = resource table { |
| /// Format of this input stream. |
| /// Required. |
| 1: format fuchsia.mediastreams.AudioFormat; |
| |
| /// Buffer for this input stream. Must provide write access and must have |
| /// enough space for `ProcessorConfiguration.max_frames_per_call`. |
| /// |
| /// Required. |
| 2: buffer fuchsia.mem.Range; |
| }; |
| |
| /// Configures a single output stream. |
| type OutputConfiguration = resource table { |
| /// Format of this output stream. |
| /// Required. |
| 1: format fuchsia.mediastreams.AudioFormat; |
| |
| /// Buffer for this output stream. Must provide write access and must have |
| /// enough space for `ProcessorConfiguration.max_frames_per_call`. |
| /// Write access is needed so the audio system can write to the output |
| /// buffer in error cases, such as when the Processor disconnects. |
| /// |
| /// If the effect supports in-place updates, this may refer to the same memory |
| /// range as an input buffer. |
| /// |
| /// Required. |
| 2: buffer fuchsia.mem.Range; |
| |
| /// If specified, the output signal is shifted by this many frames. |
| /// If not specified, this is zero. |
| /// See the explanation at `[fuchsia.audio.effects/Processor.Process]`. |
| 3: latency_frames uint64; |
| |
| /// If specified, then input frame F will affect the output stream up through |
| /// frame F + `ring_out_frames`. If not specified, this is zero. |
| /// |
| /// Put differently, if the effect is given an input stream with N non-silent |
| /// frames followed by infinite silence, the effect will produce up to N + |
| /// `ring_out_frames` non-silent frames before emitting silence. |
| 4: ring_out_frames uint64; |
| }; |