services/pipewire: meter nodes whose channels have no position - #1147
Open
GrantAbell wants to merge 1 commit into
Open
GrantAbell wants to merge 1 commit into
GrantAbell wants to merge 1 commit into
Conversation
PwPeakStream matched each capture stream channel to the node's channel list by position to look up its volume, and dropped the buffer when any lookup failed. A node without speaker positions, such as an ALSA device on a pro-audio profile (AUX0, AUX1, ...), never matches the FL/FR layout the stream negotiates, so PwNodePeakMonitor.peak stayed at zero for it and a critical error was logged for every buffer. Pipewire's channelmix has no positions to mix by in that case and pairs channels by index (pair_mix in channelmix-ops.c), so match volumes by index too when the counts agree, and use the mean volume when they do not. Log the mismatch once, at debug level.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
PwPeakStream::start()connects a capture stream to the node asking onlyfor F32; it does not request channel positions.
handleProcess()wants to divide each stream channel's peak by thatchannel's volume, so the meter shows the pre-fader level. To find the
volume it looks each stream position (FL, FR) up in the node's channel
list (
audioData->channels()).positions). Nothing matches,
volumes.length() != channelCount, and thefunction logged qCCritical and returned. No peak was ever published, and
the log line repeated for every buffer.
Changes
PipeWire's channel mixer, spa/plugins/audioconvert/channelmix-ops.c,
make_matrix(): when either side has no known positions(
src_mask == 0 || dst_mask == 0) and both sides have more than one channel,it calls
pair_mix(), which is the identity matrix: input channel i goes tooutput channel i. So stream channel i carries node channel i's audio, and node
volume i is the right divisor. AUX positions (>= 0x1000) never set a mask bit,
which is what makes the mask zero. If the node is mono it is distributed to
every stream channel, and if the stream is mono it gets the average of the
node's channels; the mean volume is the right compensation there, hence the
second branch.
handleProcess(): on a mismatch, use the node's volumes by index when thecounts agree, otherwise the mean volume; then carry on and publish the peak.
critical line per buffer.
warnedChannelMismatchis reset inresetFormat().Verification
Fix verified via pw-loopback source pinned to
audio.position=[AUX0 AUX1]with a clipplayed into it. Stock /usr/bin/quickshell 0.3.1: 199 "missing channels"
errors in 5 s, peak stays 0. This build: 0 errors, peaks reported, with the
node still on [4096, 4097] and the stream on [3, 4] (FL, FR), so the index
fallback is what did the work.