blob: f8c6582a07e39b57e2d64e98d389e54845d38540 [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.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.
closed 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.
strict 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;
};