Search Unity

Frame independent timing

Discussion in 'Scripting' started by MrMetwurst2, Mar 18, 2014.

  1. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    G'day guys,

    I've searched pretty extensively on this topic and I have a feeling there is no suitable solution in Unity but thought I'd ask in case anyone can think of a possible solution...

    I'm writing an audio application and I want to control the audio pitch after it's playing. The timing of the pitch changes is pretty critical to make the effect sound correct. In a normal 30-60 fps game this will be fine but if the frame rate drops it can really start screwing up the audio effect.

    I've tried Coroutines but these are not Frame Independent and I've tried System.Timers but of course these won't let me change the pitch value because that's part of the Unity API.

    I'd really appreciate any ideas that might help here.

    Cheers, Phil.
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    For consistent manipulation, so that it happens always no matter what with no delay. Use FixedUpdate. This will ensure you're in that 30->60fps range.

    If you need precise calculations happening independent of the framerate, start up a thread to do that in. But you'll always have to sync back to the update thread to update the audio. When syncing back, if you need to track time delay. System.DateTime.Now will return a DateTime object that's pretty dang close to the current time and has a 'ticks' property that is very small unit that the human ear won't recognize if it's off by, so could be used as a good way to track the tiny amount of time changes you might need when syncing from your thread back to the update loop.

    I've never tested merging a thread back into the update loop. I have an idea of how I'd accomplish it. If I play with it when I'm bored, and it works, I'll come back here and show you.
     
    Last edited: Mar 18, 2014
  3. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    Thanks lord. (no I'm not praying :D )

    This is the idea I just started looking at today. I'm going to try a combination of threaded timing with FixedUpdate to see how well that works.
    I initially wanted to avoid using FixedUpdate as this is going to be an Asset Tool and I'm trying to cater for all possible situations. If the user disables Physics timing then obviously this will break the effect. If it works there will only be a couple of lines of reading or writing in the FixedUpdate so the impact would be extremely small.

    Thanks for your input. It's good to know I'm probably on the right path.
     
  4. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    The audio engine has its own timer. It cannot be sped up or slowed down, not that that would help if you don't want to speed up or slow down all audio anyway.

    I haven't found a way to get passed the frames per second with volume fades or pitch shifts. You are not able to tell the audio engine to shift an audio clip to pitch x over y seconds and have it do so on its own, which is a shame.

    Fixed update might work, I don't know.
    Lerp is inaccurate, so don't use that.

    Let us know if it works.
     
    Last edited: Mar 19, 2014
  5. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    I hadn't noticed G-Audio yet. Looks interesting but fairly different to what I'm trying to accomplish.
    They do all their processing in the OnAudioFilterRead which is great for direct sample manipulation but I feel the processing power would get too heavy for my application if I went completely down that path.
    I might consider using it for minor adjustments if I can't nut out my solution.

    Thanks for your help guys.
     
  6. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    FixedUpdate doesn't work that way...it's tied specifically to the physics timestep, which will slow down if the framerate drops too much. It also depends on what you have the fixed timestep set to. If you really need "always happens no matter what", you can't use FixedUpdate.

    Lerp is 100% accurate--it's just a really basic math function. Not sure how it's related to frame independent timing in any way, though.

    --Eric
     
  7. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    Thanks Eric.

    Yeah, I'm not super keen on using FixedUpdate for these very reasons :/
    I might look more into OnAudioFilterRead and see what it allows.

    I use Lerp in part of my pitch shifting and yes it is 100% accurate as Eric stated. But that's not the issue, the issue is smoothness on Low FPS as well as other effects timing. I'm trying to implement Apreggio's which sound bad without accurate timing.
     
  8. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    Unfortunately OnAudioFilterRead must be a separate thread so it throws an error when I try and set the audioSource pitch. No Unity API control is allowed inside OnAudioFilterRead. That's disappointing but kind of makes sense.
     
  9. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,304
    My mistake, its inaccuracy is only related to frame dependent timing.

    Yes, the audio engine runs on a separate thread.
     
    Last edited: Mar 19, 2014
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,531
    Good to know.

    I assumed it would drop at some point. I mean nothing can really be guaranteed that much if the system gets stressed too much.
     
  11. MrMetwurst2

    MrMetwurst2

    Joined:
    Jul 16, 2009
    Posts:
    253
    I added a frame killing routine and FixedUpdate does start crawling. Generally the effects would work fine i reckon down to 15-20 fps so I don't see a huge problem and most songs won't be using these effects a lot. I'm just trying to make it foolproof.

    Thanks for your input everyone :)