<commit_before>
export class SamplingMaster {

  constructor(audioContext) {
    this._audioContext = audioContext
    this._samples = []
    this._instances = new Set()
  }

  get audioContext() {
    return this._audioContext
  }

  destroy() {
    if (this._destroyed) return
    this._destroyed = true
    for (let sample of this._samples) sample.destroy()
    for (let instance of this._instances) instance.destroy()
    this._samples = null
    this._instances = null
  }

  sample(arrayBuffer) {
    return this._decodeAudio(arrayBuffer)
    .then(audioBuffer => {
      if (this._destroyed) throw new Error('SamplingMaster already destroyed!')
      var sample = new Sample(this, audioBuffer)
      this._samples.push(sample)
    })
  }

  _decodeAudio(arrayBuffer) {
    return new Promise(function(resolve, reject) {
      this.audioContext.decodeAudioData(arrayBuffer,
        function decodeAudioDataSuccess(audioBuffer) {
          resolve(audioBuffer)
        },
        function decodeAudioDataFailure(err) {
          reject(err)
        }
      )
    })
  }

  _startPlaying(instance) {
    this._instances.push(instance)
  }

  _stopPlaying(instance) {
    var index = this._instances.indexOf(instance)
    if (index > -1) this._instances.splice(index, 1)
  }

}

class Sample {

  constructor(samplingMaster, audioBuffer) {
    this._master = samplingMaster
    this._buffer = audioBuffer<commit_msg>feat(sampling-master): allow Blob to be coerced asynchronously into ArrayBuffer<commit_after>
export class SamplingMaster {

  constructor(audioContext) {
    this._audioContext = audioContext
    this._samples = []
    this._instances = new Set()
  }

  get audioContext() {
    return this._audioContext
  }

  destroy() {
    if (this._destroyed) return
    this._destroyed = true
    for (let sample of this._samples) sample.destroy()
    for (let instance of this._instances) instance.destroy()
    this._samples = null
    this._instances = null
  }

  sample(blobOrArrayBuffer) {
    return this._coerceToArrayBuffer(blobOrArrayBuffer)
    .then(arrayBuffer => this._decodeAudio(arrayBuffer))
    .then(audioBuffer => {
      if (this._destroyed) throw new Error('SamplingMaster already destroyed!')
      var sample = new Sample(this, audioBuffer)
      this._samples.push(sample)
    })
  }

  _coerceToArrayBuffer(blobOrArrayBuffer) {
    if (blobOrArrayBuffer instanceof ArrayBuffer) {
      return Promise.resolve(blobOrArrayBuffer)
    } else {
      return new Promise(function(resolve, reject) {
        let reader = new FileReader()
        reader.onload = function() {
          resolve(reader.result)
        }
        reader.onerror = function() {
          reject(new Error('Unable to read from Blob'))
        }
        reader.readAsArrayBuffer(blobOrArrayBuffer)
      })
    }
  }

  _decodeAudio(arrayBuffer) {
    return new Promise(function(resolve, reject) {
      this.audioContext.decodeAudioData(arrayBuffer,
        function decodeAudioDataSuccess(audioBuffer) {
          resolve(audioBuffer)
        },
        function decodeAudioDataFailure(err) {
          reject(err)
        }
      )
    })
  }

  _startPlaying(instance) {
    this._instances.push(instance)
  }

  _stopPlaying(instance) {
    var index = this._instances.indexOf(instance)
    if (index > -1) this._instances.splice(index, 1)
  }

}

class Sample {

  constructor(samplingMaster, audioBuffer) {
    this._master = samplingMaster
    this._buffer = audioBuffer
{'fraction_non_alphanumeric': 0.09899569583931134, 'fraction_numerical': 0.0011477761836441894, 'mean_word_length': 2.9703872437357632, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, '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': '3194190', 'n_tokens_mistral': 1031, 'n_tokens_neox': 1001, 'n_words': 207}