fix(nests): G4+G5 plumb catalog sampleRate through decoder + AudioTrack
G4: Audit-9 (catalog-driven decoder reconfig) plumbed numberOfChannels
end-to-end but left sampleRate hardcoded at AudioFormat.SAMPLE_RATE_HZ
in MediaCodecOpusDecoder.buildOpusIdHeader / buildFormat and in
AudioTrackPlayer's MinBufferSize / 250 ms target / setSampleRate
calls. For Opus this is benign in practice — Codec2 always emits
48 kHz PCM regardless of OpusHead inputSampleRate — but hardcoding
the constant means a future codec or container variant whose
decoder DOES respect input sample rate would mis-clock playback.
And the OpusHead identification header should match what the
catalog declares either way.
Thread sampleRate alongside channelCount through every layer:
- MediaCodecOpusDecoder constructor takes
`sampleRate: Int = AudioFormat.SAMPLE_RATE_HZ`. buildFormat
and buildOpusIdHeader both take it as a parameter.
- AudioTrackPlayer constructor takes the same. Used in
AudioTrack.getMinBufferSize, the 250 ms-equivalent target
bytes calculation (`(sampleRate / 4) * BYTES_PER_SAMPLE *
channelCount`), AndroidAudioFormat.Builder.setSampleRate, and
the diagnostic log.
- decoderFactory and playerFactory in NestViewModel become
`(channelCount: Int, sampleRate: Int) -> ...`.
- awaitDecoderChannelCount → awaitAudioPipelineConfig, returning
a private `AudioPipelineConfig(channelCount, sampleRate)`
struct so openSubscription handles both fields uniformly.
`sampleRate` falls back to AudioFormat.SAMPLE_RATE_HZ on
timeout / non-positive declaration with a warning log.
- NestViewModelFactory + NestViewModelTest updated to the
two-arg factory shape.
G5: documented the SUBSCRIBE_BUFFER safety budget on
CATALOG_AWAIT_TIMEOUT_MS's kdoc. With the current 500 ms timeout +
SUBSCRIBE_BUFFER = 64-frame DROP_OLDEST flow + 50 fps Opus, at
most 25 frames buffer during the wait — leaving ≥ 39 frames of
margin (≈ 780 ms) before the oldest frame would be evicted. Even
at the production framesPerGroup = 50 (1 group/sec) cadence this
never trips during normal startup. No code change; just pinning
the rationale so a future timeout bump is checked against the
buffer size.
https://claude.ai/code/session_014JfZJHSTvyYYWJbC9VbB47
This commit is contained in:
+6
-2
@@ -53,8 +53,12 @@ internal class NestViewModelFactory(
|
||||
// `httpClient` slot rather than as the first positional arg.
|
||||
httpClient = OkHttpNestsClient(httpClient = Amethyst.instance.roleBasedHttpClientBuilder::okHttpClientForVideo),
|
||||
transport = QuicWebTransportFactory(),
|
||||
decoderFactory = { channelCount -> MediaCodecOpusDecoder(channelCount = channelCount) },
|
||||
playerFactory = { channelCount -> AudioTrackPlayer(channelCount = channelCount) },
|
||||
decoderFactory = { channelCount, sampleRate ->
|
||||
MediaCodecOpusDecoder(channelCount = channelCount, sampleRate = sampleRate)
|
||||
},
|
||||
playerFactory = { channelCount, sampleRate ->
|
||||
AudioTrackPlayer(channelCount = channelCount, sampleRate = sampleRate)
|
||||
},
|
||||
signer = signer,
|
||||
room = room,
|
||||
captureFactory = { AudioRecordCapture() },
|
||||
|
||||
Reference in New Issue
Block a user