rodio icon indicating copy to clipboard operation
rodio copied to clipboard

Unexpected output from FromIter

Open Heliozoa opened this issue 5 years ago • 1 comments

Hi, thanks for your work on rodio.

I was trying to create a source that repeats a sound X amount of times*, and I figured FromIter fits the purpose. But when playing the audio, some of the iterations are lower pitched than the first.

Here's an example that I tried on both rodio 0.13 and 0.12:

use rodio::{source, Source};

fn main() {
    let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap();
    // I used https://www.videvo.net/sound-effect/metallic-warble-impa-pe359507/251374/ 
    // for this example, but originally the issue was with a different source
    let file = std::fs::File::open("metal.mp3").unwrap();
    let source = rodio::Decoder::new(std::io::BufReader::new(file))
        .unwrap()
        .buffered();

    // play twice
    let twice = source::from_iter(vec![source.clone(); 2]).convert_samples();
    stream_handle.play_raw(twice).unwrap();
    std::thread::sleep(std::time::Duration::from_millis(3500));

    // loop
    let repeat = source.repeat_infinite().convert_samples();
    stream_handle.play_raw(repeat).unwrap();
    std::thread::sleep(std::time::Duration::from_millis(3500));
}

My expectation is to hear the same sound four times. Instead the second sound from the FromIter source sounds off. I recorded the audio I get instead: https://user-images.githubusercontent.com/15956940/102732225-d081c480-4342-11eb-92f5-f26c81a81297.mp4

If I add enough delay to the second source with Source::delay (about 50ms seemed to do the trick here) it sounds correct. I'm pretty clueless when it comes to audio, so I might have just misunderstood something. I'm on Ubuntu 20.04.1 LTS, let me know if there's some further information I can provide.

* Full context in case FromIter is not the right choice here: I'm trying to write a kind of faux-tex-to-speech: a function that takes a string and a source and returns a source that repeats the input source for each character with some random variation for each character.

Heliozoa avatar Dec 21 '20 02:12 Heliozoa

I tried cloning rodio and poking around to see if I could locate the issue. Returning None or Some(THRESHOLD) from FromIter's current_frame_len fixes the issue, though no doubt doing so has some negative effects somewhere else. I'm not really sure what's going on in the function or how it's supposed to work, but hopefully someone more knowledgeable can do something with this information.

Heliozoa avatar Dec 21 '20 03:12 Heliozoa