The Man who Sold the Amp: How to Process Music with JS

The Man who Sold the Amp: How to Process Music with JS

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! 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 🤘!

4f0880beebecf17d29eb709246055e14?s=128

Vitalii Bobrov

September 03, 2019
Tweet

Transcript

  1. The Man Who Sold the Amp: How to Process Music

    with JS
  2. Vitalii Bobrov Lead JS Engineer @ EPAM @AngularWroclaw organizer Guitar

    player @bobrov1989 https://bobrov.dev
  3. Web Audio

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

  5. Uni-directed Graph input output effects

  6. Guitar Stack input output

  7. Guitar Stack input output effects

  8. Connect a Guitar

  9. 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); }
  10. None
  11. Media Stream Constraints https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamConstraints/audio const stream = await navigator.mediaDevices .getUserMedia({

    audio: true });
  12. 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 } });
  13. Connect to Destination https://developer.mozilla.org/en-US/docs/Web/API/AudioDestinationNode const lineInSource = context.createMediaStreamSource(stream); lineInSource.connect(context.destination);

  14. Volume Control

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

  16. 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);
  17. Distortion

  18. group of effects shaping a sound wave

  19. None
  20. Overdrive Distortion Fuzz Effects

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

    + k * abs(x))
  22. Overdrive vs Distortion vs Fuzz

  23. Wave Shaper Node https://developer.mozilla.org/en-US/docs/Web/API/WaveShaperNode const waveShaper = new WaveShaperNode(context); waveShaper.curve

    = makeDistortionCurve(amount); 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; }
  24. 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
  25. Cabinet

  26. Impulse Response a short sample with impulse characteristics record

  27. 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; }); });
  28. Equalizer

  29. Three Band Equalizer Bass < 500 Hz Middle 500-3000 Hz

    Treble > 3000 Hz
  30. 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 });
  31. Reverb

  32. Reverb Graph Channel Splitter Node Channel Merger Node “Dry”
 Gain

    Node “Wet”
 Gain Node Delay Node Biquad Filter Node Convolver Node
  33. 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);
  34. 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);
  35. Connect line to destination Gain Node Distortion Wave Shaper Node

    Biquad Filter Node Cabinet Convolver Node Reverb Channel Merger/Splitter Node Delay Node Recap
  36. Rock it!

  37. @bobrov1989 https://bobrov.dev https://github.com/vitaliy-bobrov/js-rocks https://js-rocks.web.app