<commit_before>/* global AudioContext */
import Component from 'inferno-component'

export default class Drone extends Component {
  componentDidMount () {
    new Processor().generate()
  }

  render () {
    return null
  }
}

/**
 * Adopted from @mattdiamond's JS drone project.
 * @see http://matt-diamond.com/drone.html
 */
class Processor {
  bufferSize = 4096
  scale = [0.0, 2.0, 4.0, 6.0, 7.0, 9.0, 11.0, 12.0, 14.0]
  noiseNodes = []

  constructor (oscilatorsSize = 40, baseNote = 60) {
    const context = this.context = new AudioContext()

    const gainNode = this.gainNode = context.createGain()
    gainNode.gain.value = 0.25
    gainNode.connect(context.destination)

    this.oscilatorsSize = oscilatorsSize
    this.baseNote = baseNote
  }

  generate () {
    for (let i = 0; i < this.oscilatorsSize; i++) {
      const degree = Math.floor(Math.random() * this.scale.length)
      let frequency = mtof(this.baseNote + this.scale[degree])
      frequency += Math.random() * 4 - 2
      this.createNoiseGenerator(frequency)
    }
  }

  createNoiseGenerator (frequency) {
    const pannerNode = this.context.createPanner()
    const min = -20
    const max = 20
    let x = rand(min, max)
    let y = rand(min, max)
    let z = rand(min, max)

    pannerNode.setPosition(x, y, z)
    pannerNode.connect(this.gainNode)

    const filter = this.context.createBiquadFilter()
    filter.frequency.value = frequency
    filter.Q.value = 50
    filter.connect(pannerNode)

    const noiseSource = this.context.createScriptProcessor(this.bufferSize, 1, 2)
    noiseSource.onaudioprocess = (e) => {
      const bufferL = e.outputBuffer.getChannelData(0)
      const bufferR = e.outputBuffer.getChannelData(1)
      for (let i = 0; i < this.bufferSize; i++) {
        bufferL[i] = bufferR[i] = Math.random() * 2 - 1
      }
    }

    noiseSource.connect(filter)
    this.noiseNodes.push(noiseSource)

    setInterval(() => {
      x += rand(-0.1, 0.1)
      y += rand(-0.1, 0.1)
      z += rand(-0.1, 0.1)
      pannerNode.setPosition(x, y, z)
    }, 500)
  }<commit_msg>chore: cleanup resources on unmount<commit_after>/* global AudioContext */
import Component from 'inferno-component'

export default class Drone extends Component {
  componentDidMount () {
    this.processor = new Processor().generate()
  }

  componentWillUnmount() {
    this.processor.destroy()
  }

  render () {
    return null
  }
}

/**
 * Adopted from @mattdiamond's JS drone project.
 * @see http://matt-diamond.com/drone.html
 */
class Processor {
  bufferSize = 4096
  scale = [0.0, 2.0, 4.0, 6.0, 7.0, 9.0, 11.0, 12.0, 14.0]
  noiseNodes = []
  panIntervals = []

  constructor (oscilatorsSize = 40, baseNote = 60) {
    const context = this.context = new AudioContext()

    const gainNode = this.gainNode = context.createGain()
    gainNode.gain.value = 0.25
    gainNode.connect(context.destination)

    this.oscilatorsSize = oscilatorsSize
    this.baseNote = baseNote
  }

  generate () {
    for (let i = 0; i < this.oscilatorsSize; i++) {
      const degree = Math.floor(Math.random() * this.scale.length)
      let frequency = mtof(this.baseNote + this.scale[degree])
      frequency += Math.random() * 4 - 2
      this.createNoiseGenerator(frequency)
    }
  }

  createNoiseGenerator (frequency) {
    const pannerNode = this.context.createPanner()
    const min = -20
    const max = 20
    let x = rand(min, max)
    let y = rand(min, max)
    let z = rand(min, max)

    pannerNode.setPosition(x, y, z)
    pannerNode.connect(this.gainNode)

    const filter = this.context.createBiquadFilter()
    filter.frequency.value = frequency
    filter.Q.value = 50
    filter.connect(pannerNode)

    const noiseSource = this.context.createScriptProcessor(this.bufferSize, 1, 2)
    noiseSource.onaudioprocess = (e) => {
      const bufferL = e.outputBuffer.getChannelData(0)
      const bufferR = e.outputBuffer.getChannelData(1)
      for (let i = 0; i < this.bufferSize; i++) {
        bufferL[i] = bufferR[i] = Math.random() * 2 - 1
      }
    }

    noiseSource.connect(filter)
    this.noiseNodes.push(noiseSource)

    this.panIntervals.push(setInterval(() => {
      x += rand(-0.1, 0.1)
      y += rand(-0.1, 0.1)
      z += rand(-0.1, 0.1)
      pannerNode.setPosition(x, y, z)
    }, 500))
  }

  destroy () {
    this.panIntervals.map(window.clearInterval)
  }
{'fraction_non_alphanumeric': 0.13465935070873342, 'fraction_numerical': 0.02880658436213992, 'mean_word_length': 2.8076588337684942, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, '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': '1516091', 'n_tokens_mistral': 1601, 'n_tokens_neox': 1479, 'n_words': 330}