<commit_before>'use strict'

function assert(v) {
  if (!v) {
    throw new Error('Assertion error');
  }
}

// based on http://stackoverflow.com/a/31925519
var nextFloat = (function () {
  var intArr = new Uint32Array(1);
  var floatArr = new Float32Array(intArr.buffer);
  return function(v) {
    floatArr[0] = v;
    intArr[0] = intArr[0] + 1;
    return floatArr[0];
  }
})();

var INITIAL_LEVEL = 0; // It doesn't seem useful for this to be a setting

function EnvGen(audioContext, targetParam) {
  // Support instantiating w/o new
  if (!(this instanceof EnvGen)) {
    return new EnvGen(audioContext, targetParam);
  }

  this._audioContext = audioContext;
  this._targetParam = targetParam;

  var _this = this;

  Object.defineProperty(this, 'mode', {
    get: function() { return _this._mode; },
    set: function(value) {
      if (_this.MODES.indexOf(value) >= 0) {
        // If we're currently in a 'sustain' state, and we switched into AD mode,
        // we would get stuck in sustain state. So just to be safe, whenever mode
        // is changed we fake a gate-off signal.
        _this.gate(false, nextFloat(Math.max(this._lastGateTime, audioContext.currentTime)));

        _this._mode = value;
      }
    }
  });

  Object.defineProperty(this, 'attackShape', {
    get: function() { return _this._attackShape; },
    set: function(value) {
      if (_this.ATTACK_SHAPES.indexOf(value) >= 0) {
        _this._attackShape = value;
      }
    }
  });

  Object.defineProperty(this, 'attackRate', {
    get: function() { return _this._attackRate; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value > 0)) {
        _this._attackRate = value;
      }
    }
  });

  Object.defineProperty(this, 'attackLevel', {
    get: function() { return _this._attackLevel; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value)) {
        _this._attackLevel = value;
      }
    }
  });

  Object.defineProperty(this, 'decayShape', {
    get: function() { return _this._decayShape; },
    set: function(value) {
      if (_this.DECAY_SHAPES.indexOf(value) >= 0) {
        _this._decayShape = value;
      }
    }
  });

  Object.defineProperty(this, 'decayRate', {
    get: function() { return _this._decayRate; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value > 0)) {
        _this._decayRate = value;
      }
    }
  });

  Object.defineProperty(this, 'sustainFraction', {
    get: function() { return _this._sustainFraction; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value >= 0) && (value <= 1)) {
        _this._sustainFraction = value;
      }
    }
  });

  Object.defineProperty(this, 'releaseShape', {
    get: function() { return _this._releaseShape; },
    set: function(value) {
      if (_this.RELEASE_SHAPES.indexOf(value) >= 0) {
        _this._releaseShape = value;
      }
    }
  });

  Object.defineProperty(this, 'releaseRate', {
    get: function() { return _this._releaseRate; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value > 0)) {
        _this._releaseRate = value;
      }
    }
  });

  // Default settings
  this._mode = 'ADSR';
  this._attackShape = this.LINEAR;
  this._attackRate = 2;
  this._attackLevel = 1.0;
  this._decayShape = this.EXPONENTIAL;
  this._decayRate = 1;
  this._sustainFraction = 0.5;
  this._releaseShape = this.EXPONENTIAL;
  this._releaseRate = 1;

  this._targetParam.value = INITIAL_LEVEL;

  // Each segment has properties:
  //  beginTime: inclusive
  //  endTime: exclusive. may be +inf
  //  beginValue
  //  endValue
  //  shape: this.LINEAR, etc.
  //  rate: abs(slope-of-value) for LINEAR, abs(slope-of-log(value)) for EXPONENTIAL shapes
  this._scheduledSegments = [];

  // Track info about last gate we received
  this._lastGateTime = audioContext.currentTime;
  this._lastGateState = false;
}

EnvGen.prototype.MODES = ['AD', 'ASR', 'ADSR'];

EnvGen.prototype.LINEAR = 'L';
EnvGen.prototype.EXPONENTIAL = 'E';

EnvGen.prototype.ATTACK_SHAPES = [EnvGen.prototype.LINEAR];
EnvGen.prototype.DECAY_SHAPES = [EnvGen.prototype.LINEAR, EnvGen.prototype.EXPONENTIAL];
EnvGen.prototype.RELEASE_SHAPES = [EnvGen.prototype.LINEAR, EnvGen.prototype.EXPONENTIAL];

