feat(audio): channel sample_rate caps Opus bandwidth (narrowband/wideband)
The per-channel sample_rate field was inert after pinning the codec to 48 kHz. Make it meaningful without changing the 48 kHz clock: carry it as OpusParams::max_bandwidth_hz and apply OPUS_SET_MAX_BANDWIDTH in OpusEncoder::init (8000->narrowband, 16000->wideband, 24000->super-wideband, 48000->full). A low-bitrate room can now shed out-of-band content while every endpoint keeps a single 48 kHz clock. Make sample_rate channel-authoritative on the server: conn_session no longer overrides effective sample_rate with the client's always-48000 request (it now behaves like frame_ms/mode). vc_get_stream_audio_config reports the channel's configured rate for own streams too. New ctest channel_samplerate: a 7 kHz tone is attenuated ~1000x on an 8 kHz (narrowband) channel vs a 48 kHz (full-band) channel, proving the cap is in effect. ctest --preset dev 26/26. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -531,21 +531,20 @@ void ConnSession::handle_stream_announce(uint64_t req_id,
|
||||
res->set_ssrc(ssrc);
|
||||
|
||||
// Per-channel AudioConfig is authoritative (docs/voice.md §3): the channel's mode/
|
||||
// frame_ms/application/fec/dtx/complexity/expected_packet_loss apply to every stream
|
||||
// announced into it, regardless of kind. bitrate_bps is clamped (not overridden) to the
|
||||
// channel's ceiling so a client may still request less. sample_rate stays
|
||||
// client-requested-or-48000 — everything runs at 48kHz internally per voice.md §3.
|
||||
// sample_rate/frame_ms/application/fec/dtx/complexity/expected_packet_loss apply to every
|
||||
// stream announced into it, regardless of kind. bitrate_bps is clamped (not overridden) to
|
||||
// the channel's ceiling so a client may still request less. sample_rate is taken from the
|
||||
// channel verbatim (copied via *eff below) — the codec always runs at 48kHz internally, but
|
||||
// a sub-48k value caps the encoder's audio bandwidth (narrowband/wideband; see
|
||||
// OpusEncoder::init), so it's a channel policy, not a client choice.
|
||||
auto* eff = res->mutable_effective_audio();
|
||||
auto chan_cfg = registry_->channel_audio_config(registry_->user_channel(user_id_.load()));
|
||||
uint32_t requested_bps =
|
||||
msg.has_requested_audio() ? msg.requested_audio().bitrate_bps() : 0;
|
||||
uint32_t requested_rate =
|
||||
msg.has_requested_audio() ? msg.requested_audio().sample_rate() : 0;
|
||||
if (chan_cfg) {
|
||||
*eff = *chan_cfg;
|
||||
eff->set_bitrate_bps(requested_bps > 0 ? std::min(requested_bps, chan_cfg->bitrate_bps())
|
||||
: chan_cfg->bitrate_bps());
|
||||
eff->set_sample_rate(requested_rate > 0 ? requested_rate : 48000);
|
||||
} else if (msg.has_requested_audio()) {
|
||||
*eff = msg.requested_audio();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user