Forum
    • Categories
    • Register
    • Login

    [BLOG] How does DSP work? [Part 3]

    Scheduled Pinned Locked Moved C++ Development
    1 Posts 1 Posters 12 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • griffinboyG
      griffinboy
      last edited by griffinboy

      Part 1
      Part 2

      How does DSP work? [Part 3]

      This time, we're going to look at distortion.

      In Part 1, I briefly described distortion as "bending the waveform" by changing the sample values.
      Now let's unpack what that actually means.

      Distorting a waveform

      To "distort" something means to change its shape.

      A distortion effect does exactly that to a waveform:

      88b1a706-e7d2-401e-8b68-854c0c78a4df-distortion-shape.png

      We talked previously about how in a gain/volume effect, every sample is multiplied by the same amount.
      The waveform becomes taller or shorter, but it keeps the same shape.

      A distortion effect changes sample heights by different amounts.
      That is what allows the waveform to bend shape.

      Clipping

      The simplest example of distortion is clipping.

      For example, a clipper that only allows sample values between -1.0 and +1.0.

      (fact: Most audio file formats will clip at this value)

      Values inside that range are left alone.
      Anything above +1.0 or below -1.0 is clamped.

      Watch what happens as the waveform gets louder:

      62a3a3c9-0cde-49d6-b4ff-55b81cf7b7a9-clipping-drive.gif

      At first, the waveform simply gets taller.

      Once the peaks reach the limits, they cannot get any taller.
      That's how a clipper works. This is a distortion.

      Let's zoom in and look at a few of the sample values:

      585f2c9d-f85f-433e-bd11-bcb730cc0210-clipping-samples.png

      Only the sample values that exceed the limits are changed.
      The extra height is cut off, leaving the waveform with flat edges.

      In pseudocode, the whole effect could be written like this:

      for each sample in the buffer:
          sample = clamp(sample, -1.0, 1.0)
      

      In other words:
      if the sample value is less than -1.0, it gets set to -1.0.
      if the sample value is greater than 1.0, it gets set to 1.0.

      Waveshaping

      This kind of distortion is called a Waveshaper.
      Hardclipping is just the straightforward clamp.

      9bcd1f2d-c637-45bc-850e-ff1a41ad3482-function-one-value.png

      But we can use other rules/functions to create different waveshapers.

      You can create waveshapers by defining a function that maps input values to output values.

      174ff98f-2991-4840-8d7f-c14e30f8cde7-mapping-pairs.png

      In other words:
      If the original sample value is equal to -0.75 we set it to -0.88.
      If the original sample value is equal to -0.50 we set it to -0.67,
      and so on.

      This is called mapping.
      One value is mapped to another value.

      And the table is called a lookup table.

      Drawing the table

      The input and output mapping can also be drawn as points on a graph.
      You've probably seen this kind of thing before:

      aab8ad25-cb34-43a8-bfd2-3e89c5bef259-mapping-curve.png

      It's an easy way to visualize the waveshaper.

      Input values run along the bottom.
      Output values run up the right side.

      To look up an input of 0.50, start at 0.50 along the bottom, move up until the line is reached, then move right to read the output:

      db05a93e-37b5-4e34-bf1c-026ffa55ce31-curve-lookup.gif

      The result is 0.67.

      This plot is called a transfer curve or waveshaper curve.

      bc282e62-4fae-4ad5-b594-ef945a0d6966-identity-and-shaper.png

      Bending the line means we are mapping the samples to different output values.

      A waveshaper

      Here is a waveshaper processing a waveform:

      4fa77841-29c4-448a-bd75-340360a71ff0-waveshaper-samples.gif

      For each sample of the original wave, we look up the input value on the transfer curve,
      and replace it with the corresponding output value.

      The same process on a more dense smooth waveform looks like this:

      89c81430-ee51-4fca-94af-020254731854-waveshaper-waveform.png

      The Math

      The input and output mappings do not have to be stored in a lookup table.
      Some waveshaper distortions use a table, but some use a formula instead.

      Here is the most common "soft-clipping" formula:

      output = tanh(input * drive)
      

      input is the current sample value.
      tanh is a math function that returns the new sample value.

      The function is simply another way of providing an input-to-output map.

      (You could also use sin, cos, or any other function that takes an input value and gives you an output value!)

      The drive multiplication in my code makes the original sample value larger (increases gain) before tanh waveshapes the output.
      Tanh has more of a shape at the extreme edges, so increasing the volume of our waveform means we get mapped with all those strong parts of the curve.
      And get a more warped (distorted) waveform.

      bcdc3b56-7673-49dc-aba6-bc153a4f23b7-waveshaper-drive.gif

      Basically we get more distortion when we go into the waveshaper with a louder signal.

      The algorithm is still very simple:

      for each sample in the buffer:
          sample = tanh(sample * drive)
      

      In HISE-style C++:

      b1aa719a-7b52-4613-abb3-cb385b65a8d1-hise-waveshaper-cpp.png

      HISE's math.expr node does exactly this kind of thing, and it lets you type in your own waveshaping formula!

      85d91bf7-130f-483c-b0d7-a486664dd23f-image.png

      What distortion sounds like

      Different shaped waveforms sound different (well duh).

      A sine wave sounds smooth and pure.
      A square wave sounds harsh and loud.

      When we apply waveshaping, we are bending the waveform to make new waveforms.

      37ec97d5-de58-43d0-af8c-a7215c506e4c-distortion-harmonics.png

      More bending changes the shape more (and creates all kinds of harmonics)!

      You can use a lot of different kinds of formulas to bend waveforms in weird ways.
      Different transfer curves create different effects!

      ea20e5d9-6987-4cfe-b677-6fb11a2d830f-distortion-family.png

      To Recap

      A distortion effect changes the shape of a waveform by altering the sample values.

      A clipper does this by limiting/clamping sample values.

      Waveshapers use a function to map each input sample value to a new output value.
      You can visualise this mapping nicely as a transfer curve.

      Apply the mapping to every sample in the buffer, and the new sample heights you get, form a distorted waveform.

      That is how a waveshaper works.

      1 Reply Last reply Reply Quote 4
      • First post
        Last post

      21

      Online

      2.5k

      Users

      13.9k

      Topics

      120.9k

      Posts