OpenJOC production architecture¶
This is the canonical description of the current production data flow. It describes implemented boundaries, not a promise that every historical design goal is complete.
OpenJOC implements its spatial rendering DSP directly rather than delegating object rendering to platform-specific spatial audio engines. Operating-system audio APIs may be used for integration and I/O, but they do not define OpenJOC's spatial rendering result. One renderer. Same spatial semantics across platforms.
The CLI, GStreamer plugin, and external FFmpeg bridge are transport frontends
over the same OpenJocSession; they do not contain separate render pipelines.
GStreamer owns its buffer/caps/segment lifecycle. The FFmpeg bridge uses
libavformat for demux and public libavutil AVFrame allocation. In both cases
OpenJOC retains E-AC-3/JOC decode, scene construction, DRC/dialnorm, speaker
rendering, binaural HRTF rendering, latency, and drain state.
Data flow¶
The explicit render-scene workflow is implemented in openjoc-render-scene.
It depends on openjoc-render, openjoc-sofa, and openjoc-wave; it is
deliberately separate from openjoc-scene, so decoder metadata and
ReconstructionBasis rows cannot enter the caller-bound source contract.
raw EC-3 / seekable ISO BMFF
│
▼
input/container ownership and access-unit delivery
│
├── E-AC-3 base decode ──► channel-labelled PCM / RcLfe
│
└── EMDF payloads
├── OAMD ──► metadata objects and timed state
└── JOC ──► reconstruction-basis rows
├──► codec-domain JOC bridge
│ (T(t) remains unresolved)
│
└──► exact clean binding gate
│
▼
bound decoded JOC Objects
│
▼
reconstructed dynamic ADM
The binding branch is deliberately narrower than the decoder and renderer branches. OAMD supplies decoded dynamic metadata; JOC supplies decoded object audio rows. Only the exact admitted carrier profile pairs them. Other scene consumers still receive metadata and decoder-coordinate rows without an automatic authored-object interpretation.
The reconstructed ADM branch establishes decoded-scene and ADM structural correctness within that profile. It does not recover the authored Atmos master or prove perceptual equivalence with a native JOC final renderer; native JOC playback remains the reference for renderer-identical localization.
The render-joc workflow adds an explicit experimental speaker branch after
the decoded component boundary:
raw EC-3 / seekable ISO BMFF
↓
bounded AU delivery → E-AC-3 Base + RcLfe + JOC/OAMD decode
↓
decoded Base/RB codec-coordinate bundle + automatic bridge-control assembly
↓
persistent JocSpatialBridge → active N-channel speaker planes
├── Base LFE/RcLfe → LFE plane only
└── active planes + LFE → shared final linked speaker gain
↓
incremental semantic WAV/CAF output
The CLI presets are data-only registrations over the generic SpatialLayout
and JocSpatialBridge projection path. The public library can consume a
caller-defined channel registry, geometry, and output order without a
preset-specific projection algorithm; the CLI accepts the same versioned
geometry through --layout-file.
The 22.2 preset is ITU-R BS.2051-3 Sound System H (9+10+3): a four-layer
bottom/middle/upper/top topology with 22 spatial speakers and two semantic
LFE destinations. It uses the same N-layer point projector and semantic
operation boundaries as the established layouts; LFE channels are never
projection vertices.
Automatic assembly derives codec-coordinate control from validated OAMD and
decoded Base/RB state. A complete sidecar is optional and takes precedence as
an explicit override/test source; automatic and explicit sources are not
implicitly merged. Topology/count, coordinate dimensions, metadata updates,
and Base topology changes are validated at the integration boundary; no
guessed row/object renderer is constructed. The public semantic PCM order is
selected by the explicit preset; exact speaker WAV masks remain backend
specific. 5.1 remains FL, FR, FC, LFE, Ls, Rs.
The parser reads what is present in the carrier. Validation then applies an explicit profile. The decoder consumes an accepted representation; it does not hide vendor compatibility decisions.
Layer boundaries¶
Input and container¶
Raw E-AC-3 uses the in-process incremental reader. Ordinary seekable ISO BMFF uses a sample cursor with container ownership kept separate from the AU consumer. Non-seekable and fragmented MP4 are outside the current contract.
E-AC-3 base¶
The base decoder keeps frame, audio-block, coupling, SPX, AHT, rematrix,
substream and TDAC state explicit. Channel labels and RcLfe are retained as
base-carried information; RcLfe is not a dynamic reconstruction row.
OAMD and profiles¶
OAMD metadata is parsed into typed state and timed updates. ETSI_STRICT
enforces the published validation rules. OBSERVED_VENDOR_COMPAT is explicit and
partial: it preserves original metadata and records deviations, but does not
assign meaning to unresolved vendor continuation.
User-facing decode and decode-payload commands expose a separate AUTO
selection policy. It parses once, evaluates strict validation first, and uses
the existing compatibility policy only when every blocking deviation is
already whitelisted. Malformed, unsafe, unknown, and non-whitelisted failures
remain failures. Selection diagnostics include the requested and selected
profiles, strict status, deviation set, and reason. AUTO is not a parser or
renderer profile; explicit ETSI_STRICT never falls back, while normative
inspection remains strict by purpose.
The observed OAMD warp_mode value raw=3 remains reserved under ETSI strict
parsing. The exact observed compatibility profile preserves raw3 as opaque and
may use the decoded OAMD spatial metadata directly for the tested scene scope;
no production alias, transform, offset, or trim guess is present.
Scene and binding¶
ObjectScene retains metadata objects, timed positions, and decoder-coordinate
rows as separate domains. For the exact admitted decoded-JOC/OAMD profile,
SemanticBindingState::ResolvedWithinCarrier records a carrier-local pairing
for the reconstructed ADM path. For all other profiles it remains
Unresolved; there is no implicit row == authored object, slot identity, or
dominant-row fallback.
JOC ReconstructionBasis¶
JOC reconstruction produces rows with structural indices and deterministic
numerical behavior. The rows remain decoder coordinates and are not authored-
object PCM. In the exact admitted carrier profile, a row also has a scoped
decoded JOC Object interpretation for the dynamic ADM path; that does not
turn it into an authored stem. Diagnostic WAV export uses
diagnostics/reconstruction_rows/row_NNN.wav.
The stable component boundary uses ReconstructionBasisRowIndex as a local
decoder-coordinate identity. DecodedComponentLayout and the CLI
diagnostics/components.json manifest distinguish Base full-band channels,
separate Base LFE, indexed RB rows, and SemanticBindingState::Unresolved
or its admitted carrier-local counterpart without retaining another PCM copy.
Operations requiring authored-object audio
identity fail explicitly even when decoded-object binding is admitted;
component-domain decode and streaming remain available.
JOC spatial reconstruction bridge¶
openjoc-scene exposes JocSpatialFrameBridge and the versioned
openjoc.joc-spatial-reconstruction.v1 codec-domain contract. A borrowed
CodecBasisBlock carries explicitly labelled Base full-band PCM, indexed
ReconstructionBasis rows, and separate RcLfe; JocSpatialMetadataFrame carries
the current OAMD payload and structural programme dimensions; and
SampleRange gives each committed decoder frame an absolute half-open sample
interval. The bridge is streaming and retains no duration-proportional PCM.
The semantic operation is modelled as o(t) = T(t)c(t) followed by the
independent renderer operator. T(t) is not known: JocSpatialOperatorState
therefore remains Unresolved, and require_resolved_operator() is a hard
gate. There is no automatic conversion from decoded components to
ExplicitSpatialScene. The scoped decoded-object binding resolves only the
carrier-local association between decoded JOC row j and decoded OAMD dynamic
ordinal j for reconstructed ADM; it does not resolve T(t), a
speaker-rendering operator, or an authored source identity. There is no fixed
RB-row/authored-object mapping and no implicit matrix or permutation. The
readiness census remains a repository artifact and is available as
docs/joc_reconstruction_readiness.json.
The explicitly activated JocSpatialBridge is a downstream spatial function
with experimental maturity. It consumes a losslessly retained topology/
coordinate snapshot, projects into a caller-supplied public layout, applies the
Q32 gain scheduler, and accumulates linearly into caller-owned buffers. It does
not change profile validation, assign authored-object identity, or resolve
SemanticBindingState for authored or renderer semantics; its raw warp-3 field
is retained as opaque data and excluded from projection arithmetic. The
supported ordinary domain and activation surface remain an experimental
implementation boundary. The E-AC-3 JOC overview shows
how this branch relates to reconstructed ADM export.
After Base and ReconstructionBasis contributions have been accumulated into the final semantic speaker planes, the shared renderer applies a causal, common FinalLinkedGain stage for the admitted 48-kHz 32-sample adapter blocks. It includes active LFE in the linked channel set, adds one block of speaker output history, and is reset with the stream/timeline lifecycle. The stage is not applied to the SOFA binaural path; Base downmix overload protection and pre-gain contribution linearity remain separate contracts.
Base full-band scene-composition gate¶
Decoded non-LFE Base/full-band channels are known JOC reconstruction inputs.
That fact is separate from whether an independent Base contribution survives
into the final JOC delivery scene. The experimental bridge may accumulate Base
coordinates and ReconstructionBasis rows together, but that codec-basis
composition is not proof of the final-scene equation while T(t) remains
unresolved. In particular, strong energy in decoded Base C is not evidence that
Base C should be exported a second time, and the original authored Bed is not
used to explain or authorize that export. Base-plus-Objects must pass an
explicit double-counting proof before ADM scene composition changes.
Explicit spatial renderer¶
The openjoc-render crate is a separate Layer-A/Layer-B foundation. It accepts
only caller-supplied ExplicitSpatialSource blocks with an opaque source ID,
mono PCM, explicit Cartesian position, and explicit linear gain. Its initial
renderer maps the front horizontal hemisphere to FL, FR with a public
equal-power law and mixes borrowed blocks into caller-owned floating-point
buffers. It has no dependency on openjoc-scene, DecodedJocComponents, or
ReconstructionBasis, so unresolved decoder rows cannot become authored
spatial sources through an implicit conversion.
The initial StereoRenderer rejects rear-hemisphere and undefined horizontal
directions, ignores elevation for stereo, performs no distance/room/occlusion
processing, and does not clip by default. SpeakerLayout2d and
LayoutRenderer2d add arbitrary validated horizontal layouts with deterministic
adjacent-pair, checked 2x2 VBAP-style gains. The caller's speaker order is the
public planar output order; unsupported angular gaps fail explicitly. The 2D
renderer ignores elevation and has no LFE/bass-management path. The separate
binaural renderer and experimental JOC spatial bridge do not change this 2D
contract or provide automatic JOC semantic binding.
SpatialState2d, TrajectorySegment2d, and SourceTrajectory2d add an
explicit, piecewise-linear automation contract. Segment endpoints are inclusive
absolute sample indices; azimuth follows an explicit shortest/increasing/
decreasing path policy and source gain is interpolated linearly in the linear
domain. StereoRenderer::render_trajectory_block and
LayoutRenderer2d::render_trajectory_block evaluate that state per sample, so
one block, irregular blocks, and one-sample blocks have the same result for the
same absolute timeline. Trajectory blocks borrow PCM and caller-owned output
planes, perform bounded preflight validation, and allocate neither per sample
nor for the full timeline. The trajectory is directional only: radius, z,
distance, Doppler, room effects, elevation, and HRTF are not rendered.
Speaker3d, SpeakerTriplet3d, and SpeakerLayout3d add an explicit
three-dimensional topology contract. The caller supplies the public speaker
order and every admissible VBAP triplet; LayoutRenderer3d never performs
Delaunay, hull, coverage, or “best triplet” inference. Each declared triplet
is solved as the public 3×3 system S g = p, with finite/non-singular checks,
non-negative gain checks, and unit-energy normalization. Exact speaker hits
are deterministic one-hot gains. If multiple declared triplets cover a
direction, their complete public-order gain vectors must agree or rendering
fails with an ambiguity error. Partial layouts fail explicitly for unsupported
directions, and LFE/bass management remains outside this renderer contract.
The 3D renderer accepts only explicit sources and caller-owned planar f64
outputs. SpatialState3d, TrajectorySegment3d, SourceTrajectory3d, and
TrajectorySourceBlock3d add an additive sample-accurate dynamic path over
that same immutable topology. Each segment uses shortest great-circle SLERP
between canonical unit directions, a stable small-angle branch, linear gain
interpolation, and explicit rejection of antipodal ambiguity. Callers supply
intermediate keyframes for longer routes; no path inference is performed.
LayoutRenderer3d::render_trajectory_block evaluates absolute sample indices
and preserves static output equivalence, endpoint/keyframe continuity, and
byte-identical block-partition invariance. It preflights every sample before
clearing caller-owned planar f64 outputs and performs no per-sample heap
allocation. Distance, Doppler, listener orientation, room effects, LFE,
HRTF/binaural rendering, JOC, ObjectScene, and authored-object bridges remain
outside the contract.
HrirPair, HrirEntry, and HrirBank provide a compact caller-supplied
exact-direction HRIR contract, with optional explicit per-ear delay metadata
retained for construction-time interpolation. StaticBinauralSource binds a
fixed explicit source ID, canonical direction, linear gain, and HRIR entry; it
does not infer authored-object identity. BinauralRenderer uses the fixed
listener convention (+Y forward, +X right, +Z up), emits LEFT_EAR then
RIGHT_EAR, and performs direct causal time-domain FIR convolution. It
preserves leading HRIR delay, keeps bounded per-source history across
caller-owned input blocks, and exposes explicit tail draining and reset
semantics. openjoc-sofa resolves exact directions first and performs bounded
delay-aligned spherical interpolation before registering static sources.
PartitionedBinauralRenderer is an additive,
caller-selected uniform overlap-add backend: its fixed power-of-two partition
P uses a 2P FFT, reports one-partition scheduling latency, accepts exactly
P-sample input partitions plus one explicit final partial operation, and
drains exactly the largest registered M-1 causal tail. It precomputes HRIR
spectra and keeps only bounded filter-length frequency/time state; no
duration-proportional PCM history or adaptive backend selection is used.
Direct FIR remains the numerical oracle, so cross-backend validation is
numerical rather than a promise of bit identity.
The separate openjoc-sofa crate is a construction-time, read-only adapter
from a deliberately narrow SimpleFreeFieldHRIR SOFA contract into
HrirBank. It depends on openjoc-render; the renderer remains independent
of file parsing, NetCDF/HDF5 libraries, and OS-specific APIs. The current
portable reader accepts the project-tested NetCDF classic CDF-1 subset, fixed
listener pose, spherical degree/degree/metre source positions, exactly two
receivers, common sample rate, and integer sample delays. Receiver geometry,
not array order, determines left/right ear mapping. Exact lookup is preferred;
non-exact requests use a deterministic local spherical segment/triangle with
shared ear weights, while sparse/outside coverage fails closed. After
construction no SOFA file handle is retained and neither renderer performs
file I/O per audio block. HDF5/NetCDF-4 remains outside the portable runtime
reader; the bundled SADIE II resource is converted offline to the same CDF-1
path and needs no network access at render time. Resampling, moving sources,
SOFA writing, and any JOC semantic bridge remain outside this boundary.
Capture and streaming¶
Capture mode may retain metadata and diagnostic artifacts. Streaming mode uses bounded AU/frame state and incremental output finalization; it does not silently capture an unbounded ObjectScene or reconstruction-row vector. Malformed or truncated raw E-AC-3 and consumed ISO BMFF structures are rejected with bounded diagnostics; streaming output is staged and promoted only after a complete successful decode, so failure cannot publish a canonical partial.
Scoped decoded-JOC/OAMD binding¶
The payload boundary has one explicit clean-room structural admission gate for
the ordinary strict profile and the exact observed raw3-compatible profile: 15
decoded JOC objects, no OAMD bed, one Base LFE at total index 0, no ISF, 15
dynamic OAMD objects, and 16 total OAMD entries. Only after this gate passes
does the canonical typed mapping produce joc_ordinal = dynamic_ordinal and
oamd_total_index = joc_ordinal + 1.
The +1 is centralized in DecodedJocBindingProfile; it is not an element-ID
lookup, audio-content match, or PCM heuristic.
SemanticBindingState::ResolvedWithinCarrier means only that decoded JOC PCM
and decoded OAMD metadata are paired inside this admitted carrier profile. It
does not recover original authored ADM identity. Bed-bearing, ISF-bearing,
alternative-LFE, count/order-mismatched, unknown-compatibility-deviation, and
incomplete-Base-LFE cases remain unresolved; inactive transitions are not
admitted by the dynamic ADM metadata exporter.
The dynamic ADM path reuses the existing absolute scene sample domain. It
retains metadata events for the export plan but never duplicates programme PCM:
each generated OpenJOC Reconstructed JOC Object NN track consumes its bound
reconstruction row during the existing bounded streaming write, while its ADM
blocks are derived from the corresponding OAMD event boundaries. Reset,
discontinuity, flush, and stream reopen create a fresh decoder/scene epoch;
stale metadata and PCM are not combined.
Error and evidence model¶
Malformed input, unsupported container shapes, strict profile violations and output failures are classified separately. A diagnostic or empirical result cannot upgrade semantic binding. Current claim boundaries are summarized in the capability matrix and known limitations.