I have spent a fair bit of time trying to solve one bug related to positionalAudio, in my own project. I thought it would be useful to share it in case someone else is googling around how to solve it. The bug is: audio getting an unintended frequency modulation envelope.
I was playing short clips of sound when certain event happens; a lot like in webaudio_timing example (https://github.com/mrdoob/three.js/blob/670b1e9e85356d98efa4c702e93c85dd52f01e1e/examples/webaudio_timing.html). I was playing each sound at slightly different rates. The sound would come out with a sort of “glissando” effect on it. Further investigating the issue made me realize that the glissando went from the sound’s original tone and end in the playback rate determined in my code. For example, if I wanted to play the sound at 2 times the speed, it would start at a low tone and raise fast one octave.
I created a fiddle to figure out whethr it was an issue with three js or with my code: https://jsfiddle.net/jaldunate/ucg46nvL/14/
This fiddle is just the forementioned example, only that I add a playback rate. In this fiddle I observed that the glissando effect is still present, however much less noticeable. That made me think that three js is scheduling the playback rate every time one plays the sound again. Therefore, the glissando effect I observed is due to a mismatch between three js rate of updating audio parameters, and the rate at which my code was setting these parameters.
The first think I found on my code that needed fixing, is that I was not using the same timing for the sound related stuff than for the drawing: I wanted to have a precise musical timing, so I made it in “parallel”. This was causing part of the problem: this loop might request a play, but since three js will not update the playback rate until the next call to render, the sound would start off with 1x playback and then the rate would be ramped up on the next draw.
Setting the audio schedule to the same as the drawing schedule was not enough, I had another problem: I was calling the render function at the beggining of the loop. This was causing that the renderer was always drawing the “previous state”, essentially producing a glissando in the length of one frame loop. So, that’s the lesson: the render function always goes at the end of the render loop, especially if one is using pitched sounds.
The fiddle has the render loop in the “wrong” order, which causes a very fast, undesired pitch envelope as described. If the program is more complex and takes longer to draw one frame, this effect becomes less and less subtle. Here, the same example, but causing the glitch purposefully: https://jsfiddle.net/jaldunate/n28u69pv/12/ (line 181 to 187)