- From: Chris Rogers <crogers@google.com>
- Date: Wed, 15 May 2013 14:34:50 -0700
- To: rbj@audioimagination.com
- Cc: "public-audio@w3.org" <public-audio@w3.org>
- Message-ID: <CA+EzO0mxsZL9heLa4-dHXLhUCCWZpj+6Cg0hVHuR=USbKeYUjw@mail.gmail.com>
On Mon, May 13, 2013 at 8:26 PM, <rbj@audioimagination.com> wrote: > > ---------------------------- Original Message ---------------------------- > Subject: Re: Interpolation on WaveShaperNode? > From: "Chris Rogers" <crogers@google.com> > Date: Mon, May 13, 2013 3:09 pm > To: "Ehsan Akhgari" <ehsan.akhgari@gmail.com> > Cc: rbj@audioimagination.com > "public-audio@w3.org" <public-audio@w3.org> > -------------------------------------------------------------------------- > > > > > > 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. > > > > remember, for an oversampling ratio of N, you can define the waveshaping > function as any polynomial of order up to 2N-1. so you can have a > 3rd-order polynomial mapping function with 2x oversampling and filter out > all harmonics over the original Nyquist (the top octave in the 2x > oversampled spectrum) and downsample back to 1x. with 4x oversampling, > your polynomial can be up to 7th order. i s'pose you can oversample by 3x > and put in a 5th-order polynomial. > > the LPF at the higher sampling rate might be a little costly. if it's > IIR, you have to run it on every sample at the 2x or 3x or 4x rate, even > the samples you will throw away in downsampling. if it's FIR, then you > need only run it for every output sample you're gonna keep. but FIR > filters often cost more than IIR filters (to get the same or similar filter > jobs done), even when the IIR is running at an oversampled rate. > > if the waveshaping function is implemented as a table lookup with linear > interpolation, that's fine but put in a lotta points in the > piecewise-linear function. and if it defines something other than a smooth > polynomial of limited order, then expect that there may be aliases that > creep down into your original baseband (what's covered with 1x sampling). > > if you're implementing the waveshaping function as a polynomial, then > Horner's method is probably the most efficient way to do it. > Thanks, I'm trying to get this going so really appreciate the advice. Yesterday, I wrote a 2x up and down sampler each of which uses FIR filters of length 64. Performance is pretty good. The up-sampling filter is basically a windowed sinc() function shifted 1/2 sample to create the in-between samples, while the down-sampling filter is a half-band filter, which is nice since every other coefficient is 0, allowing a nice optimization since we also only need to generate every other sample... It should be easy to chain two up-samplers together to get 4x, of course with a performance penalty. Since developers can set any table they want, including the polynomials you suggest they can avoid aliasing completely, or at least minimize the aliasing. In the past, playing around with these shaping curves I've found that it's not only avoiding the aliasing that is interesting, but also the dynamics-shaping of the curves themselves, since they act kind of like instantaneous compressors, so the shapes of the curves matter a lot for the dynamics. It seems like there are some good design tradeoffs in choosing curves that have no aliasing versus those which have maybe a little bit (but is helped by the oversampling), but have good sounding dynamics-shaping/compression. Chris > > > r b-j > > > > > > >> > >> > >> 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 Wednesday, 15 May 2013 21:35:18 UTC