noise/index.js

/**
 * > Generate noise
 *
 * [![npm install dsp-noise](https://nodei.co/npm/dsp-noise.png?mini=true)](https://npmjs.org/package/dsp-noise/)
 *
 * @example
 * const dsp = require('dsp-kit')
 * dsp.fill(1024, dsp.white())
 *
 * @module noise
 */
const { random } = Math

/**
 * Create a function that generates white noise
 *
 * @param {Number} [compensate = 1] - the gain compensation
 * @return {Function} the white noise generator function
 * @example
 * var dsp = require('dsp-kit')
 * dsp.fill(1024, dsp.white())
 */
export function white (compensate = 1) {
  return compensate === 1 ? _white : () => compensate * _white()
}
function _white () { return 2 * random() - 1 }

/**
 * Create a function that generates pink noise
 *
 * Pink noise has an even distribution of power if the frequency is mapped in a
 * logarithmic scale.
 *
 * If 'white' consists of uniform random numbers, such as those generated by the
 * rand() function, 'pink' will have an almost gaussian level  distribution.
 *
 * This is an approximation to a -10dB/decade filter using a weighted sum of
 * first order filters. It is accurate to within +/-0.05dB above 9.2Hz  (44100Hz
 * sampling rate). Unity gain is at Nyquist, but can be adjusted by scaling the
 * numbers at the end of each line.
 *
 * It uses the Paul Kellet’s (refined) method: has smooth spectrum, but goes up
 * slightly at the far high end
 *
 * #### References
 * - https://github.com/csound/csound/blob/develop/Opcodes/pitch.c#L1338
 * - http://www.musicdsp.org/files/pink.txt
 *
 * @param {Number} [compensate = 0.11] - The result will be multiplied by
 * this constant in order to compensate the gain output
 * @return {Function} the pink noise generator function
 * @example
 * var dsp = require('dsp-kit')
 * dsp.fill(1024, dsp.pink())
 */
export function pink (compensate = 0.11) {
  var b0, b1, b2, b3, b4, b5, b6
  b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0
  return function () {
    var w = _white()
    b0 = 0.99886 * b0 + w * 0.0555179
    b1 = 0.99332 * b1 + w * 0.0750759
    b2 = 0.96900 * b2 + w * 0.1538520
    b3 = 0.86650 * b3 + w * 0.3104856
    b4 = 0.55000 * b4 + w * 0.5329522
    b5 = -0.7616 * b5 - w * 0.0168980
    var out = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362
    b6 = w * 0.115926
    return compensate * out
  }
}

/**
 * Create a function that generates brown noise
 *
 * @param {Number} [compensate = 3.5] - the gain compensation value
 * @return {Function} the brown noise generator function
 * @example
 * var dsp = require('dsp-kit')
 * dsp.fill(1024, dsp.brown())
 */
export function brown (compensate = 3.5) {
  var out = 0
  return function () {
    out = (out + 0.02 * _white()) / 1.02
    return compensate * out
  }
}