Search code examples
javascriptaudioweb-audio-api

createPeriodicWave from an array of sample values


I have a curve -- say, a sine curve -- that is sampled at uniform intervals into a Float32Array, called samples. The curve is sampled by value. If samples (with some rounding) was put on the screen, we would get something like the following:

 1.0 |    x           x
 0.5 |  x   x       x   x
 0.0 | x     x     x     x     x
-0.5 |        x   x       x   x
-1.0 |          x           x

And the contents of the samples array is something along these numbers:

0, 0.5, 1, 0.5, 0, -0.5, -1, -0.5, 0, ...

As you can see, the curve is represented by the value of the curve at each given sample. I would like to create a PeriodicWave from these sample values, which can be done by using AudioContext.createPeriodicWave().

However, this method accepts the following arguments instead of sampled values:

  • real: An array of cosine terms (traditionally the A terms).
  • imag: An array of sine terms (traditionally the B terms).

I'm not quite sure what these values mean in regard to an array of sampled values. How can I make a conversion from sampled values to cosine terms and sine terms?

Edit: the curve that is sampled is not necessarily a sine or cosine wave. It can take any arbitrary shape.


Solution

  • If you really just want to take a waveform, then just use an AudioBufferSource and loop it (as an AudioBuffer).

    PeriodicWaves are something different - they're a way of controlling the waveform of the Oscillator harmonically, by changing the relative coefficients of each harmonic. If you created a PeriodicWave with only the value "1" in the second slot of the "imag" array, you would get a sine wave. Likewise, you can create square, triangle, or sawtooth waves by controlling the higher harmonics - see https://en.wikipedia.org/wiki/Non-sinusoidal_waveform. These waves can end up being pretty rich -

    If you want to turn it into a PeriodicWave, you need to turn it into the set of relative harmonic strengths used by PeriodicWave, using an FFT algorithm (https://en.wikipedia.org/wiki/Discrete_Fourier_transform is a decent introduction). There are libraries on the net to do this, like DSP.js (https://github.com/corbanbrook/dsp.js/).

    (This used to be called Wavetable, but that was confusing too. Maybe it should have been renamed HarmonicWaveTable?)