Two conventional channels share one mono audio stream — simultaneous traffic is mislabelled/mixed #26

Open
opened 2026-10-04 15:54:10 -04:00 by logan · 0 comments
Owner

Found 2026-10-04 by drb-audio-review on the node-26#24 branch (feat/24-p25-conventional). Not fixed there.

What happens. When a node decodes two P25 conventional channels (e.g. White Plains PD1 460.400 + PD3 460.425), OP25 sends channel A's audio to UDP 23456 and channel B's to 23457. audio.py -2 then puts them on L/R, and Liquidsoap mixes them down to ONE mono PulseAudio stream (mean(input)). The recorder has one stream, so when both channels are keyed at once:

  • If B's grant arrives during A's call, _handle_grant forces a split. Everything after it, A's speech included, is labelled B, and A never gets a new grant to split back (one call_log per call).
  • If B keys with no grant (voice only), nothing splits (len(channels) != 1 guard), so B's speech is filed under A.
  • sockaudio writes A-only and B-only frames as separate PCM writes, so simultaneous traffic may also run faster than realtime or be choppy. This is unverified without hardware.

Impact. Mislabelled or mixed recordings, which feed the wrong channel's words into correlation. This only happens while both channels are keyed at once (e.g. dispatch talking while units are on tac). A single channel is unaffected.

Fix shape. Give each conventional channel its own capture path: two Pulse sinks, or one per-channel recorder keyed by receiver. Or, at minimum, flag a call that overlapped activity on the other channel (overlap_channels in the call_end payload) so C2 can down-weight it. Needs drb-audio-review.

Linked: DEFERRED.md entry (op25 two-channel mixdown), node-26#24.

Found 2026-10-04 by drb-audio-review on the node-26#24 branch (feat/24-p25-conventional). Not fixed there. **What happens.** When a node decodes two P25 conventional channels (e.g. White Plains PD1 460.400 + PD3 460.425), OP25 sends channel A's audio to UDP 23456 and channel B's to 23457. `audio.py -2` then puts them on L/R, and Liquidsoap mixes them down to ONE mono PulseAudio stream (`mean(input)`). The recorder has one stream, so when **both channels are keyed at once**: - If B's grant arrives during A's call, `_handle_grant` forces a split. Everything after it, A's speech included, is labelled B, and A never gets a new grant to split back (one call_log per call). - If B keys with no grant (voice only), nothing splits (`len(channels) != 1` guard), so B's speech is filed under A. - sockaudio writes A-only and B-only frames as separate PCM writes, so simultaneous traffic may also run faster than realtime or be choppy. This is unverified without hardware. **Impact.** Mislabelled or mixed recordings, which feed the wrong channel's words into correlation. This only happens while both channels are keyed at once (e.g. dispatch talking while units are on tac). A single channel is unaffected. **Fix shape.** Give each conventional channel its own capture path: two Pulse sinks, or one per-channel recorder keyed by receiver. Or, at minimum, flag a call that overlapped activity on the other channel (`overlap_channels` in the call_end payload) so C2 can down-weight it. Needs drb-audio-review. Linked: DEFERRED.md entry (op25 two-channel mixdown), node-26#24.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logan/node-26#26