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
-
class BindProducerLeadTimeWatcher -
class CancelStartOrStop -
class CreateConsumer -
class CreateCustom -
class CreateEdge -
class CreateGainControl -
class CreateGraphControlledReferenceClock -
class CreateMixer -
class CreateProducer -
class CreateSplitter -
class CreateThread -
class DeleteEdge -
class DeleteGainControl -
class DeleteNode -
class DeleteThread -
class Start -
class Stop