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.
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.
Thanks lord. (no I'm not praying ) 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.
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.
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.
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
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.
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.
My mistake, its inaccuracy is only related to frame dependent timing. Yes, the audio engine runs on a separate thread.
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.
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