rodio icon indicating copy to clipboard operation
rodio copied to clipboard

Spatial & Reverb dont work with ogg

Open mfluehr opened this issue 5 months ago • 13 comments

Examples that use ogg files still run, but no longer produce sound. Based on my testing, this problem seems to have been introduced in #753.

mfluehr avatar Jul 24 '25 14:07 mfluehr

Could you share a little more about your system? Since everything works on our systems.

yara-blue avatar Jul 24 '25 16:07 yara-blue

I'm running Arch Linux, EndeavourOS. My sound server is Pipewire.

I noticed that cargo r --example reverb prints out this message immediately: "Dropping OutputStream, audio playing through this stream will stop." If behaving as desired, it should instead play audio for a while, and then drop. If I use an mp3 instead of an ogg, the example works correctly.

mfluehr avatar Jul 24 '25 16:07 mfluehr

I can reproduce the reverb issue 👍

yara-blue avatar Jul 24 '25 18:07 yara-blue

Switching to the lewton decoder backend addresses it. We might need to make that the default again. It might be an issue similar to #769. As reverb uses buffered which needs the full duration.

Still strange that the music_ogg example does not work. @mfluehr Could you double check that cargo r --example music_ogg does not work?

yara-blue avatar Jul 24 '25 19:07 yara-blue

I'd like to have this issue dug a little deeper before switching defaults again. First, to understand. Second, because unlike MP3, Ogg Vorbis files should have their duration reliably determinable always. So reverb, buffered reads and total duration should all be fine even if they are not today.

roderickvd avatar Jul 24 '25 19:07 roderickvd

@dvdsk, I must've been a little sloppy when trying examples the first time. The only ones that seem broken are "reverb" and "spatial."

mfluehr avatar Jul 24 '25 19:07 mfluehr

@dvdsk, I must've been a little sloppy when trying examples the first time. The only ones that seem broken are "reverb" and "spatial."

no worries :)

Then I can reproduce it all locally :)

yara-blue avatar Jul 24 '25 19:07 yara-blue

Ah, I was banging my head trying rodio wondering why the sink stopped producing sounds whenever I added .buffered() or .repeat_infinite()...

I can confirm changing the backend (cargo add rodio --no-default-features --features lewton,playback) works around the issue.

Also, it's different from #769 in that .total_duration() returns a proper duration.. And actually with lewton it's not :)

This might help; printing this:

    let a = rodio::Decoder::try_from(file)?;
    println!("file duration {:?}", a.total_duration());
    let b = a.buffered();
    println!("buffered duration {:?}", b.total_duration());
    println!("sample rate {:?}", b.sample_rate());
    println!("channels {:?}", b.channels());
    println!("span len {:?}", b.current_span_len());

with lewton (buffered audio works)

file duration None
buffered duration None
sample rate 44100
channels 2
span len Some(256)

with default:

file duration Some(124.577777777s)
buffered duration Some(124.577777777s)
sample rate 44100
channels 1
span len Some(0)

I suspect span length being wrong is a problem?

Anyway, I'll just use lewton for now.

martinetd avatar Aug 06 '25 05:08 martinetd

Yes, clearly the span length. Thanks for that quick debugging.

Haven't gotten around to it yet, but my hunch is that the first chunk of Ogg data does not contain any samples, just metadata, and therefore our decoder mistakenly sets the span length to 0. And channels to 1! Instead, it should forward to the next chunk and start counting span length from there. Didn't check yet, just a hunch.

Side note: it should be possible to determine total_duration with lewton (or actually, ogg) also now that we've got the builder. We can find the last granule position for finite streams. Separate issue though.

roderickvd avatar Aug 06 '25 09:08 roderickvd

Hypothesis confirmed, I'll submit a PR soon.

roderickvd avatar Aug 08 '25 07:08 roderickvd

Working on this I got carried away :laughing: so a pretty large PR is incoming to fix alongside a host of other improvements.

roderickvd avatar Aug 14 '25 12:08 roderickvd

Hello, I was wondering if my issue was linked to this one. I have a setup similar to mfluehr (Archlinux, Pipewire, Hyprland for WM). I reduced the problem to this snippet of code:

let stream_handle = rodio::OutputStreamBuilder::open_default_stream().unwrap();
let mixer = stream_handle.mixer();
let file = File::open("/path/to/file.ogg").unwrap();
let source = Decoder::try_from(file).unwrap();
mixer.add(source); // Direct use a mixer
std::thread::sleep(std::time::Duration::from_secs(60));

I have no sound output whereas wpctl show a correct stream as expected. I have no problem with mp3 files.

The thing that I find weird is that the Vorbis ogg file is working well when I go through a Sink like that:

let stream_handle = rodio::OutputStreamBuilder::open_default_stream().unwrap();
let sink = Sink::connect_new(&stream_handle.mixer());
let file = File::open("/path/to/file.ogg").unwrap();
let source = Decoder::try_from(file).unwrap();
sink.append(source); // Playing with a Sink instead of directly mixer.add()
std::thread::sleep(std::time::Duration::from_secs(60));

I hope this is helping. It will be my pleasure to do other tests if needed but please keep in mind that I do not know a lot about Rust.

Xysto avatar Oct 26 '25 18:10 Xysto

It’s been fixed in #786.

roderickvd avatar Oct 26 '25 19:10 roderickvd