I've noticed in the Audio Mixer when panning an audio source, the overall gain
also changes, and the level control must be adjusted to compensate.  A look at
src/sound/AudioProcess.cpp makes clear what's going on:

 481:  rec.gainLeft = volume * ((pan > 0.0) ? (1.0 - (pan / 100.0)) : 1.0);
 482:  rec.gainRight = volume * ((pan < 0.0) ? ((pan + 100.0) / 100.0) : 1.0);

What all this means is that when

  pan = -100
  rec.gainLeft =  volume * 1.0
  rec.gainRight = volume * 0

  pan = -50
  rec.gainLeft =  volume * 1.0
  rec.gainRight = volume * 0.5

  pan = 0
  rec.gainLeft =  volume * 1.0
  rec.gainRight = volume * 1.0

  pan = 50
  rec.gainLeft =  volume * 0.5
  rec.gainRight = volume * 1.0

  pan = 100
  rec.gainLeft =  volume * 0
  rec.gainRight = volume * 1.0

Clearly there is a 3dB drop in overall gain when the control is moved off
center to one side or the other.


My proposed fix, which is fairly straightforward, looks like this:

  rec.gainLeft = volume * sqrtf(fabsf((100.0 - pan) / 100.0));
  rec.gainRight = volume * sqrtf(fabsf((100.0 + pan) / 100.0));

which means that when

  pan = -100
  rec.gainLeft =  volume * sqrt(2.0)
  rec.gainRight = volume * 0

  pan = -50
  rec.gainLeft =  volume * sqrt(1.5)
  rec.gainRight = volume * sqrt(0.5)

  pan = 0
  rec.gainLeft =  volume * 1.0
  rec.gainRight = volume * 1.0

  pan = 50
  rec.gainLeft =  volume * sqrt(0.5)
  rec.gainRight = volume * sqrt(1.5)

  pan = 100
  rec.gainLeft =  volume * 0
  rec.gainRight = volume * sqrt(2.0)

This maintains constant audio power as the source is panned.

It is because the audio power increases as the square of the level that the
gain here is multiplied by by the square root of the desired audio power gain.
(In electronic terms, simply doubling the voltage would also double the
current, resulting in a quadrupling of the power, which we don't want.)

The "fabs()" function is just a reflection of my paranoia.

I have used this modification for some months now and have found it
indispensable, as it greatly simplifies the operation of the panning controls.
It does, however, come with a minor down side: it breaks (or at least bends)
every Rosegarden composition ever written that relies on the current broken
behavior.

This obviously warrants some discussion before adoption.  Thoughts?

Tim Munro


--- src/sound/AudioProcess.cpp  2013-01-07 13:43:43.000000000 -0800
+++ src/sound/AudioProcess.cpp  2013-03-05 08:25:23.921596507 -0800
@@ -478,8 +478,12 @@
 
     float volume = AudioLevel::dB_to_multiplier(dB);
 
-    rec.gainLeft = volume * ((pan > 0.0) ? (1.0 - (pan / 100.0)) : 1.0);
-    rec.gainRight = volume * ((pan < 0.0) ? ((pan + 100.0) / 100.0) : 1.0);
+//  rec.gainLeft = volume * ((pan > 0.0) ? (1.0 - (pan / 100.0)) : 1.0);
+//  rec.gainRight = volume * ((pan < 0.0) ? ((pan + 100.0) / 100.0) : 1.0);
+
+    // Maintain a constant combined power gain while panning between channels
+    rec.gainLeft = volume * sqrtf(fabsf((100.0 - pan) / 100.0));
+    rec.gainRight = volume * sqrtf(fabsf((100.0 + pan) / 100.0));
 }
 
 void
@@ -1541,8 +1545,12 @@
 
     float volume = AudioLevel::dB_to_multiplier(dB);
 
-    rec.gainLeft = volume * ((pan > 0.0) ? (1.0 - (pan / 100.0)) : 1.0);
-    rec.gainRight = volume * ((pan < 0.0) ? ((pan + 100.0) / 100.0) : 1.0);
+//  rec.gainLeft = volume * ((pan > 0.0) ? (1.0 - (pan / 100.0)) : 1.0);
+//  rec.gainRight = volume * ((pan < 0.0) ? ((pan + 100.0) / 100.0) : 1.0);
+
+    // Maintain a constant combined power gain while panning between channels
+    rec.gainLeft = volume * sqrtf(fabsf((100.0 - pan) / 100.0));
+    rec.gainRight = volume * sqrtf(fabsf((100.0 + pan) / 100.0));
     rec.volume = volume;
 }
 
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Rosegarden-devel mailing list
[email protected] - use the link below to unsubscribe
https://lists.sourceforge.net/lists/listinfo/rosegarden-devel

Reply via email to