Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions quest/m0/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ repository.
- [moq-video's browser backends are pinned](/quest/m0/pin-browser-video.md) - the web studio's video slice and browser composition
- [moq-audio's browser backends are pinned](/quest/m0/pin-browser-audio.md) - the web studio's audio slice
- [moq-audio's source tap is pinned](/quest/m0/pin-audio-tap.md) - the samples clap-to-measure sync times a clap from
- [Playout writes land on positioned bus channels](/quest/m0/playout-positioned.md) - broadcast, media, and replay sound at the bus position its pictures are timed for
- [moq-audio's positioned bus channel is pinned](/quest/m0/pin-bus-positioned.md) - `Bus::positioned`, which playout writes through

## Related

Expand Down
20 changes: 20 additions & 0 deletions quest/m0/pin-bus-positioned.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# [XS] moq-audio's positioned bus channel is pinned

## Goal

The `moq` submodule includes moq-audio's `Bus::positioned`, whose
`bus::Positioned::write(position, data)` plays a write at the bus position it
names, from [moq-dev/moq#8273](https://github.com/moq-dev/moq/pull/8273). That
PR also renamed `Bus::channel`/`bus::Channel` to `Bus::live`/`bus::Live`.

## Plan

Planned 2026-11-08 (maintainer, moq's /quest-complete), a follow-up of
moq-dev/moq#8273, which has merged on moq's `main`.

Advance it with `just upgrade-moq` in its own PR, fixing whatever the new API
breaks here: at least the `Bus::live` rename at every `bus.channel(..)` call.
If [moq-dev/moq#8272](https://github.com/moq-dev/moq/pull/8272) has landed by
then, `moq_mux::timeline` is `moq_mux::sync`, and `playout.rs` follows that
PR's migration notes too. Move no audio onto positioned writes here; that is
[Playout writes land on positioned bus channels](/quest/m0/playout-positioned.md).
54 changes: 54 additions & 0 deletions quest/m0/playout-positioned.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# [M] Playout writes land on positioned bus channels

## Goal

A broadcast, media, or replay source's sound plays at exactly the bus
position its pictures are timed for. `rs/moq-scene`'s playout writes it
through moq-audio's `Bus::positioned`, and its private copy of moq-audio's bus
latency (`BUS_LATENCY`) and of the live ring's pad rule are deleted.

Non-goals: the `Speaker`'s jitter targeting stays as it is, and live inputs
(microphones, capture, guests) stay on `Bus::live`.

## Plan

Planned 2026-11-08 (maintainer, moq's /quest-complete), a follow-up of
[moq-dev/moq#8273](https://github.com/moq-dev/moq/pull/8273), which added
`Bus::positioned` for this consumer.

Today `playout::Writer` writes into a live `bus::Channel` and keeps track of
when what it wrote runs out, padding silence ahead of a frame so it sounds a
copied 50 ms `BUS_LATENCY` later, the way moq-audio's ring would. Each source
that plays timed audio (`source.rs`'s broadcast, media, and replay paths)
goes through it.

Decided with the maintainer:

- ✅ **Studio maps an instant to a bus position** (rejected: an upstream
moq-audio bus clock). `Program::run_audio` (`rs/moq-studio/src/engine.rs`) already advances the bus
sample-exact on the program clock from `start`, so the position a frame
sounds at is `(sounds - start) * rate`. The writer gets the program clock's
`start` and the bus rate through the sources' `Context`. moq-audio's bus
counts frames and has no wall clock, so a clock there would guess timing
only the app knows.
- ✅ **A late frame is trimmed, not dropped** (rejected: drop the whole
frame). `Positioned::write` fails a write any part of which is already
mixed, overlaps earlier audio, or lands past `bus::REACH`. The writer cuts
the frames whose position has passed and writes the rest at its position,
as today's writer does with a late part.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved

Recommendations, not settled:

- Keep consecutive writes contiguous: a frame that starts within the
existing one-millisecond `CONTIGUOUS` stamp rounding of where the last one
ended is written at that end, since a one-frame overlap from rounding fails
the write.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
- A frame the writer holds earlier than `REACH` ahead waits until it is in
reach rather than failing.
- Test on the scene's driver-stepped bus, as `a_write_sounds_when_placed`
does: frames written ahead, late, and across a stall sound at the expected
bus positions, sample-exact.

## Required

- [moq-audio's positioned bus channel is pinned](/quest/m0/pin-bus-positioned.md) - `Bus::positioned`, which the writer writes through