WebAudio / web-audio-api

The Web Audio API v1.0, developed by the W3C Audio WG
https://webaudio.github.io/web-audio-api/
Other
1.05k stars 167 forks source link

Bandlimited pulse oscillator with a-rate pulseWidth parameter #2418

Open svgeesus opened 8 years ago

svgeesus commented 8 years ago

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

hoch commented 8 years ago

We might want to do this as a separate node from OscillatorNode.

svgeesus commented 8 years ago

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.

svgeesus commented 8 years ago

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

hoch commented 5 years ago

Tentatively, to capture the idea in F2F:

interface VariPulseOscillator : AudioScheduledSourceNode {
  AudioParam frequency;
  AudioParam detune;
  AudioParam pulseWidth;
}
svgeesus commented 5 years ago

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.

svgeesus commented 4 years ago

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.

rtoy commented 4 years ago

Teleconf: Would be really nice to have a polyfill with a Worklet to see and hear what the oscillator does.

charlieroberts commented 4 years ago

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...

skratchdot commented 4 years ago

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!

rtoy commented 4 years ago

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.

Rumyra commented 4 years ago

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

rtoy commented 4 years ago

Teleconf: Also what about hard sync? We should be consistent with Oscillator

rtoy commented 4 years ago

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.

rtoy commented 4 years ago

Teleconf: Need to resolve WebAudio/web-audio-api-v2#1 and WebAudio/web-audio-api#2402 before we can finalize this.