Re: Interpolation on WaveShaperNode?

On Mon, May 13, 2013 at 11:32 AM, Ehsan Akhgari <ehsan.akhgari@gmail.com>wrote:

> FWIW, in Gecko, I'm implementing linear interpolation by default.
>

Good, I think that's what we should do for the default, but we could
consider an attribute "linear" or "nearest-neighbor" to select the
interpolation method.  On the other hand, it's pretty easy to create the
"bit-crushing" effects even with linear interpolation as long as the table
size is suitably large, so maybe all we need is linear.

WebKit/Blink are not doing the linear interpolation, so that'll have to
change.

By the way, I've been looking in some detail about how to implement a
"high-quality" mode for the shaper, which up-samples the signal to a higher
sample-rate (2x, in the simple case), does the shaping, then down-samples
back down to the node sample-rate.  This type of processing is important
for guitar amp simulation and other simulation of analog gear to avoid the
harsh aliasing.  I think the default mode of operation for the shaper
should not do this up-sampling, but that it would be good to opt-in by
having a .quality attribute.

Cheers,
Chris



>
> --
> Ehsan
> <http://ehsanakhgari.org/>
>
>
> On Sat, Apr 6, 2013 at 6:12 PM, robert bristow-johnson <
> rbj@audioimagination.com> wrote:
>
>> On 4/6/13 12:09 AM, Chris Rogers wrote:
>>
>>
>>>
>>>
>>> On Thu, Apr 4, 2013 at 6:57 PM, robert bristow-johnson <
>>> rbj@audioimagination.com <mailto:rbj@audioimagination.**com<rbj@audioimagination.com>>>
>>> wrote:
>>>
>>>     On 4/4/13 7:06 PM, Chris Rogers wrote:
>>>
>>>         Another aspect of the WaveShaperNode is anti-aliasing.  In
>>>         certain cases it would be great to be able to up-sample the
>>>         signal before applying the shaping, then down-sampling.  This
>>>         is to avoid the extremely harsh aliasing that can occur in
>>>         applications such as guitar amp simulations.  Once again we
>>>         could have an attribute .upsample ("none", "2x", "4x") or
>>>         something like that.  Then the default value for that would be
>>>         "none" I think.
>>>
>>>
>>>     just lurking, and i haven't looked at the code at all, but thought
>>>     i might mention a couple of things that might be applicable.
>>>
>>>     if you can get away from table lookup and implement the waveshaper
>>>     by use of a pure polynomial if finite order, you can get a solid
>>>     handle on aliasing.  a finite-order polynomial is not as general
>>>     and a general lookup table, but for the purposes of distortion (or
>>>     "warmth" or whatever) in audio, it might be closer to what you
>>>     want anyway.  you can fit polynomials to tube curves and the sort
>>>     pretty well.
>>>
>>>     the images generated is no higher in frequency than the order of
>>>     the polynomial (let's call that M) times the highest frequency.
>>>      if that highest frequency is potentially Nyquist, then upsampling
>>>     by a factor of N means that the highest frequency is the *new*
>>>     Nyquist/N.  that makes the highest frequency image (M/N)*Nyquist.
>>>      you can allow aliases as long as they don't get back into your
>>>     original baseband which is below the new Nyquist/N.  that means
>>>
>>>         2*Nyquist - (M/N)*Nyquist > Nyquist/N
>>>
>>>     or
>>>
>>>         2*N - M > 1
>>>
>>>     or
>>>
>>>         M <  2*N - 1
>>>
>>>     if you upsample by 2x, you can have a 3rd-order polynomial.  if
>>>     you upsample by 4x, you can have a 7th-order polynomial.
>>>
>>>     then a decent brick-wall LPF with cutoff at Nyquist/N to kill the
>>>     images and aliases.   then downsample by factor of N and you have
>>>     output.  you will get the distortion components you were meant to
>>>     get (harmonics) and no non-harmonic components which are the
>>>     tell-tales of aliasing and cheezy distortion.
>>>
>>>     you can do this with table lookup if you make sure the table ain't
>>>     defined to wildly (like if it's implementing a Mth-order
>>>     polynomial), have enough points in the table (memory is cheap),
>>>     and at least linearly interpolate between points.  how many points
>>>     you need (based on what interpolation is done between points) in
>>>     the table is something that i had done some analysis about long
>>>     ago, but i might be able to find notes.  if computational burden
>>>     is no problem, i might suggest implementing this as a polynomial
>>>     and use Horner's rule.
>>>
>>>     just an idea.
>>>
>>>
>>> Thanks Robert, this is really valuable information.  I'd still like to
>>> support general shaping curves and bit-crushing applications.  But I'd
>>> really like to get the highest quality sound and best general purpose
>>> approach that is possible, especially for these "warming" applications.
>>>
>>>
>> probably, for generality and for efficiency regarding speed, you might
>> want to implement the non-linear function simply with table lookup and
>> linear interpolation.  that is less computation than computing a 7th-order
>> polynomial directly using the Horner method.  but i might suggest that what
>> goes *into* that table are the points of a polynomial of limited order.
>>  neglecting the error from linear interpolation (which can be very, very
>> small if there are a decent number of points in the table), then they are
>> mathematically equivalent, and since it's usually the case that memory is
>> cheap, you may as well do this with a table.
>>
>> but if you define points in the table that would be the same as
>> evaluating the limited-order polynomial, then you still enjoy the benefits
>> of limited frequency to the images, and with enough upsampling (and
>> downsampling on the other end), you can totally lose the non-harmonic
>> aliasing (from foldover around Nyquist) that makes some digital distortion
>> algs sound cheesy.  again, you can do a 7th-order polynomial with no
>> aliasing if you upsample 4x and, at the output, LPF well and downsample 4x.
>>  and you can make a 7th-order polynomial fit practically any tube curve to
>> a very good fit.
>>
>> whether that 7th-order polynomial is implemented directly or is
>> implemented with a decently large lookup table and linear interpolation,
>> that shouldn't matter.  but if your table implements some wild-and-crazy
>> function with discontinuities or with amazing slopes and corners, that
>> might generate harmonics that fold over and cause aliases that you can't
>> get rid of.
>>
>>
>> --
>>
>> r b-j                  rbj@audioimagination.com
>>
>> "Imagination is more important than knowledge."
>>
>>
>>
>>
>>
>

Received on Monday, 13 May 2013 19:09:33 UTC