[Bug 17366] (OscillatorTypes): Oscillator types are not defined

https://www.w3.org/Bugs/Public/show_bug.cgi?id=17366

paul@paul.cx <padenot@mozilla.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |padenot@mozilla.com
           Assignee|dave.null@w3.org            |padenot@mozilla.com

--- Comment #2 from paul@paul.cx <padenot@mozilla.com> ---
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.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Received on Friday, 30 August 2013 18:01:40 UTC