Marc Vinyes mvinyes at iua.upf.es
Thu Aug 25 07:52:03 PDT 2005

```hello,

I know you're busy with such a big project, but I thought maybe sbdy could
just give me a "2-words hint" or a quick link to a reference...

I'm working in a project in the university where I'm implementing some
work about "azimuth source separation". (curious minds may find a similar
algorithm explained at
http://www.ee.columbia.edu/~dpwe/papers/Aven03-unmix.pdf)

I needed to know how the DAWs implement the pannning of each track and I
took as a reference ardour (which is the closest approach to a pro open
source sequencer that I know).

I looked at the code and I saw some things which surprised me:

I expected to see an attenuation of x in one channel and sqrt(1-x*x) in
the other, but I saw:

const float pan_law_attenuation = -3.0f;
const float scale = 2.0f - 4.0f * powf
//snip
desired_left = panL * (scale * panL + 1.0f - scale);
desired_right = panR * (scale * panR + 1.0f - scale);

what is the purpose of this formula?

BTW(not very important), wouldn't be better to replace powf
(10.0f,pan_law_attenuation/20.0f) with 1/sqrt(2). and add a comment of
//-3db attenuation
?

THank you very much in advance,
Marc Vinyes

<<<<<<<<<<<<<<<<<< in panner.cc
void
EqualPowerStereoPanner::update ()
{
/* it would be very nice to split this out into a virtual function
that can be accessed from BaseStereoPanner and used in
distribute_automated().

but the place where its used in distribute_automated() is a tight
inner loop,
and making "nframes" virtual function calls to compute values is an
absurd
*/

const float pan_law_attenuation = -3.0f;
const float scale = 2.0f - 4.0f * powf (10.0f,pan_law_attenuation/20.0f);

/* x == 0 => hard left
x == 1 => hard right
*/

float panR = x;
float panL = 1 - panR;

desired_left = panL * (scale * panL + 1.0f - scale);
desired_right = panR * (scale * panR + 1.0f - scale);

effective_x = x;
}
>>>>>>>>>>>>>>>>

```