Reputation: 3692
I'm having trouble understanding how the transfer function for a WaveShaperNode in the Web Audio API works. As I understand, a transfer function is a waveshaper which takes in a signal input x and produces a new signal y. So,
y = f(x)
I understand that if x equals zero, then so should y. Therefore, 0 = f(0)
. And that to fit in an appropriate range, y should be between [-1, 1], so this function: y = x / (1 + |x|)
limits the output range to [-1, 1]. And that Chebyshev Polynomials are useful for transfer functions used to "distort" musical input signals.
But for a transfer function you need the input signal x in order to manipulate it and create an output y. However, with a WaveShaperNode in the Web Audio API, you don't have access to the original input x (or do you?). Often I see algorithms like:
for(var i = 0; i < sampleRate; i++){
var x = i * 2 / sampleRate - 1;
this.curve[i] = (3 + distortionAmount) * x * 20 * (Math.PI / 180) / (Math.PI + distortionAmount * Math.abs(x));
}
Where, in the above code, this.curve
is a Float32Array representing the graphing of each sample frame. And I assume x
here is supposed to represent the input audio signal. Yet, it doesn't actually represent the exact input audio signal. Is this because it just represents an average sinusoid and the actual input doesn't matter? Does the WaveShaperNode take the original input x and use (multiply?) the general curve we created to calculate the output y?
Upvotes: 0
Views: 747
Reputation: 13928
The WaveShaper node does not enable generic transfer functions, per se - but you can use it to do that. To answer your question - x is the offset into the array, with a little preprocessing.
The curve you give to the waveshaper is like a lookup table for x - spread across the range [-1,1]. Y does not need to be in [-1,1] - but x does. So, to solve f(x) for x in [-1,1], you just get the value at
curve[ Math.floor( (x+1)/2 * (curve.length-1) ) ];
or something like that.
It's not actually true that if x equals zero, then so must y; but it's likely. You could use the waveshaper to implement a DC offset, for example.
That "sampleRate" bit in your demo code is goofy - you should use maxint, not samplerate, to determine the size of your array. sampleRate is a time-domain thing, and waveshaper only operates in the amplitude vector.
Upvotes: 2
Reputation: 70733
The WaveShaperNode is described as applying a non-linear distortion. As such it would not have a classical linear time-invariant transfer function (which strictly only applies to linear distortions).
Upvotes: 0