module.exports = function(neume) {
  "use strict";

  /**
   * $("white")
   *
   * $("pink")
   *
   * +------------------+
   * | BufferSourceNode |
   * | - loop: true     |
   * +------------------+
   *   |
   */
  neume.register("white", function(ugen) {
    whiteNoise = whiteNoise || generateWhiteNoise(ugen.$context.sampleRate);
    return make(whiteNoise, ugen);
  });

  neume.register("pink", function(ugen) {
    pinkNoise = pinkNoise || generatePinkNoise(ugen.$context.sampleRate);
    return make(pinkNoise, ugen);
  });

  function make(data, ugen) {
    var buf = ugen.$context.createBuffer(1, data.length, ugen.$context.sampleRate);
    var bufSrc = ugen.$context.createBufferSource();

    buf.getChannelData(0).set(data);

    bufSrc.buffer = buf;
    bufSrc.loop   = true;

    return new neume.Unit({
      outlet: bufSrc,
      start: function(t) {
        bufSrc.start(t);
      },
      stop: function(t) {
        bufSrc.stop(t);
      }
    });
  }

  var whiteNoise = null;
  var pinkNoise  = null;

  function generateWhiteNoise(sampleRate) {
    var noise = new Float32Array(sampleRate);

    for (var i = 0, imax = noise.length; i < imax; i++) {
      noise[i] = Math.random() * 2.0 - 1.0;
    }

    return noise;
  }

  function generatePinkNoise(sampleRate) {
    var noise = new Float32Array(sampleRate);

    var whites = new Uint8Array([ rand(), rand(), rand(), rand(), rand() ]);

    var MAX_KEY = 31;
    var key = 0;
    var last_key, diff;

    for (var i = 0, imax = noise.length; i < imax; i++) {
      last_key = key++;
      key &= MAX_KEY;

      diff = last_key ^ key;

      var sum = 0;
      for (var j = 0; j < 5; ++j) {
        if (diff & (1 << j)) {
          whites[j] = rand();
        }
        sum += whites[j];
      }

      noise[i] = (sum * 0.01666666) - 1;
    }

    return noise;
  }

  function rand() {
    return ((Math.random() * 1073741824)|0) % 25;
  }

};

@@ -1295,149 +1295,220 @@
     
-var noise = new Float32Array(sampleRate);%0A%0A    var whites = new Uint8Array(%5B rand(), rand(), rand(), rand(), rand() %5D);%0A%0A    var MAX_KEY = 31
+// DSP generation of Pink (1/f) Noise%0A    // http://www.firstpr.com.au/dsp/pink-noise/%0A%0A    var noise = new Float32Array(sampleRate);%0A%0A    var white;%0A    var b0 = 0;%0A    var b1 = 0;%0A    var b2 = 0;%0A    var b3 = 0
 ;%0A  
@@ -1513,19 +1513,18 @@
     var 
-key
+b4
  = 0;%0A  
@@ -1533,22 +1533,30 @@
 var 
-last_key, diff
+b5 = 0;%0A    var b6 = 0
 ;%0A%0A 
@@ -1622,239 +1622,376 @@
     
-last_key = key++;%0A      key &= MAX_KEY;%0A%0A      diff = last_key %5E key;%0A%0A      var sum = 0;%0A      for (var j = 0; j %3C 5; ++j) %7B%0A        if (diff & (1 %3C%3C j)) %7B%0A          whites%5Bj%5D = rand();%0A        %7D%0A        sum
+white = Math.random() * 2 - 1;%0A      b0 = 0.99886 * b0 + white * 0.0555179;%0A      b1 = 0.99332 * b1 + white * 0.0750759;%0A      b2 = 0.96900 * b2 + white * 0.1538520;%0A      b3 = 0.86650 * b3 + white * 0.3104856;%0A      b4 = 0.55000 * b4 + white * 0.5329522;%0A      b5 = -0.7616 * b5 - white * 0.0168980;%0A      noise%5Bi%5D = b0 + b1 + b2 + b3 + b4 + b5 + b6
  +
-=
  white
-s%5Bj%5D;%0A      %7D%0A
+ * 0.5362;
 %0A   
@@ -2006,138 +2006,89 @@
 %5Bi%5D 
-= (sum * 0.01666666) - 1;%0A    %7D%0A%0A    return noise;%0A  %7D%0A%0A  function rand() %7B%0A    return ((Math.random() * 1073741824)%7C0) %25 25
+*= 0.12; // adjust gain%0A      b6 = white * 0.115926;%0A    %7D%0A%0A    return noise
 ;%0A  %7D%0A
-%0A
 %7D;%0A

fix ugen/noise: change pink noise algorithm