Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Do you even jam bruh?

Do you even jam bruh?

Experiments with Web Audio API and React

Siddharth Kshetrapal

August 20, 2017
Tweet

More Decks by Siddharth Kshetrapal

Other Decks in Technology

Transcript

  1. DO YOU
    EVEN
    JAM
    BRUH?

    View full-size slide

  2. bit.ly/reactbangalore
    twitter slack

    View full-size slide

  3. @siddharthkp

    View full-size slide

  4. javascript architect @practo
    open source github.com/siddharthkp
    youtube thingy bit.ly/jsshow

    View full-size slide

  5. Web Audio API

    View full-size slide

  6. AudioContext
    input → effects → destination

    View full-size slide

  7. AudioContext
    input → effects → destination
    OscillatorNode
    AudioBuffer

    View full-size slide

  8. AudioContext
    input → effects → destination
    OscillatorNode
    AudioBuffer
    BiquadFilter
    GainNode
    WaveShaper

    View full-size slide

  9. AudioContext
    input → effects → destination
    OscillatorNode
    AudioBuffer
    BiquadFilter
    GainNode
    WaveShaper
    Audio
    MediaStream

    View full-size slide

  10. Web Audio API
    Full spec: https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API

    View full-size slide

  11. AudioContext
    input → effects → destination
    OscillatorNode
    AudioBuffer
    BiquadFilter
    GainNode
    WaveShaper
    Audio
    MediaStream

    View full-size slide

  12. AudioContext
    input → effects → destination
    OscillatorNode
    AudioBuffer
    BiquadFilter
    GainNode
    WaveShaper
    Audio
    MediaStream

    View full-size slide

  13. AudioContext

    destination

    effect
    input

    View full-size slide

  14. const context = new(window.AudioContext || window.webkitAudioContext)
    AudioContext

    destination

    effect
    input

    View full-size slide

  15. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    AudioContext

    destination

    effect
    input

    View full-size slide

  16. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    AudioContext

    destination

    effect
    input

    View full-size slide

  17. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    oscillator.connect(context.destination)
    AudioContext

    destination

    effect
    input

    View full-size slide

  18. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    oscillator.connect(context.destination)
    oscillator.start()
    setTimeout(() => oscillator.stop(), 1000)
    AudioContext

    destination

    effect
    input

    View full-size slide

  19. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    const gainEffect = context.createGain()
    oscillator.connect(context.destination)
    oscillator.start()
    setTimeout(() => oscillator.stop(), 1000)
    AudioContext

    destination

    effect
    input

    View full-size slide

  20. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    const gainEffect = context.createGain()
    gainEffect.gain.setValueAtTime(10, context.currentTime)
    oscillator.connect(context.destination)
    oscillator.start()
    setTimeout(() => oscillator.stop(), 1000)
    AudioContext

    destination

    effect
    input

    View full-size slide

  21. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    const gainEffect = context.createGain()
    gainEffect.gain.setValueAtTime(10, context.currentTime)
    oscillator.connect(gainEffect).connect(context.destination)
    oscillator.start()
    setTimeout(() => oscillator.stop(), 1000)
    AudioContext

    destination

    effect
    input

    View full-size slide

  22. const context = new(window.AudioContext || window.webkitAudioContext)
    const oscillator = context.createOscillator()
    oscillator.frequency.setValueAtTime(400, context.currentTime)
    oscillator.type = 'square' // sine, square, triangle, sawtooth
    const gainEffect = context.createGain()
    gainEffect.gain.setValueAtTime(10, context.currentTime)
    oscillator.connect(gainEffect).connect(context.destination)
    oscillator.start()
    setTimeout(() => oscillator.stop(), 1000)
    AudioContext

    destination

    effect
    input

    View full-size slide

  23. AudioContext

    destination

    effect
    const context = new(window.AudioContext || window.webkitAudioContext)
    const source = context.createBufferSource()
    const url = './audio/snare.wav'
    input

    View full-size slide

  24. AudioContext

    destination

    effect
    const context = new(window.AudioContext || window.webkitAudioContext)
    const source = context.createBufferSource()
    const url = './audio/snare.wav'
    new BufferLoader(context, url, audioBuffer => {
    source.buffer = audioBuffer
    }).load()
    input

    View full-size slide

  25. AudioContext

    destination

    effect
    const context = new(window.AudioContext || window.webkitAudioContext)
    const source = context.createBufferSource()
    const url = './audio/snare.wav'
    new BufferLoader(context, url, audioBuffer => {
    source.buffer = audioBuffer
    source.connect(context.destination)
    source.start()
    }).load()
    input

    View full-size slide

  26. • • • • • • • •

    View full-size slide

  27. • • • • • • • •
    kick x x x x x x x x

    View full-size slide

  28. • • • • • • • •
    kick x----- x----- x----- x----- x----- x----- x----- x-----

    View full-size slide

  29. • • • • • • • •
    kick x x x x x x x x

    View full-size slide

  30. • • • • • • • •
    kick x x x x x x x x
    snare x x x x

    View full-size slide

  31. • • • • • • • •
    kick x x x x x x x x
    snare x x x x
    hihat x x x x x x x x

    View full-size slide

  32. • • • • • • • •
    kick x x x x x x x x
    snare x x x x
    hihat x x x x x x x x
    bass E E E E B B B B

    View full-size slide

  33. • • • • • • • •
    kick x x x x x x x x
    snare x x x x
    hihat x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide

  34. • • • • • • • •
    kick x x x x x x x x
    snare x x x x
    hihat x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide


  35. kick x x x x x x x x
    snare x x x x
    hihat x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide


  36. x x x x x x x x
    snare x x x x
    hihat x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide

  37. class Kick extends React.Component {
    }

    View full-size slide

  38. class Kick extends React.Component {
    constructor () {
    }
    componentDidMount () {
    }
    render () {
    }
    }

    View full-size slide

  39. class Kick extends React.Component {
    constructor () {
    super(props)
    this.state = { notes: this.props.children.split(' ') }
    }
    componentDidMount () {
    }
    render () {
    }
    }

    View full-size slide

  40. class Kick extends React.Component {
    constructor () {
    super(props)
    this.state = { notes: this.props.children.split(' ') }
    }
    componentDidMount () {
    loadInstrument('kick').then(source => {
    this.setState({ source })
    })
    }
    render () {
    }
    }

    View full-size slide

  41. class Kick extends React.Component {
    constructor () {
    super(props)
    this.state = { notes: this.props.children.split(' ') }
    }
    componentDidMount () {
    loadInstrument('kick').then(source => {
    this.setState({ source })
    })
    }
    render () {
    this.state.notes.map((note, index) => {
    setTimeout(() => this.state.source.play(), index * 500)
    })
    }
    }

    View full-size slide


  42. x x x x x x x x
    x x x x
    hihat x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide


  43. x x x x x x x x
    x o x o x o x o
    hihat x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide

  44. class Kick extends React.Component {
    constructor () {
    ...
    }
    componentDidMount () {
    ...
    }
    render () {
    this.state.notes.map((note, index) => {
    if (index !== 'o') {
    setTimeout(() => this.state.source.play(), index * 500)
    }
    })
    }
    }

    View full-size slide


  45. x x x x x x x x
    x o x o x o x o
    x x x x x x x x
    bass E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide


  46. x x x x x x x x
    x o x o x o x o
    x x x x x x x x
    E E E E B B B B
    lead E2 E2 G2 E2 D2 C2 B1

    View full-size slide

  47. class Bass extends React.Component {
    constructor () {
    ...
    }
    componentDidMount () {
    ...
    }
    render () {
    this.state.notes.map((note, index) => {
    setTimeout(() => {
    this.state.source.frequency.value = getFrequency(note)
    this.state.source.play())
    }, index * 500)
    })
    }
    }

    View full-size slide

  48. const chords = {
    C: 65.406,
    D: 73.416,
    E: 82.407,
    F: 87.307,
    G: 97.999,
    B: 123.471,
    }

    View full-size slide

  49. const chords = {
    C: 65.406, C1: 32.703,
    D: 73.416, D1: 36.708,
    E: 82.407, E1: 41.203,
    F: 87.307, F1: 43.654,
    G: 97.999, G1: 48.999,
    B: 123.471, B1: 61.735
    }

    View full-size slide

  50. const chords = {
    C: 65.406, C1: 32.703,
    D: 73.416, D1: 36.708,
    E: 82.407, E1: 41.203,
    F: 87.307, F1: 43.654,
    G: 97.999, G1: 48.999,
    B: 123.471, B1: 61.735
    }
    const getFrequency = note => {
    return chords[note]
    }

    View full-size slide


  51. x x x x x x x x
    x o x o x o x o
    x x x x x x x x
    E E E E B B B B
    E2 E2 G2 E2 D2 C2 B1

    View full-size slide

  52. • • • • • • • •
    E2 E2 G2 E2 D2 C2 B1

    View full-size slide

  53. • • • • • • • •
    E2 E2 G2 E2 D2 C2 B1

    E2
    E2
    G2
    E2
    D2
    C2
    B1

    View full-size slide

  54. • • • • • • • •
    E2 E2 G2 E2 D2 C2 B1

    E2
    E2
    G2
    E2
    D2
    C2
    B1

    View full-size slide

  55. class Lead extends React.Component {
    constructor () {
    ...
    }
    componentDidMount () {
    ...
    }
    render () {
    this.props.children.map((child, index) => {
    setTimeout(() => {
    this.state.source.frequency.value = getFrequency(child.props.chord)
    this.state.source.play())
    }, child.props.time * 1000)
    })
    }
    }

    View full-size slide

  56. Speech Synthesis API

    View full-size slide

  57. const synth = window.speechSynthesis
    const voices = synth.getVoices()

    View full-size slide

  58. const synth = window.speechSynthesis
    const voices = synth.getVoices()
    const text = 'Hello world'
    const speech = new SpeechSynthesisUtterance(text);
    speech.voice = voices[0]

    View full-size slide

  59. const synth = window.speechSynthesis
    const voices = synth.getVoices()
    const text = 'Hello world'
    const speech = new SpeechSynthesisUtterance(text);
    speech.voice = voices[53]
    synth.speak(speech)

    View full-size slide

  60. @siddharthkp
    twitter github

    View full-size slide