Open delucis opened 8 years ago
On Sat, Dec 5, 2015 at 8:14 PM, Chris Swithinbank notifications@github.com wrote:
The current exponentialRampToValueAtTime() http://webaudio.github.io/web-audio-api/#widl-AudioParam-exponentialRampToValueAtTime-AudioParam-float-value-double-endTime method seems fairly shaky, not least because of its failure to accept ramps to/from zero, but also because the exponential curve it implements is not a quadratic curve.
Not sure what this means. It's called exponential because it's exponential, not quadratic.
The draft API states http://webaudio.github.io/web-audio-api/#widl-AudioParam-exponentialRampToValueAtTime-AudioParam-float-value-double-endTime that “parameters representing filter frequencies and playback rate are best changed exponentially because of the way humans perceive sound,” which would suggest that a default exponential curve should be quadratic, complementing how frequency and amplitude scale perceptually.
What are the reasons for the current proposed model (below)?
[image: image] https://cloud.githubusercontent.com/assets/357379/11609919/8c389814-9b61-11e5-9711-6ea04844ad35.png
Might it not be better to implement a single rampToValueAtTime() method, replacing both the linear and exponential ramp methods, which accepts a third optional argument for the exponent?
Well, frequencies are exponential, I think. You move up an octave and the frequency doubles. That's exponential. The frequencies for the notes on a piano are powers of two.
This could be implemented using the following (based on the existing model for linearRampToValueAtTime() http://webaudio.github.io/web-audio-api/#widl-AudioParam-linearRampToValueAtTime-AudioParam-float-value-double-endTime), where k is the exponent.
[image: image] https://cloud.githubusercontent.com/assets/357379/11610981/1e578058-9b84-11e5-9327-ad8e33f717c8.png
k = 1, resulting in a linear ramp (equivalent to linearRampToValueAtTime()) could be the default exponent, k = 2 would produce a quadratic curve, while k < 1 would produce logarithmic curves. k = 4.2 would come close to replicating the current exponentialRampToValueAtTime() function. Keyword aliases (“linear” => 1; “exponential” => 2) could also be a possibility.
I think your curve with k=4.2 only works because of the particular values of v0, v1, T1, and T0 that you used in the graph.
You can easily achieve what you want with setValueCurveAtTime, I think.
[image: image] https://cloud.githubusercontent.com/assets/357379/11611624/632df09c-9ba5-11e5-88f7-893dd980c40f.png
— Reply to this email directly or view it on GitHub https://github.com/WebAudio/web-audio-api/issues/671.
Ray
If there are no additional comments, I would like to close this soon.
Apologies for the slow reply!
You’re right about the k=4.2 being dependent on particular values — my proposed function could not consistently replace the current exponential function.
However, I would still argue for something along the lines of a rampToValueAtTime()
with optional exponent as I suggested above. setValueCurveAtTime()
requires an array to define the curve, which could of course reproduce a non-linear ramp, but that is relatively clumsy. setValueCurveAtTime()
seems more suited to envelopes and the like than ramps. (The MDN demo is just such an envelope.)
For example, the current exponentialRampToValueAtTime()
is not perceptually smooth with regards to either gain or frequency ramping, a quadratic ramp would sound smoother. To achieve that with setValueCurveAtTime()
would require an array (which is linearly interpolated between points, so you’d have to ensure enough points for longer ramp times). To achieve that with a ramp could be as simple as rampToValueAtTime(targetVal, targetTime, exponent)
with the third argument optional (defaulting to 1, i.e. linear).
Does that make a bit more sense?
Do you have an example where exponentialRampToValueAtTime()
is not perceptually smooth?
I don't have any real objections to your proposal, except that it's now a feature request and not a bug in exponential ramps.
I’ll try to find time in the coming days to build a demo. I noticed it most with slower fade-ins: a linear ramp sounding loud too soon; the exponential ramp sounding loud too suddenly towards the end.
Agreed this is now a feature request.
Thanks for looking into this. Perhaps setTargetAtTime will produce the kind of fade-in you want?
Anyway, marking this as a Feature Request/Missing Feature.
Note that arbitrary "laws" can be implemented using AudioWorkletNode piped into AudioParams.
Hello, I've just stumbled upon this.
Perhaps what @delucis is looking for is something like polynomialRampToValueAtTime()
.
The only use-case I can find right now is to automate equal-power cross-fading or panning.
Here's an existing example of equal-power cross-fading that is not automated: https://webaudioapi.com/samples/crossfade/ (Also mirrored on HTML5rocks: https://www.html5rocks.com/en/tutorials/webaudio/intro/#toc-xfade )
If one wanted to perform such automation, I believe it's currently possible with linearRampToValueAtTime()
, or with setValueCurveAtTime()
using correct values for the first argument's element.
Another solution-proposal to this problem without adding an extra method would be an extra argument for setValueCurveAtTime()
. Right now, setValueCurveAtTime()
interpolates linearly between values. Allowing a fourth argument which specifies the polynomial-degree of interpolation would solve this problem.
The example I linked above used a cosine function; however, a polynomial solution is also available (see: https://dsp.stackexchange.com/a/36778)
Examples of automation equal-power cross-fading:
// Assume gainNodeA.gain.value, gainNodeB.gain.value is current at 1 and 0 respectively
// With current specs
let curveLength = 20;
let curveA = (new Float32Array(curveLength)).fill(0).map((x,i) => (i/(curveLength-1))**0.5);
let curveB = curveA.reverse();
// This will crossfade between two signals within 2 seconds, linearly interpolating a curve
gainNodeA.gain.setValueCurveAtTime(curveA, blah.currentTime, 2);
gainNodeB.gain.setValueCurveAtTime(curveB, blah.currentTime, 2);
// --------------------
// Proposed ?
// using polynomialRampToValueAtTime(value, endTime, polynomialDegree)
gainNodeA.gain.polynomialRampToValueAtTime(0, blah.currentTime + 2, 0.5);
gainNodeB.gain.polynomialRampToValueAtTime(1, blah.currentTime + 2, 0.5);
// modified setValueCurveAtTime(values, startTime, duration, polyDegree)
gainNodeA.gain.setValueCurveAtTime([1.0, 0.0], blah.currentTime, 2, 0.5);
gainNodeB.gain.setValueCurveAtTime([0.0, 1.0], blah.currentTime, 2, 0.5);
setValueCurveAtTime()
?
Well, yes it can be. The example code above shows. I think the only benefits this would reap from becoming native is that you harvest some native computation or optimization that the implementations might have (e.g. curveLength
above is controlled in terms of the duration of the cross-fade)setTargetAtTime()
?
Can polynomial curves be approximated by this method? I don't have the time to check this right now (but I doubt it could), but one advantage of polynomial curves is that you can reach 0. This is currently not allowed using with setTargetAtTime()
nor exponentialRampToValueAtTime()
AFAIK.Virtual F2F:
Teleconf: We should do this, especially if it's common as Paul says in https://github.com/WebAudio/web-audio-api-v2/issues/22#issuecomment-642076903.
Proposal:
AudioParam.powerRampToValueAtTime(v1, t1, k)
Same parameters and order like linearRampToValueAtTime
, with the an additional 3rd parameter, k
, that specifies the power law. The formula would be the one given in https://github.com/WebAudio/web-audio-api-v2/issues/22#issue-494354028.
k
should be constrained to be non-negative perhaps?
F2F meeting: API in https://github.com/WebAudio/web-audio-api-v2/issues/22#issuecomment-705848406 is good. Nothing more needed except writing up the spec.
The current
exponentialRampToValueAtTime()
method seems fairly shaky, not least because of its failure to accept ramps to/from zero, but also because the exponential curve it implements is not a quadratic curve.The draft API states that “parameters representing filter frequencies and playback rate are best changed exponentially because of the way humans perceive sound,” which would suggest that a default exponential curve should be quadratic, complementing how frequency and amplitude scale perceptually.
What are the reasons for the current proposed model (below)?
Might it not be better to implement a single
rampToValueAtTime()
method, replacing both the linear and exponential ramp methods, which accepts a third optional argument for the exponent?This could be implemented using the following (based on the existing model for
linearRampToValueAtTime()
), where _k_ is the exponent._k = 1_, resulting in a linear ramp (equivalent to
linearRampToValueAtTime()
) could be the default exponent, _k = 2_ would produce a quadratic curve, while _k < 1_ would produce logarithmic curves. _k = 4.2_ would come close to replicating the currentexponentialRampToValueAtTime()
function. Keyword aliases (“linear” => 1; “exponential” => 2) could also be a possibility.