PipeWire host: streams set no channel positions, so a stereo input on a mono source has a silent right channel
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 1-2 ngày
- Mức phù hợp với người mới
- 52/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- rust
- Lĩnh vực
- audio-video-rtc
Hướng nghiên cứu
Start with host/pipewire/stream.rs, especially connect_input and connect_output, where the issue says AudioInfoRaw is built without channel positions. Read how the stream format and properties are passed to PipeWire, then check host/pipewire/device.rs for the input_default channel count. Reproduce with a 2-channel stream on a mono source; done means both captured channels carry the source audio.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
The PipeWire host builds its streams' audio format (AudioInfoRaw in
connect_input and connect_output, host/pipewire/stream.rs) with a
format, a rate and a channel count, but no channel positions. A 2-channel
input stream on a mono source then shows two ports, input_FL and
input_FR, and the source's single capture_MONO port is linked to
input_FL only, with no channel mixing between them. The stream gets the
source in channel 0 and silence in channel 1, which halves the level for
anything that mixes the two down.
Two things make it easy to hit:
- The synthetic default input (
input_default) always reports 2 channels
(Device::input_default()inhost/pipewire/device.rshardcodes
channels: 2), whatever the default source has. Opening the default
input with its own default config on a mono microphone captures a silent
right channel. - When the default source changes, the stream on
input_defaultis moved
to the new source at the channel count it opened with, so the same
happens after a move from a stereo source to a mono one.
The PulseAudio host does not have this: PulseAudio (and pipewire-pulse)
remixes a 2-channel record stream from a mono source into both channels.
Environment
- cpal 0.18.2,
pipewirefeature - PipeWire 1.6.9, WirePlumber 0.5.18, Arch Linux
- Source: a Behringer FLOW 8's "Mic 1" input, a mono source
(pactl list sources shortshowsfloat32le 1ch 48000Hz)
Reproduction
Any mono source shows it; most USB microphones are mono. With such a
source set as the default (pactl set-default-source <name>):
// Cargo.toml: cpal = { version = "0.18.2", features = ["pipewire"] }
use cpal::traits::{DeviceTrait, HostTrait, StreamTrait};
use std::sync::{Arc, Mutex};
fn main() {
let host = cpal::host_from_id(cpal::HostId::PipeWire).expect("PipeWire host");
let device = host.default_input_device().expect("a default input");
let config = device.default_input_config().expect("a config");
println!("{} channels, {:?}", config.channels(), config.sample_format());
let mut config: cpal::StreamConfig = config.into();
config.channels = 2; // already 2 for `input_default`
let peaks = Arc::new(Mutex::new([0.0_f32; 2]));
let sink = Arc::clone(&peaks);
let stream = device
.build_input_stream(
config,
move |data: &[f32], _: &cpal::InputCallbackInfo| {
let mut peaks = sink.lock().unwrap();
for frame in data.chunks_exact(2) {
peaks[0] = peaks[0].max(frame[0].abs());
peaks[1] = peaks[1].max(frame[1].abs());
}
},
|error| eprintln!("{error}"),
None,
)
.expect("a stream");
stream.play().expect("playing");
std::thread::sleep(std::time::Duration::from_secs(2));
let [left, right] = *peaks.lock().unwrap();
println!("loudest: left {left}, right {right}");
}
(If the source captures i16 or another format, change the callback's
sample type to match.)
Speak into the microphone, or let it pick up the room. Expected: both
channels carry the microphone, as the PulseAudio host gives them. Actual:
the right channel is exactly 0.
Run on the FLOW 8 mic as the default source:
2 channels, F32
loudest: left 0.0027721382, right 0
and pw-link -l while it ran:
alsa_input.usb-Behringer_FLOW_8_D8-B6-73-B3-8C-44-00.Recording__Mic1__source:capture_MONO
|-> cpal-repro:input_FL
cpal-repro:input_FL
|<- alsa_input.usb-Behringer_FLOW_8_D8-B6-73-B3-8C-44-00.Recording__Mic1__source:capture_MONO
Nothing is linked to input_FR. Opening the mic's own node (not
input_default) at 2 channels gives the same: through fastframe-audio
0.12.0, which opens cpal streams the same way, left -53.9 dBFS and right
silence.
Suggested fix
We have not confirmed which change makes PipeWire mix, so these are
suggestions to try:
- set channel positions on the stream's format (for example FL/FR for 2
channels and MONO for 1), so the stream's adapter can convert between
its layout and the node's with its channel mixer, as it does for other
clients; - or set
audio.positionin the stream's properties.
Separately,
input_default could report the default source's real channel count
rather than 2, though with positions set that matters much less.
Until then, applications have to open each source at its own channel
count and remix themselves, and look up the default source's channels some
other way (fastframe asks PipeWire's PulseAudio server), and reopen the
stream when the default source changes.
- Ngôn ngữ chính
- Rust
- Star
- 4k
- Fork
- 554
- Merge trung bình
- 3 ngày 3 giờ
- Pull request đã merge (30 ngày)
- 4
Chuẩn bị môi trường
- Có Dockerfile hoặc tệp Docker Compose
- Không có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của RustAudio/cpal
-
aaudio: dynamic buffer tuning never grows the buffer (set_buffer_size_in_frames reports Err on success)Có thể đã có người làm @dannyward630 đã nhận 3 ngày trước. Đang mởhost - aaudio platform - android
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 79/100
Maintainer thường phản hồi trong vòng 1 ngày
-
WebAudio wasm build fails with wasm-bindgen panic=unwind closuresCó thể đã có người làm @bogusyogi đã nhận 11 ngày trước. Đang mởhost - webaudio platform - web
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
RustAudio/cpal#1394 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
New WASAPI implementationĐang mởcode quality dependencies host - wasapi platform - windows
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 35/100
RustAudio/cpal#1416 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
WASAPI: default-device activation fails with RPC_E_CHANGED_MODE after endpoint-notification callbacks put thread-pool threads into an STACó thể đã có người làm @dannyward630 đã nhận 4 ngày trước. Đang mởcorrectness host - wasapi platform - windows
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 20/100
RustAudio/cpal#1402 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
coreaudio (macOS): capture/playback timestamps double-count the buffer, loopback reads as −2 buffersCó thể đã có người làm @Marco-Farruggio đã nhận 14 ngày trước. Đang mởcorrectness host - coreaudio platform - macos
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 53/100
RustAudio/cpal#1398 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của RustAudio/cpal
Issue tương tự
-
needs triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
mozilla-services/syncstorage-rs#2715 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 70/100
-
documentation
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 82/100
physicsdolphin/nv-uefi-unlocker#53 · 4 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày