<commit_before>import React, { Component } from 'react';
import Rcslider from 'rc-slider'

import Keyboard from '../keyboard/Keyboard'

import 'rc-slider/assets/index.css'

export default class Synth extends Component {
  constructor(props) { 
    super(props);
    
    this.state = {
      isMuted: true,
      frequency: 1000,
      oscillator: {},
      gainNode: {},
      audioCtx: {},
      hasntStarted: true,
      waveForms: [
        'sine',
        'square',
        'sawtooth',
        'triangle',
      ],
    };
  }
  
  componentDidMount = () => {
    this.init();
  }
  
  init = () => {
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
    const oscillator = audioCtx.createOscillator();
    const gainNode = audioCtx.createGain();

    oscillator.connect(gainNode);
    gainNode.connect(audioCtx.destination);
    
    oscillator.type = 'sine';
    oscillator.frequency.value = 1000;
    
    this.setState({oscillator, gainNode, audioCtx})
  }

  playNote = () => {
    var currTime = this.state.audioCtx.currentTime
    var fadeTime = 1
    this.state.gainNode.gain.linearRampToValueAtTime(1, currTime);
    this.state.gainNode.gain.linearRampToValueAtTime(0, currTime + fadeTime);
  }

  toggleMute = () => {
    if (this.state.hasntStarted) {
      this.state.oscillator.start()
      this.setState({hasntStarted: false})
    }

    const value = this.state.isMuted ? 1 : 0

    this.state.gainNode.gain.value = value
    this.setState({isMuted: !this.state.isMuted})
  }

  gainSlider = value => {
    this.state.gainNode.gain.value = value / 100
  }
  
  frequencySlider = value => {
    this.changeFrequency(value)
  }

  changeFrequency = frequency => {
    this.state.oscillator.frequency.value = frequency
    this.playNote()
  }

  renderKeys = () => {
    return (
      <Keyboard 
        onKeyClick={this.changeFrequency}
        keyboardPress={this.changeFrequency}
      />
    )
  }

  renderWaveFormButtons = () => {
    return (
      this.state.waveForms.map(waveForm =>
        <div key={waveForm}>
          <button onClick={() => this.setWaveForm(waveForm)}>{waveForm}</button>
        </div>
      )
    )
  }

  setWaveForm = waveForm => this.state.oscillator.type = waveForm

  render() {
    return (
      <div>
        Synth
        <Rcslider onChange={this.gainSlider}/>
        <button onClick={this.toggleMute}>
          {this.state.isMuted ? 'Play' : 'Mute'}
        </button>
        <Rcslider max={20000} onChange={this.frequencySlider}/>
        {this.renderKeys()}
        {this.renderWaveFormButtons()}
      </div>
    );
  }
}<commit_msg>fix: playing new notes while a previous is playing doesnt mess things up<commit_after>import React, { Component } from 'react';
import Rcslider from 'rc-slider'

import Keyboard from '../keyboard/Keyboard'

import 'rc-slider/assets/index.css'

export default class Synth extends Component {
  constructor(props) { 
    super(props);
    
    this.state = {
      isMuted: true,
      frequency: 1000,
      oscillator: {},
      gainNode: {},
      audioCtx: {},
      hasntStarted: true,
      waveForms: [
        'sine',
        'square',
        'sawtooth',
        'triangle',
      ],
    };
  }
  
  componentDidMount = () => {
    this.init();
  }
  
  init = () => {
    const audioCtx = new (window.AudioContext || window.webkitAudioContext)()
    const oscillator = audioCtx.createOscillator();
    const gainNode = audioCtx.createGain();

    oscillator.connect(gainNode);
    gainNode.connect(audioCtx.destination);
    gainNode.gain.value = 0

    oscillator.type = 'sine';
    oscillator.frequency.value = 1000;
    oscillator.start()
    this.setState({oscillator, gainNode, audioCtx})
  }

  setGain = value => {
    this.state.gainNode.gain.value = value
  }

  playNote = () => {
    var currTime = this.state.audioCtx.currentTime
    var fadeTime = 1
    this.state.gainNode.gain.linearRampToValueAtTime(1, currTime);
    this.state.gainNode.gain.linearRampToValueAtTime(0, currTime + fadeTime);
  }

  gainSlider = value => {
    this.setGain(value / 100)
  }
  
  frequencySlider = value => {
    this.keyPress(value)
  }

  keyPress = frequency => {
    if (this.state.gainNode.gain.value > 0) {
      this.state.gainNode.gain.cancelScheduledValues(0)
    }
    this.setFrequency(frequency) 
    this.playNote()
  }

  setFrequency = frequency => {
    this.state.oscillator.frequency.value = frequency
  }

  renderKeys = () => {
    return (
      <Keyboard 
        onKeyClick={this.keyPress}
        keyboardPress={this.keyPress}
      />
    )
  }

  renderWaveFormButtons = () => {
    return (
      this.state.waveForms.map(waveForm =>
        <div key={waveForm}>
          <button onClick={() => this.setWaveForm(waveForm)}>{waveForm}</button>
        </div>
      )
    )
  }

  setWaveForm = waveForm => this.state.oscillator.type = waveForm

  render() {
    return (
      <div>
        Synth
        <Rcslider onChange={this.gainSlider}/>
        <Rcslider max={20000} onChange={this.frequencySlider}/>
        {this.renderKeys()}
        {this.renderWaveFormButtons()}
      </div>
    );
  }
}
{'fraction_non_alphanumeric': 0.13643410852713178, 'fraction_numerical': 0.008333333333333333, 'mean_word_length': 2.4989830508474578, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 49, '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': '5143963', 'n_tokens_mistral': 1725, 'n_tokens_neox': 1698, 'n_words': 278}