Re: [web-audio-api] (OscillatorTypes): Oscillator types are not defined (#104)

> [Original comment](https://www.w3.org/Bugs/Public/show_bug.cgi?id=17366#1) by paul@paul.cx on W3C Bugzilla. Fri, 30 Aug 2013 18:01:38 GMT

I'd like to get the group's opinion on this, as this is a very noticeable problem. This node is not specified, and implementations have taken different routes to implement the basic waveforms (sine, square, triangle, sawtooth).
Ralph Giles has written a tool to visualize what the implementations are doing. I've modified it to put emphasis on some, and attached it to this bug. Simply unzip and load the html file in a browser that has OscillatorNode.

First, how implementation I read currently work:
- In Webkit/Blink, reading the code, an inverse fourrier transform is performed to generate a buffer that will be looped over. 
- In Gecko, we generate the waveform in the time domain directly.

Then, what are the perceptible differences:
- All the basic waveforms on all implementation have the same phase but the triangle on Webkit/Blink (which has a +PI/4 phase offset, and maybe an off-by-one). While not noticeable by ear when the signal is not mixed, this means that mixing a triangle OscillatorNode and an other OscillatorNode with another type will yield different results. It forces the authors to special case the triangle oscillator when they want to intentionally dephase two oscillators.
- Blink/Webkit seems to duck its signal (look at the RMS values at the bottom of the page, for pure signals) to avoid clipping, because of the ripples near the discontinuities.

We should really spec the phase of the basic waveforms.

`phi(t)` is the phase at time `t` (which is in samples), `frequency(t)` and `detune(t)` are the value of the `frequency` and `detune` AudioParam at time `t`, and are defined like so: 

finalFrequency = frequency * pow(2, detune / 1200.) [per spec]
phi = fmod(t * (finalFrequency * 2.0 * Pi / AudioContext.sampleRate), 1.0)

Now, the actual definitions, like so:

- "name of the waveform"
amplitude for phase `phi`
(description of the waveform, to be replaced by images in the actual spec text)

- "sine":
sin(phi)
(starts at zero, 1.0 at 0.25, zero at 0.5, -1.0 at 0.75)

- "square":
1.0 if phi is less than 0.5, -1.0 otherwise
(1.0 at zero, -1.0 at 0.5)

- "sawtooth":
2.0 * phi if phi  is greater than 0.5, 2.0 * (phi - 1.0) otherwise
(0.0 at phi == 0, 1.0 at phi == 0.5, -1.0 at phi == 1.0)

- "triangle": 
if phi is less than 0.25
  4.0 * phi
else if phi is less than 0.75
  1.0 - 4.0 * (phi - 0.25)
else
  4.0 * (phase - 0.75) - 1.0
(0.0 at phi == 0, 1.0 at phi == 0.25, -1.0 at phi == 0.75, 0.0 at phi == 1.0)

Then, onto the ducking problem, I think it would be valuable to have the same RMS level for all waveform types, across implementations, so authors don't have to fine-tune with gain node to get a uniform output. The RMS level for the basic waveforms using the above definition is well defined, we could use those as a reference.

---
Reply to this email directly or view it on GitHub:
https://github.com/WebAudio/web-audio-api/issues/104#issuecomment-24244225

Received on Wednesday, 11 September 2013 14:30:18 UTC