Open svgeesus opened 8 years ago
We might want to do this as a separate node from OscillatorNode.
I agree. Firstly, each predefined type in OscillatorNode is defined in terms of the equivalent real and imaginary arrays, which would not be the case here. Secondly, this new node has an a-rate parameter for the width, which OscillatorNode does not have. I suggest we initially just do a pulse oscillator; @hoch mentioned at the f2f non-50-50 mark-space waveforms like asymmetric triangle or warped sine and I agree that these are possible and I have seen these occasionally (in the analog domain, I mean), but the pulse wave is the major missing feature here which is widely used musically.
Useful links: Antialiased oscillators http://www.yofiel.com/software/cycling-74-patches/antialiased-oscillators
Alias-Free Digital Synthesis of Classic Analog Waveform https://ccrma.stanford.edu/~stilti/papers/blit.pdf
Perceptually informed synthesis of bandlimited classical waveforms using integrated polynomial interpolation http://mac.kaist.ac.kr/pubs/ValimakiPeknenNam-jasa2012.pdf
Edit: https://www.cs.cmu.edu/~eli/papers/icmc01-hardsync.pdf
Tentatively, to capture the idea in F2F:
interface VariPulseOscillator : AudioScheduledSourceNode {
AudioParam frequency;
AudioParam detune;
AudioParam pulseWidth;
}
Also, pulseWidth
should be in the range 0.0 to 1.0, with 0.5 meaning a square wave (equal mark/space ratio).
Some hardware synths slightly constrain the range (like 0.01 to 0.99) to prevent fat-fingered users setting an all-mark or all-space pulse which has zero AC component and thus, no sound. But we should not do that IMO.
How much detail should the specification have about the implementation? Obviously it needs to say the output must be bandlimited but do we want to specify BLIT or leave it up to implementations? OscillatorNode is fairly specific on details.
Teleconf: Would be really nice to have a polyfill with a Worklet to see and hear what the oscillator does.
just a quick note that FM PWM is a nice option... I use polyblep for other waveforms in gibber, but FM for PWM because it just seems to sound better.to me subjectively. http://scp.web.elte.hu/papers/synthesis1.pdf
Although I noticed that @svgeesus linked a paper on oscillators with hard sync which I don't think would work using an FM approach (I could be wrong about this). Would love to see hard sync support in oscillator nodes some day...
I created a demo here: https://github.com/skratchdot/web-audio-api-v2-issue-7
But it's not quite right. I need to read some of the articles posted, and read more about the math / audio dsp side of things. I'm coming from a "web dev" perspective, so am probably missing something simple.
Anyways, if anyone wants to fix this "overly complex" demo, I think you should just be able to edit the worklet code here: https://github.com/skratchdot/web-audio-api-v2-issue-7/blob/master/public/pulse-oscillator.js
edit on 8/19/2020: I removed the unneeded images from this comment. Also, I've updated the demo to use some polyblep code I ported, but I still need to try to implement a minblep solution (I need to understand it first though 🤣). The original solution I came up with was a naive solution (and wasn't bandlimited). I re-learned a lot about dsp this week!
From today's teleconf, a simple design was done:
interface PulseWidthOscillatorNode : AudioScheduledSourceNode {
constructor (BaseAudioContext context, optional PulseWidthOscillatorOptions options = {});
readonly attribute AudioParam frequency;
readonly attribute AudioParam detune;
readonly attribute AudioParam pulseWidth;
};
dictionary PulseWidthOscillatorOptions : AudioNodeOptions {
float frequency = 440;
float detune = 0;
float pulseWidth = 0.5;
};
This oscillator is bandlimited and goes between -1 and 1. The pulseWidth range is [0,1]
, where a value of 0 means the output is a constant -1 and a value of 1 means the output is a constant +1. A value of 0.5 is a square wave.
Would we need phase offset here as per https://github.com/WebAudio/web-audio-api-v2/issues/1 and https://github.com/WebAudio/web-audio-api-v2/issues/9?
Came up in wg/cg meeting
Teleconf: Also what about hard sync? We should be consistent with Oscillator
Oh, I think I got the output inverted. To match a square wave, the output should start at +1 and go to -1. So a pulseWidth near 0 is a little bit of +1 followed by mostly -1; a width close to 1 is mostly +1 followed by a little bit of -1.
Teleconf: Need to resolve WebAudio/web-audio-api-v2#1 and WebAudio/web-audio-api#2402 before we can finalize this.
Unlike the existing square wave, here the mark-space ration is changeable and modulatable. This is a classic effect and (unlike a static mark:space ratio) cannot be achieved using the FFT arrays on a custom oscillator node.
This was asked for several times at WAC2016