Skip to content

Refine KHR_audio_graph spec and schemas - #2572

Open
rudybear wants to merge 46 commits into
KhronosGroup:mainfrom
facebook:codex/update-khr-audio-graph-only
Open

Refine KHR_audio_graph spec and schemas#2572
rudybear wants to merge 46 commits into
KhronosGroup:mainfrom
facebook:codex/update-khr-audio-graph-only

Conversation

@rudybear

Copy link
Copy Markdown

Summary

  • refactor KHR_audio_graph around document-level graphs with explicit inputs, outputs, and node schemas
  • remove the older graph-owned emitter/listener/audioData model in favor of the updated schema layout
  • keep this PR scoped to KHR_audio_graph only

Validation

  • python3 -m json.tool on all KHR_audio_graph/schema/*.json files

Context

robertlong and others added 30 commits March 31, 2022 15:39
Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
Co-authored-by: Aaron Franke <arnfranke@yahoo.com>
factors in KHR PR feedback and fixes readme
Clarify spec details in KHR_audio and add property summary tables
Rename from KHR_audio to KHR_audio_emitter and add example file
merge KHR_audio branch (omigroup repo) to facebook repo for glTF.
utuere and others added 16 commits November 27, 2024 19:20
# Proposed Spec Text Updates (Phase 2)

This file contains suggested text blocks to paste into `extensions/2.0/Khronos/KHR_audio_graph/README.md`.

General — Units & Mapping
- Add to an early “Conventions” section:
  "Unless specified otherwise, times are expressed in milliseconds (ms). When mapping to Web Audio API, timing values are converted to seconds (s), e.g. `delayTime(ms)` → `DelayNode.delayTime(s)`."

Source Node (4.1) — Mapping Note
- “Web Audio Mapping: This node maps to an `AudioBufferSourceNode`. `playbackSpeed` corresponds to `playbackRate`. `loopStart` and `loopEnd` map to `loopStart`/`loopEnd` (seconds). `when` uses seconds and passes to `start(when, offset, duration)` after ms→s conversion for `offset`/`duration`.”

Oscillator Data (4.3) — PWM Clarification
- “Mapping: `OscillatorNode`. If `type = square` and `pulseWidth` is provided, implement as a static PWM using `PeriodicWave`. PWM modulation is out of scope.”

Gain (6.1) — Smoothing
- “Mapping: `GainNode`. Optional smoothing may be expressed with `interpolation: 'linear'|'custom'` and `duration (ms)`. Linear smoothing uses linear ramp; ‘custom’ can be approximated with `setTargetAtTime`.”

Delay (6.2)
- “Mapping: `DelayNode` with `delayTime` in seconds. Convert ms→s.”

Filters (6.8.x)
- “Mapping: `BiquadFilterNode` with corresponding `type`. `frequency` (Hz ≥ 0), `qualityFactor` maps to `Q` (≥ 0), `gain` (dB). Optional `bypass` may be supported via build-time routing or runtime dry/wet crossfade.”

Reverb (6.9) — IR-based
- “Mapping: IR-based reverb via `ConvolverNode`. The effect’s overall wet/dry ratio is implemented by summing dry and wet paths with respective gains. Algorithmic reverb parameters (room size, reflectivity, etc.) are out of scope for the IR-based mapping and may be considered for a future optional node.”

Panning
- “Mapping: `StereoPannerNode` for pan control and `PannerNode` for 3D spatialization. `spatializationModel` maps to `panningModel`; attenuation maps to `distanceModel`, `refDistance`, `maxDistance`, `rolloffFactor`, `cone*`.”

Emitter (5.1)
- “Implemented as a gain stage with optional spatialization using `PannerNode`. A single scene listener is assumed; listener details are outside the scope of this runtime but remain part of the specification.”

Pitch Shifter (6.3) — Deferred
- “This node is deferred from initial scope due to lack of a stock Web Audio node. It can be realized via custom DSP/Worklet in future revisions.”

Bypass (Implementation Note)
- “For processors, an optional `bypass: boolean` may be honored by either: (1) build-time routing (rewire around the node), or (2) runtime dry/wet crossfade wrapper. Both approaches are viable; exact behavior may be implementation-defined.”

Channel Interpretation (Implementation Note)
- “Where supported by Web Audio (`AudioNode.channelInterpretation`), an optional `channelInterpretation: 'speakers'|'discrete'` may be provided to refine mixing behavior. Not all nodes or runtimes support this property.”
@CLAassistant

CLAassistant commented Apr 22, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
3 out of 6 committers have signed the CLA.

✅ aaronfranke
✅ robertlong
✅ antpb
❌ Chintan Shah
❌ rudybear
❌ utuere


Chintan Shah seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@rudybear

rudybear commented Aug 4, 2026

Copy link
Copy Markdown
Author

Self-review after building this spec end-to-end (Web Audio reference runtime with full test coverage, plus a WebGPU viewer integration) and benchmarking against Web Audio 1.0/1.1 and the X3D 4.0 Sound component. Items I intend to address in the next revision — posting publicly for visibility:

Spec bugs

  1. custom oscillator type has no data model — add periodicWave { real[], imag[] } (Web Audio/X3D PeriodicWave) or drop custom from the enum until defined. Same treatment needed for the custom gain-interpolation curve and the waveshaper amount→curve mapping (currently implementation-defined).
  2. The bundled KHR_audio_emitter copy is stale vs KHR_audio_emitter #2137 (singular emitter in the node schema/prose vs the plural emitters array adopted upstream in April). Plan: drop the vendored copy and depend on KHR_audio_emitter #2137 directly.

Design items
3. Add a compressor node (Web Audio/X3D DynamicsCompressor params). It is the only roster gap vs both benchmark standards, and the workhorse for mastering/ducking.
4. Feedback cycles: currently DAG-only, which forbids feedback-delay topologies. Web Audio permits cycles when every cycle contains a DelayNode (≥1 render quantum). Leaning toward adopting that rule; validators can check it.
5. Extended source properties placement: loopStart/loopEnd/offset/when/duration/priority are playback semantics, not graph semantics — they likely belong in the base layer (or a small playback extension), and playbackRate currently exists in both layers. state as a mutable string pointer needs normative transitions or replacement with interactivity verbs (see the playable-asset experiment linked from #2561). Needs joint resolution with #2137.
6. Define the playback clock: when is seconds from an undefined origin. USD's stage-time anchoring is the precedent worth following (schedule relative to a glTF animation timeline).

Decisions to document (so review doesn't re-litigate them): no audio-rate parameter connections (reserve a to: {node, param} connection form for future use), no envelopes (gain smoothing is the mechanism), graphs are pre-spatialization (master-bus inserts belong to the environment layer), and implicit fan-in mixing follows Web Audio rules with speakers interpretation.

Also: the reference implementation's schema-validation CI now validates against this PR's schemas directly (fixtures modernized from the pre-refactor model). Full gap analysis: https://github.com/rudybear/KHR_audio_proposals/blob/feature/environment-v2/analysis/2026-08-session/03-gap-analysis-audio-graph.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants