SpaceManiac / opus-rs

Safe Rust bindings for libopus
Apache License 2.0
68 stars 63 forks source link

Output length not accounting for interleaved samples #26

Closed colinmarc closed 7 months ago

colinmarc commented 7 months ago

I'm pretty confused about the following behavior:

#[test]
fn test_roundtrip() {
    let mut encoder =
        opus::Encoder::new(48000, opus::Channels::Stereo, opus::Application::LowDelay).unwrap();

    let mut decoder = opus::Decoder::new(48000, opus::Channels::Stereo).unwrap();

    let mut packet = vec![0; 200];
    let packet_len = encoder.encode_float(&[0.0; 960], &mut packet).unwrap();

    let mut output = [1.0; 960];
    let len = decoder
        .decode_float(&packet[..packet_len], &mut output, false)
        .unwrap();

    assert_eq!(960, len); // <- this assertion fails
}

The output buffer is filled to 960 samples, as expected (that's 10ms of stereo samples), but the returned size is 480. get_nb_samples returns 480, but passing a length 480 output buffer results in BufferTooSmall.

Is this just the expected behavior for libopus? I can't find it documented everywhere, but I also don't see anywhere this would be a bug in opus-rs. I haven't managed to test this using the C library yet.

colinmarc commented 7 months ago

Ok, the answer was in fact staring me in the face in the libopus docs (emphasis mine):

opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.

Hopefully this helps someone else not get stuck on that.