| // 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; |
| |
| /// 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]. |
| /// |
| /// ## Args |
| /// |
| /// * `num_frames` the number of frames to process |
| /// * `options` extra options |
| /// * error a zx.status value indicating success or failure |
| Process(struct { |
| num_frames uint64; |
| options ProcessOptions; |
| }) -> (struct {}) 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; |
| }; |
| |
| /// 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 input stream. Must provide read access and must have |
| /// enough space for `ProcessorConfiguration.max_frames_per_call`. |
| /// |
| /// 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; |
| }; |