tesselode / kira

Library for expressive game audio.
https://crates.io/crates/kira
Apache License 2.0
855 stars 43 forks source link

fix: oversight in seeking while paused #52

Closed zkrising closed 1 year ago

zkrising commented 1 year ago

when paused, the state of the resampler never changes, but you can still seek around.

this results in all seek events being effectively reset while paused. (i.e. i play to 40 seconds, pause, seek to 20 seconds but the resampler still thinks i'm at 40 seconds).

tesselode commented 1 year ago

I don't understand your bug description. Can you post a code example that demonstrates the bug?

zkrising commented 1 year ago

Sorry, I wrote this PR verrrry late at night and my explanation was really bad.

I'm no longer actually sure whether this PR is a correct solution to the problem, but the problem is as such:

let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default())?;
let data = StaticSoundData::from_file("some_audio.ogg", StaticSoundSettings::default()?;

let mut handle = manager.play(data)?;

// let it play for a second
std::thread::sleep(Duration::from_millis(1000));

const NO_TWEEN: Tween = Tween {
        start_time: StartTime::Immediate,
        duration: Duration::from_millis(0),
        easing: Easing::Linear,
}

// pause it
handle.pause(NO_TWEEN);

// should be around 1 second into the song
println!("{:?}", handle.position());

// seek to 5 seconds into the song **WHILE PAUSED**
handle.seek_to(5.0);

// wait a bit just to ensure the command goes through
std::thread::sleep(Duration::from_millis(1000));

// should report that we are at 5.0 seconds in, but instead reports 1.0 seconds.
println!("{:?}", handle.position());

// start playing the file, and it starts playing back from 1.0 seconds!
handle.play(NO_TWEEN);

It's probably worth noting that I'm using this library in a bit of an unintended use case (users need to be able to scroll around in an audio file a-la a DAW even while it's playing and the reported position needs to be exact)

I managed to get kira to work in this use case but I did some fairly disgusting local patches to get the seeking to be real-time responsive as I don't really understand what I'm doing.

I'm not sure if this PR is even a correct fix for the problem, but it does fix something that is incorrect.

tesselode commented 1 year ago

I can't reproduce the issue on the main branch. Here's the test file I used:

use std::{error::Error, io::stdin, time::Duration};

use kira::{
    manager::{backend::DefaultBackend, AudioManager, AudioManagerSettings},
    sound::static_sound::{StaticSoundData, StaticSoundSettings},
    tween::{Easing, Tween},
    StartTime,
};

fn main() -> Result<(), Box<dyn Error>> {
    let mut manager = AudioManager::<DefaultBackend>::new(AudioManagerSettings::default())?;
    let data = StaticSoundData::from_file("test.wav", StaticSoundSettings::default())?;

    let mut handle = manager.play(data)?;

    // let it play for a second
    std::thread::sleep(Duration::from_millis(1000));

    const NO_TWEEN: Tween = Tween {
        start_time: StartTime::Immediate,
        duration: Duration::from_millis(0),
        easing: Easing::Linear,
    };

    // pause it
    handle.pause(NO_TWEEN)?;

    // should be around 1 second into the song
    println!("{:?}", handle.position());

    // seek to 5 seconds into the song **WHILE PAUSED**
    handle.seek_to(0.0)?;

    // wait a bit just to ensure the command goes through
    std::thread::sleep(Duration::from_millis(1000));

    // should report that we are at 5.0 seconds in, but instead reports 1.0 seconds.
    println!("{:?}", handle.position());

    // start playing the file, and it starts playing back from 1.0 seconds!
    handle.resume(NO_TWEEN)?;

    stdin().read_line(&mut "".into())?;

    Ok(())
}

I changed the code to seek back to the beginning of the sound because the sound I'm using is shorter than 5 seconds. Here's the output I get:

image

The sound also seeks back to the beginning correctly.

I think the issue you're having may have to do with the changes you made to the playback position tracking.

I'm curious how you went about getting more exact playback position reporting. If you did it the way I think you did, it's probably not as exact as you think.