class Graph

Defined at line 136 of file fidling/gen/sdk/fidl/fuchsia.audio.mixer/fuchsia.audio.mixer/cpp/fidl/fuchsia.audio.mixer/cpp/markers.h

A mixer Graph.

## Directed Acyclic Graphs (DAGs)

Each graph includes a set of nodes connected into one or more DAGs. Audio

data flows from Producer nodes to Consumer nodes, and in between, may flow

through processing nodes, including Mixers, Splitters, and Custom nodes.

Each node has zero or more incoming and outgoing edges. Each edge represents

a single stream of audio data. Incoming edges are called "source streams"

and outgoing edges are called "destination streams".

Audio is strongly typed: each node declares the audio format(s) it can

ingest from source streams and the audio format(s) it can produce to

destination streams. It is illegal to connect nodes with incompatible

formats.

## Execution Model

Execution is driven by Consumers. Each Consumer wakes every N ms (N is

configurable per Consumer) and pulls N ms of audio from its sources, which

pull audio from their sources, and so on, up to the connected Producers. As

audio is pulled down the graph, it is processed and mixed into a single

stream that is written into the Consumer.

Each Consumer is attached to a Thread, which gives the Consumer a place to

do its work. Threads usually need deadline profiles to meet real-time

constraints. The client is responsible for creating Thread objects,

assigning Consumers to Threads, and attaching appropriate deadline profiles

when needed.

When the DAG includes nodes with multiple outgoing edges, such as Splitters,

we can end up in a situation where two Consumers A and B share the same

dependencies (via the Splitter's source). If A and B run on different

threads, it's unclear which Thread should process those shared dependencies,

making it unclear how much deadline capacity is required by each thread. To

avoid this problem, we partition the DAG so that each Consumer is the root

of an inverted tree. At nodes with multiple outgoing edges, such as

Splitters, we partition the node into a hidden Consumer node (which drives

the sources) and hidden Producer nodes (which drive the destinations). When

the client creates a Splitter, they must assign a Thread to the Splitter's

hidden Consumer. This ensures that each node is processed on a unique

thread, making it simpler to analyze the needed capacity for each Thread.

## Method Semantics

Methods will be executed sequentially in the order they are called. Method

calls can be pipelined, but if more than an implementation-defined number of

requests are in flight at one time, the server reserves the right to assume

a DoS attack and close the connection.

Most methods use a minimal set of arguments plus an "options" table to allow

for extensibility.

## IDs and names

Every object is identified by a numeric `id`. Within each object type

(Nodes, Threads, and GainControls) IDs are guaranteed to be unique. Old IDs

for deleted objects will never be reused for new objects.

Every object has an optional string `name`. If specified, ideally this name

should be unique within the [`Graph`] and have a printable CamelCase format,

but uniqueness is not required. Names are used for developer-visible

diagnostics only -- they do not need to be unique. Duplicate names can at

worst lead to potentially-confusing diagnostics. IDs, not names, should be

used when unique identification is required.

## Clocks

Each audio stream is associated with a *reference clock*. Different streams

can use different clocks. Any two clocks can differ in both value (the

current time) and the rate, where the rate may [change over

time](https://fuchsia.dev/fuchsia-src/reference/syscalls/clock_update) as

long as the clock remains [continuous and

monotonic](https://fuchsia.dev/fuchsia-src/reference/kernel_objects/clock).

This reflects many real situations. For example, a speaker may have an

internal clock separate from the CPU's physical clock. Or, a stream may

originate from some other computer on the network whose clock is not

precisely synchronized to our local clock.

Every node must specify the reference clock used by the node's destination

streams, except for Consumers, which must specify a clock for the Consumer's

source stream. To connect two streams that use different clocks, we must

translate one stream onto the other stream's clock. This is done at Mixer

nodes, which use sample rate conversion (SRC) to translate source streams

onto the Mixer's destination reference clock.

Reference clocks can change rate over time. These rate changes are typically

controlled by the client. If the client doesn't need precise control over

reference clocks, a cheaper option is to use Graph-controlled clocks (see

[`Graph.CreateGraphControlledReferenceClock`]), which can avoid a

potentially-expensive SRC in many cases. For example, if a Producer flows to

a Consumer, where the Producer uses a Graph-controlled clock and the

Consumer uses a client-controlled clock, the `Graph` will adjust the

Producer clock's rate to synchronize the Producer and Consumer clocks,

eliminating the need for SRC.

Public Members

static Openness kOpenness

Records