SHARE
TWEET

neat panner

a guest Jul 5th, 2018 209 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Neat Panner v2018-07-06-A
  2. // Mono-to-binaural panner by Thomas Howe (thomashowemain@gmail.com)
  3.  
  4.  
  5. // function (run this first to add the global variable)
  6.  
  7. (~monoToBinaural = {
  8.     arg monoIn = PinkNoise.ar(0.1),
  9.         rightnessOrAzimuth = 0,
  10.         forwardnessOrDistance = 0,
  11.         layout = 0,
  12.         normalise = 1,
  13.         maximumMultiplier = 3,
  14.         earDistance = 0.00033;
  15.     var rightness = if(layout == 0, rightnessOrAzimuth, rightnessOrAzimuth.sin * forwardnessOrDistance);
  16.     var forwardness = if(layout == 0, forwardnessOrDistance, rightnessOrAzimuth.cos * forwardnessOrDistance);
  17.     var distance = hypot(rightness + [1, -1], forwardness);
  18.     var delay = earDistance * (distance + 1.0001 - ((distance[0] + distance[1]) / 2));
  19.     var mulRaw = (distance + 0.0001) ** -2;
  20.     var mul = if(normalise == 0, mulRaw, (mulRaw / hypot(mulRaw[0], mulRaw[1]))).min(maximumMultiplier);
  21.     DelayN.ar(monoIn, earDistance * 3, delay, mul)
  22. })
  23.  
  24.  
  25. // examples
  26.  
  27. ({ // default values (commented out)
  28.     ~monoToBinaural.value(
  29.         //monoIn: PinkNoise.ar(0.1), // reasonable volume pink noise for testing
  30.         //rightnessOrAzimuth: 0,     // distance right from centre of head OR the azimuth in radians
  31.         //forwardnessOrDistance: 0,  // distance forward from centre of head OR distance away from centre of head
  32.         //layout: 0,                 // 0 = rightness and forwardness, anything else = azimuth and distance
  33.         //normalise: 1,              // 0 = don't adjust volumes, anything else = keep loudness the same as monoIn
  34.         //maximumMultiplier: 3,      // caps the multiplier (at 3 by default, which is +9.54dB) for both channels to prevent deafness
  35.         //earDistance: 0.00033,      // internal unit of distance, defined as the middle of head and an ear (half the maximum ITD)
  36.     )
  37. }.play)
  38.  
  39. ({ // just to the left of the left ear, forward a bit
  40.     ~monoToBinaural.value(
  41.         rightnessOrAzimuth: -1.3,
  42.         forwardnessOrDistance: 0.7,
  43.     )
  44. }.play)
  45.  
  46. ({ // mapped to a 16x9 screen
  47.     ~monoToBinaural.value(
  48.         rightnessOrAzimuth: MouseX.kr(-4, 4),
  49.         forwardnessOrDistance: MouseY.kr(0, 4.5),
  50.     )
  51. }.play)
  52.  
  53. ({ // by azimuth and distance, without normalisation
  54.     ~monoToBinaural.value(
  55.         rightnessOrAzimuth: MouseX.kr(-pi/2, pi/2),
  56.         forwardnessOrDistance: MouseY.kr(1, 5, 1), // logarithmic distance, starting at earDistance
  57.         layout: 1,
  58.         normalise: 0,                              // watch out for that 9.54dB boost at the ear positions
  59.     )
  60. }.play)
  61.  
  62. ({ // SuperCollider's audio input mapped to a 16x9 screen without normalisation
  63.     ~monoToBinaural.value(
  64.         monoIn: (SoundIn.ar([0]) + SoundIn.ar([1])) * (2 ** -0.5), // convert stereo to equal power mono
  65.         rightnessOrAzimuth: MouseX.kr(-2, 2),                      // with this set to 0,
  66.         forwardnessOrDistance: MouseY.kr(0, 2.25),                 // and this set to 0, equal loudness to source should be achieved
  67.         normalise: 0,
  68.     )
  69. }.play)
  70.  
  71. ({ // just some silliness
  72.     // samples remaining till new samples remaining time is chosen, minus 2
  73.     var fallerKR = {
  74.         arg min = 1, max = 2;
  75.         var buffer = Buffer.alloc(s, 1);
  76.         var random = round(((WhiteNoise.kr(0.5, 0.5) * (max - min)) + min) * s.sampleRate / s.options.blockSize, 1) - 2;
  77.         var previous = PlayBuf.kr(1, buffer);
  78.         var current = Select.kr(previous < 0, [previous - 1, random]);
  79.         RecordBuf.kr(current, buffer);
  80.         current;
  81.     };
  82.     // picks new point every fallerKR trigger
  83.     var stochasticLine = {
  84.         arg faller = fallerKR.value, min = -1, max = 1;
  85.         var buffer = Buffer.alloc(s, 1);
  86.         var random = TRand.kr(min, max, faller);
  87.         var previous = PlayBuf.kr(1, buffer);
  88.         var current = ((random - previous) / (faller + 2)) + previous;
  89.         RecordBuf.kr(current, buffer);
  90.         current;
  91.     };
  92.     var whineRate = fallerKR.value(0.4, 0.5);
  93.     var whine = stochasticLine.value(whineRate, 850, 880);
  94.     var time = 0.5 ** Sweep.kr(0, 1/30);
  95.     var locationRate = fallerKR.value(4 * time, 5 * time);
  96.     ~monoToBinaural.value(
  97.         monoIn: Saw.ar(whine, 0.005),
  98.         rightnessOrAzimuth: stochasticLine.value(locationRate, -1.1, 1.1),
  99.         forwardnessOrDistance: stochasticLine.value(locationRate, -1.1, 1.1),
  100.         normalise: 0,
  101.     )
  102. }.play)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top