How to get the real and imag arrays for createPeriodicWave for a piecewise periodic function?

125 Views Asked by At

The pattern of the wave is as follows:

0.0 - 0.5 => low,
0.5 - 1.0 => high,
1.0 - 2.0 => low,
2.0 - 2.5 => high,
2.5 - 4.0 => low,
4.0 - 4.5 => high,
4.5 - 6.5 => low,
6.5 - 7.0 => high,

enter image description here

The pulses are equal but the time between different pulses increases as follows: 0.5, 1.0, 1.5, 2.0. This pattern repeats itself so that if we keep going the next iteration would look like this:

7.0 - 7.5 => low,
7.5 - 8.0 => high,
8.0 - 9.0 => low,
9.0 - 9.5 => high,
9.5 - 11.0 => low,
11.0 - 11.5 => high,
11.5 - 13.5 => low,
13.5 - 14.0 => high,

enter image description here

I believe the lows should be -1 instead of 0 (not sure though). How can I get the real and imag arrays for this waveform?

https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/createPeriodicWave

2

There are 2 best solutions below

0
On

The createPeriodicWave() requires a signal in the frequency domain, that means you need to transform your signal from the time domain to the frequency domain using a (Discrete) Fourier Transformation (sometimes called DFT for short) to get the data format for createPeriodicWave(). More information can be found here.

createPeriodicWave() will perform a inverse Fourier Transformation back to the time domain (which you already had at the beginning), so it makes no sense to use createPeriodicWave(). Instead you can directly feed your sample data into an AudioBuffer

0
On

There is no indication of preferred language in this question but in Node there is a version of the Fast Fourier Transform (FFT) With this you can input the test data (1 to 0 or 1 to -1 or whatever as the dc element will be removed).

Please see https://www.npmjs.com/package/fft-js for details.

Once you have it installed (npm i fft-js) you can do something like this

var fft = require('fft-js').fft,
    fftUtil = require('fft-js').util,
    signal = [1,0,1,0];

var phasors= fft(signal);

var frequencies = fftUtil.fftFreq(phasors, 8000), // Sample rate and coef is just used for length, and frequency step
    magnitudes = fftUtil.fftMag(phasors); 

var both = frequencies.map(function (f, ix) {
    return {frequency: f, magnitude: magnitudes[ix]};
});

console.log(both);

I would also break the sample into something smaller so say 1 unit is the time of the on pulse (0.5 seconds?) so would be something like 0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,1,0,0,1,0,0,0,1,0,0,0,0,1,