Re: WaveShaperNode.curve

On 14 May, 2013, at 9:07 AM, "Robert O'Callahan" <robert@ocallahan.org> wrote:

> On Tue, May 14, 2013 at 2:58 PM, Srikumar Karaikudi Subramanian <srikumarks@gmail.com> wrote:
>> shaper.curve = new Float32Array(100);
>> for (var i = 0; i < 100; ++i) {
>>   // oops, at this point the array has been internally copied,
>>   // and while the code below doesn't throw an exception,
>>   // it effectively sets the curve property to an all-0 array,
>>   // which is not what the author has intended.
>>   shaper.curve[i] = whatever;
>> }
> 
> 
> This code will bomb anyway if the array is neutered after setting the curve (the length of a
> neutered array is 0).
> 
> That's a good thing. Code that fails obviously and synchronously is better than code that silently fails to work, from the point of view of an author trying to find bugs.

Agreed in general. What I was trying to point out was that if a dev would expect this code to modify the curve used by the shaper, neutering the array won't serve that purpose either.

The bigger inconvenience of neutering, as I've said before, is that a dev cannot now use the same shape curve array with two wave shaper nodes. If the system is to somehow sneak in behind the neutered array and get the contents, then there really needs to be a whole section in the spec on how objects are to respond to array properties when neutered arrays are passed 'cos it is all non-obvious. As a dev, I worry more about the following not working -

	var curve = new Float32Array(N);
	// ... fill up curve with data...
	shaper1.curve = shaper2.curve = curve;

> 
> Furthermore, what would be 
> the point of having a getter for the shaper.curve property if all it will provide is a neutered array? 	
> RoC's suggestion of a setCurve() without a getter is in this case a much cleaner solution.
> 
> We could arrange for the getter of 'curve' to return a new non-neutered array, with the old contents, if the original array has been neutered.

Possible solution, but this makes a copy anyway and raises further questions. If the first code is expected to work, when should the shaper node check that the contents of this new array has changed and update itself?

> 
> In general, please consider whether any "setBlah" qualifies as a full property before
> also including a getter for it. In this case, what we (devs) really need is a write-only property
> to avoid all this potential confusion. A setCurve() will offer a clear point where any consistency
> checks on the array can be expected to be performed.
> 
> Sounds good to me :-). Maybe we could add setCurve(), deprecate the attribute, make setting the attribute neuter the array, and make getting the attribute return a new array with the latest curve data.

This is close to best, but since compatibility is of interest here, the deprecated attribute shouldn't be spec'd to neuter because it'll break code that shares an array between shaper nodes. setCurve() should then be spec'd such that modifying the array after setCurve() is called should not affect the shaper node.

This situation is analogous to WebGL where a texture is created from an array of pixels. The pixel data is copied and the array with the pixel data is free to be modified with no expectation of immediately affecting the texture. The advantage of an internal copy is that the copy can use a more efficient representation if it so desires - for example, by supersampling the array using polynomial interpolation, for higher quality if that cost cannot be paid in the inner processing loop.

To sum up the points on this - 
	a) there is loss of functionality in neutering array attributes after they're set,
	b) what a node should do with neutered array data is non-obvious and needs separate specification if neutered arrays behave differently from zero-length arrays,
	c) there are potential efficiency advantages to a node keeping internal copies, and
	d) internal copies are more friendly to implementations that might sandbox the audio code in a separate process (like Chrome does with WebGL).

On a wider note, the only case I can find for neutering is for Blob objects after close() is called on them (http://dev.w3.org/2006/webapi/FileAPI/). That makes sense and I wouldn't expect to use a Blob after close()ing it. Any other cases that might serve as guides for when to neuter and when not to?

Best,
-Kumar

> 
> Rob
> -- 
> q“qIqfq qyqoquq qlqoqvqeq qtqhqoqsqeq qwqhqoq qlqoqvqeq qyqoquq,q qwqhqaqtq qcqrqeqdqiqtq qiqsq qtqhqaqtq qtqoq qyqoquq?q qEqvqeqnq qsqiqnqnqeqrqsq qlqoqvqeq qtqhqoqsqeq qwqhqoq qlqoqvqeq qtqhqeqmq.q qAqnqdq qiqfq qyqoquq qdqoq qgqoqoqdq qtqoq qtqhqoqsqeq qwqhqoq qaqrqeq qgqoqoqdq qtqoq qyqoquq,q qwqhqaqtq qcqrqeqdqiqtq qiqsq qtqhqaqtq qtqoq qyqoquq?q qEqvqeqnq qsqiqnqnqeqrqsq qdqoq qtqhqaqtq.q"

Received on Tuesday, 14 May 2013 05:58:39 UTC