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

JavaScript, JavaScript…. Rocks You!

JavaScript, JavaScript…. Rocks You!

After so many years sitting with the computer you can take your old scratched Les Paul or Stratocaster from the case and fill all the space around with warm riffs. I’m going to show how to transform the code into Kirk Hammett’s wah-wah, Stevie Ray Vaughan’s overdrive and Kurt Cobain’s distortion. You’ll learn how to parse audio input in real-time using JavaScript and the Web Audio API.

I’ll be jamming live on stage with my guitar to demo every code example and we’ll also use WebRTC to jam with friends across the world! After this talk, you will be familiar with the principles behind pedal sound effects and how to create them in code. Let’s rock the Web!

Vitalii Bobrov

June 01, 2019
Tweet

More Decks by Vitalii Bobrov

Other Decks in Programming

Transcript

  1. JavaScript, JavaScript…
    Rocks You!

    View full-size slide

  2. Vitalii Bobrov
    Lead JS Engineer @ EPAM
    @AngularWroclaw organizer
    Guitar player
    @bobrov1989
    https://bobrov.dev

    View full-size slide

  3. a uni-directed graph containing
    audio nodes
    https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API

    View full-size slide

  4. Uni-directed Graph
    input output
    effects

    View full-size slide

  5. Guitar Stack
    input output

    View full-size slide

  6. Guitar Stack
    input output
    effects

    View full-size slide

  7. Connect a Guitar

    View full-size slide

  8. Stream Source
    https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamAudioSourceNode
    try {
    const context = new AudioContext();
    const stream = await navigator.mediaDevices
    .getUserMedia({
    audio: true
    });
    } catch (err) {
    console.error(err);
    }

    View full-size slide

  9. Media Stream Constraints
    https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints/audio
    const stream = await navigator.mediaDevices
    .getUserMedia({
    audio: true
    });

    View full-size slide

  10. Media Stream Constraints
    https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints/audio
    const stream = await navigator.mediaDevices
    .getUserMedia({
    audio: {
    echoCancellation: false,
    autoGainControl: false,
    noiseSuppression: false,
    latency: 0
    }
    });

    View full-size slide

  11. Connect to Destination
    https://developer.mozilla.org/en-US/docs/Web/API/AudioDestinationNode
    const lineInSource = context.createMediaStreamSource(stream);
    lineInSource.connect(context.destination);

    View full-size slide

  12. Volume Control

    View full-size slide

  13. Gain Control
    sin(x) 0.5sin(x)

    View full-size slide

  14. Gain Node
    https://developer.mozilla.org/en-US/docs/Web/API/GainNode
    const gainNode = new GainNode(context);
    gainNode.gain.value = 0.5;
    source.connect(gainNode).connect(context.destination);

    View full-size slide

  15. group of effects shaping
    a sound wave

    View full-size slide

  16. Overdrive
    Distortion
    Fuzz
    Effects

    View full-size slide

  17. Wave Shape
    sin(x) (PI + k) * x / (PI + k * abs(x))

    View full-size slide

  18. Distortion vs Overdrive vs Fuzz

    View full-size slide

  19. Wave Shaper Node
    https://developer.mozilla.org/en-US/docs/Web/API/WaveShaperNode
    const waveShaper = new WaveShaperNode(context);
    waveShaper.curve = makeDistortionCurve(amount1);
    function makeDistortionCurve(amount) {
    const k = amount * 150 + 50;
    const n = 8096;
    const curve = new Float32Array(n + 1);
    for (let i = 0, x: number; i <= n; ++i) {
    x = i * 2 / n - 1;
    curve[i] = (Math.PI + k) * x / (Math.PI + k * Math.abs(x));
    }
    return curve;
    }

    View full-size slide

  20. Biquad Filter Node
    https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode
    const toneNode = new BiquadFilterNode(context, {
    type: 'lowpass',
    frequency: 350
    });
    toneNode.frequency.value = tone; // 350 - 22050

    View full-size slide

  21. Impulse Response
    a short sample with
    impulse characteristics record

    View full-size slide

  22. Convolver Node
    https://developer.mozilla.org/en-US/docs/Web/API/ConvolverNode
    const convolver = new ConvolverNode(context);
    fetch('impulse.wav')
    .then(response => response.arrayBuffer())
    .then(buffer => {
    context.decodeAudioData(buffer, decoded => {
    convolver.buffer = decoded;
    });
    });

    View full-size slide

  23. Three Band Equalizer
    Bass < 500 Hz
    Middle ~1500 Hz
    Treble > 3000 Hz

    View full-size slide

  24. Biquad Filter Nodes
    https://developer.mozilla.org/en-US/docs/Web/API/BiquadFilterNode
    const bassNode = new BiquadFilterNode(context, {
    type: 'lowshelf',
    frequency: 500
    });
    const midNode = new BiquadFilterNode(context, {
    type: 'peaking',
    frequency: 1500
    });
    const trebleNode = new BiquadFilterNode(context, {
    type: 'highshelf',
    frequency: 3000
    });

    View full-size slide

  25. Reverb Graph
    Channel
    Splitter Node
    Channel
    Merger Node
    “Dry”

    Gain Node
    “Wet”

    Gain Node
    Delay Node
    Biquad Filter
    Node
    Convolver
    Node

    View full-size slide

  26. Reverb Nodes
    https://developer.mozilla.org/en-US/docs/Web/API/ChannelSplitterNode
    https://developer.mozilla.org/en-US/docs/Web/API/DelayNode
    const splitter = new ChannelSplitterNode(context);
    const delayNode = new DelayNode(context);
    const toneNode = new BiquadFilterNode(context);
    const convolver = new ConvolverNode(context);
    const wet = new GainNode(context);
    const dry = new GainNode(context);
    const merger = new ChannelMergerNode(context);

    View full-size slide

  27. Connect Nodes
    https://developer.mozilla.org/en-US/docs/Web/API/ChannelMergerNode
    splitter.connect(delayNode);
    delayNode.connect(toneNode);
    toneNode.connect(convolver);
    convolver.connect(wet);
    wet.connect(merger);
    splitter.connect(dry, 1).connect(merger, 0, 1);

    View full-size slide

  28. Connect line to destination
    Gain Node
    Distortion
    Wave Shaper Node
    Biquad Filter Node
    Cabinet
    Convolver Node
    Reverb
    Channel Merger/Splitter Node
    Delay Node
    Recap

    View full-size slide

  29. @bobrov1989
    https://bobrov.dev
    https://github.com/vitaliy-bobrov/js-rocks
    https://bobrov.dev/js-rocks/

    View full-size slide