Better panning in the audio mixer

When Casey began addressing the issues in GitHub, I saw the one about "wrong pitch" and just assumed it had to do with the audio mixer, so I set out to look at the audio code to see if I could find it. Turns out, of course, that the issue had nothing to do with audio.. :) but, in the process I did discover that there is an issue with the way panning is calculated.

Casey implemented linear panning, which looks like this:
http://imgur.com/a/W0ZqI

The problem with linear panning is that it does not maintain the same intensity level of the audio across the panning field. Panning full left or full right will have full intensity, but towards the centre, if you listen carefully, the intensity will dip, and as the audio pans from L -> R and vice versa it will seem to get "pulled" into the L/R speakers. The reason is that at the centre, both channels are at 0.5 amplitude, but amplitude values of 0.5 + 0.5 does not equal full intensity. The amplitude of sound is not really a good measure of how we perceive loudness, which is why the dB scale is so important and why the root-mean-square value is a more accurate measurement of how we perceive loudness.

So as opposed to linear panning, constant power panning maintains intensity across the whole panning field:
http://imgur.com/a/fZcOk

The equations for calculating the panning for L/R are:
1
2
L = (sqrt(2) / 2) * (cos(x) - sin(x))
R = (sqrt(2) / 2) * (cos(x) + sin(x))

where x is the panning angle in radians.

So you would just need to map the panning value of -1 -> 1 into -pi/4 -> pi/4 radians (giving the total panning field a value of pi / 2), and then calculate the L/R panning given the equations above.
1
angle = panning * (pi / 4) 


We haven't looked at the audio code in a long time, but I thought I would bring this up as Casey has been doing some bug fixes lately. And computationally speaking it's not much more expensive than the linear panning that's in there now, so hopefully you think it's worth it, Casey. :)
Can you file a GitHub request for it? That seems to be the best way of keeping track of things people would like me to look at.

- Casey
cmuratori
Can you file a GitHub request for it? That seems to be the best way of keeping track of things people would like me to look at.

- Casey


For sure.
As you said in day 330, I agree that calculating sin/cos once per sample is too expensive. I actually have it outside and calculate the panning once per block and then apply this panning adjustment to the interpolated volume inside the loop when mixing, and this works fine. If you were to have some fancy panning sweeps or something, then you'd want to interpolate the panning calculation per sample when mixing, and then you would want to use either a lookup table or a fast sin/cos approximation.

Anyway, as you mentioned, maybe not super important in this case. Thanks for addressing it!
Yes, that seems reasonable, if you don't hear any artifacts with that (sometimes you can hear periodic audio artifacts like that when you approximate a function piecewise-linear, and sometimes you can't, and I don't know audio well enough to know :)

In terms of accuracy, that seems totally fine then, to do it per chunk, because you could always make the chunk size smaller if it wasn't. Eg., instead of 800 samples or whatever, you could do it every 200 samples, etc. So I do think it would be possible to do this as long as it doesn't make artifacts!

- Casey