EnvGen.prototype._computeScheduledValue = function(time) {
  if (!this._scheduledSegments.length) {
    // If there are no scheduled segments, that means envelope should be at zero
    return 0;
  }

  // Sanity check: Scheduled segments should not start in the future
  assert(time >= this._scheduledSegments[0].beginTime);

  // Find what scheduled segment (if any) would be active at given time
  var activeIdx; // index into _scheduledSegments of one that is active at given time, if any
  for (var i = 0; i < this._scheduledSegments.length; i++) {
    var seg = this._scheduledSegments[i];
    if ((time >= seg.beginTime) && (time < seg.endTime)) {
      activeIdx = i;
      break;
    }
  }

  if (activeIdx === undefined) {
    // This must mean that time is after last scheduled segment
    var lastSeg = this._scheduledSegments[this._scheduledSegments.length-1];
    assert(time > lastSeg.endTime); // sanity check
    return lastSeg.endValue;<commit_msg>Fix bug in sanity check<commit_after>'use strict'

function assert(v) {
  if (!v) {
    throw new Error('Assertion error');
  }
}

// based on http://stackoverflow.com/a/31925519
var nextFloat = (function () {
  var intArr = new Uint32Array(1);
  var floatArr = new Float32Array(intArr.buffer);
  return function(v) {
    floatArr[0] = v;
    intArr[0] = intArr[0] + 1;
    return floatArr[0];
  }
})();

var INITIAL_LEVEL = 0; // It doesn't seem useful for this to be a setting

function EnvGen(audioContext, targetParam) {
  // Support instantiating w/o new
  if (!(this instanceof EnvGen)) {
    return new EnvGen(audioContext, targetParam);
  }

  this._audioContext = audioContext;
  this._targetParam = targetParam;

  var _this = this;

  Object.defineProperty(this, 'mode', {
    get: function() { return _this._mode; },
    set: function(value) {
      if (_this.MODES.indexOf(value) >= 0) {
        // If we're currently in a 'sustain' state, and we switched into AD mode,
        // we would get stuck in sustain state. So just to be safe, whenever mode
        // is changed we fake a gate-off signal.
        _this.gate(false, nextFloat(Math.max(this._lastGateTime, audioContext.currentTime)));

        _this._mode = value;
      }
    }
  });

  Object.defineProperty(this, 'attackShape', {
    get: function() { return _this._attackShape; },
    set: function(value) {
      if (_this.ATTACK_SHAPES.indexOf(value) >= 0) {
        _this._attackShape = value;
      }
    }
  });

  Object.defineProperty(this, 'attackRate', {
    get: function() { return _this._attackRate; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value > 0)) {
        _this._attackRate = value;
      }
    }
  });

  Object.defineProperty(this, 'attackLevel', {
    get: function() { return _this._attackLevel; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value)) {
        _this._attackLevel = value;
      }
    }
  });

  Object.defineProperty(this, 'decayShape', {
    get: function() { return _this._decayShape; },
    set: function(value) {
      if (_this.DECAY_SHAPES.indexOf(value) >= 0) {
        _this._decayShape = value;
      }
    }
  });

  Object.defineProperty(this, 'decayRate', {
    get: function() { return _this._decayRate; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value > 0)) {
        _this._decayRate = value;
      }
    }
  });

  Object.defineProperty(this, 'sustainFraction', {
    get: function() { return _this._sustainFraction; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value >= 0) && (value <= 1)) {
        _this._sustainFraction = value;
      }
    }
  });

  Object.defineProperty(this, 'releaseShape', {
    get: function() { return _this._releaseShape; },
    set: function(value) {
      if (_this.RELEASE_SHAPES.indexOf(value) >= 0) {
        _this._releaseShape = value;
      }
    }
  });

  Object.defineProperty(this, 'releaseRate', {
    get: function() { return _this._releaseRate; },
    set: function(value) {
      if ((typeof(value) === 'number') && !isNaN(value) && (value > 0)) {
        _this._releaseRate = value;
      }
    }
  });

  // Default settings
  this._mode = 'ADSR';
  this._attackShape = this.LINEAR;
  this._attackRate = 2;
  this._attackLevel = 1.0;
  this._decayShape = this.EXPONENTIAL;
  this._decayRate = 1;
  this._sustainFraction = 0.5;
  this._releaseShape = this.EXPONENTIAL;
  this._releaseRate = 1;

  this._targetParam.value = INITIAL_LEVEL;

  // Each segment has properties:
  //  beginTime: inclusive
  //  endTime: exclusive. may be +inf
  //  beginValue
  //  endValue
  //  shape: this.LINEAR, etc.
  //  rate: abs(slope-of-value) for LINEAR, abs(slope-of-log(value)) for EXPONENTIAL shapes
  this._scheduledSegments = [];

  // Track info about last gate we received
  this._lastGateTime = audioContext.currentTime;
  this._lastGateState = false;
}

EnvGen.prototype.MODES = ['AD', 'ASR', 'ADSR'];

EnvGen.prototype.LINEAR = 'L';
EnvGen.prototype.EXPONENTIAL = 'E';

EnvGen.prototype.ATTACK_SHAPES = [EnvGen.prototype.LINEAR];
EnvGen.prototype.DECAY_SHAPES = [EnvGen.prototype.LINEAR, EnvGen.prototype.EXPONENTIAL];
EnvGen.prototype.RELEASE_SHAPES = [EnvGen.prototype.LINEAR, EnvGen.prototype.EXPONENTIAL];

EnvGen.prototype._computeScheduledValue = function(time) {
  if (!this._scheduledSegments.length) {
    // If there are no scheduled segments, that means envelope should be at zero
    return 0;
  }

  // Sanity check: Scheduled segments should not start in the future
  assert(time >= this._scheduledSegments[0].beginTime);

  // Find what scheduled segment (if any) would be active at given time
  var activeIdx; // index into _scheduledSegments of one that is active at given time, if any
  for (var i = 0; i < this._scheduledSegments.length; i++) {
    var seg = this._scheduledSegments[i];
    if ((time >= seg.beginTime) && (time < seg.endTime)) {
      activeIdx = i;
      break;
    }
  }

  if (activeIdx === undefined) {
    // This must mean that time is after last scheduled segment
    var lastSeg = this._scheduledSegments[this._scheduledSegments.length-1];
    assert(time >= lastSeg.endTime); // sanity check
    return lastSeg.endValue;
{'fraction_non_alphanumeric': 0.14258823529411765, 'fraction_numerical': 0.0073411764705882355, 'mean_word_length': 3.082212831348444, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1125771', 'n_tokens_mistral': 3580, 'n_tokens_neox': 3453, 'n_words': 821}