<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>129333</bug_id>
          
          <creation_ts>2014-02-25 13:43:08 -0800</creation_ts>
          <short_desc>WaveShaperNode interpolation does not match specification</short_desc>
          <delta_ts>2014-02-28 01:35:38 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>Web Audio</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>PC</rep_platform>
          <op_sys>Windows XP</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Andy Harman">webaudio.at.pendragon</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>crogers</cc>
    
    <cc>webaudio.at.pendragon</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>984486</commentid>
    <comment_count>0</comment_count>
      <attachid>225181</attachid>
    <who name="Andy Harman">webaudio.at.pendragon</who>
    <bug_when>2014-02-25 13:43:08 -0800</bug_when>
    <thetext>Created attachment 225181
HTML page that demonstates the bug (updated to work in Firefox too).

The interpolation for the Web Audio WaveShaperNode does not work properly.

I have created the follow JavaScript to demonstrate the 2 problems:
var c=new webkitOfflineAudioContext(1, 23, 48000);

//Create input values between -1.1 and + 1.1.
var b=c.createBuffer(1, 23, 48000);
var d=b.getChannelData(0);
for (var i=0; i&lt;23; i++){ d[i]=(i*.1)-1.1; }
var src=c.createBufferSource();
src.buffer=b;
src.start(0);

//Simple wave-shaper. It should map -1 to 0, 0 to 1, and +1 to 0 - and interpolate all
//points between.
var ws=c.createWaveShaper();
var curve=new Float32Array(3);
curve[0]=0;
curve[1]=1;
curve[2]=0;
ws.curve=curve;
src.connect(ws);
ws.connect(c.destination);

//Execute.
c.oncomplete=function(ev){
  var outputData=ev.renderedBuffer.getChannelData(0);
  var msgItems=[];
  for (var i=0; i&lt;23; i++){
    msgItems.push(&quot;Input value &quot; + d[i].toFixed(4) +
      &quot; =&gt; output value &quot; + outputData[i].toFixed(4));
  }
  alert(msgItems.join(&quot;\n&quot;));
};
c.startRendering();

The specification says &quot;Any sample value less than -1 will correspond to the first value in the curve array.&quot;
* An input of -1.1 returns a value -0.1500, it should return 0.0000

The specification says &quot;Each input sample within this range will index into the shaping curve
with a signal level of zero corresponding to the center value of the curve array.&quot;
* An input of 0 returns a value of 0.5000, it should return 1.0000
* An input of 0.4 returns a value of 0.0000, it should return 0.8000

The problem appears to be in WaveShaperDSPKernel.cpp - I think it should be changed to something like:

double virtualIndex = 0.5 * (input + 1) * curveLength;
double output;
if (virtualIndex &lt;= -1) {
  output = curve[0];
} else if (virtualIndex &gt;= curve[curveLength-1]) {
  output = curve[curveLength-1];
} else {
  var index1 = (int)virtualIndex;
  var value1 = curve[index1];
  var value2 = curve[index1+1];
  var interpolationFactor = virtualIndex - index1;
  output = (1.0 - interpolationFactor) * value1 + interpolationFactor * value2;
}

The current test HTML page only tests input values that fall between -1 and +1 - and the
error from the mid-point and end-point of the curve are disguised by the large number of
elements in the curve array.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>985503</commentid>
    <comment_count>1</comment_count>
      <attachid>225181</attachid>
    <who name="Andy Harman">webaudio.at.pendragon</who>
    <bug_when>2014-02-28 01:35:38 -0800</bug_when>
    <thetext>Comment on attachment 225181
HTML page that demonstates the bug (updated to work in Firefox too).

&lt;html&gt;
&lt;body&gt;
&lt;pre&gt;
The interpolation for the Web Audio WaveShaperNode does not work properly.

I have created the follow JavaScript to demonstrate the 2 problems:
var audioContextClass=window.OfflineAudioContext||webkitOfflineAudioContext
var c=new audioContextClass(1, 23, 48000);

//Create input values between -1.1 and + 1.1.
var b=c.createBuffer(1, 23, 48000);
var d=b.getChannelData(0);
for (var i=0; i&lt;23; i++){ d[i]=(i*.1)-1.1; }
var src=c.createBufferSource();
src.buffer=b;
src.start(0);

//Simple wave-shaper. It should map -1 to 0, 0 to 1, and +1 to 0 - and interpolate all
//points between.
var ws=c.createWaveShaper();
var curve=new Float32Array(3);
curve[0]=0;
curve[1]=1;
curve[2]=0;
ws.curve=curve;
src.connect(ws);
ws.connect(c.destination);

//Execute.
c.oncomplete=function(ev){
  var inputData=b.getChannelData(0);
  var outputData=ev.renderedBuffer.getChannelData(0);
  var msgItems=[];
  for (var i=0; i&lt;23; i++){
    msgItems.push(&quot;Input value &quot; + inputData[i].toFixed(4) +
      &quot; =&gt; output value &quot; + outputData[i].toFixed(4));
  }
  alert(msgItems.join(&quot;\n&quot;));
};
c.startRendering();

The specification says &quot;Any sample value less than -1 will correspond to the first value in the curve array.&quot;
* In Chrome, an input of -1.1 returns a value -0.1500, it should return 0.0000

The specification says &quot;Each input sample within this range will index into the shaping curve
with a signal level of zero corresponding to the center value of the curve array.&quot;
* In Chrome and FireFox, an input of 0 returns a value of 0.5000, it should return 1.0000
* In Chrome and FireFox, an input of 0.4 returns a value of 0.0000, it should return 0.8000

The problem appears to be in WaveShaperDSPKernel.cpp in the webkit source code - I think it should be
something like this:

double virtualIndex = 0.5 * (input + 1) * curveLength;
double output;
if (virtualIndex &lt;= -1) {
  output = curve[0];
} else if (virtualIndex &gt;= curve[curveLength-1]) {
  output = curve[curveLength-1];
} else {
  int index1 = static_cast&lt;int&gt;(virtualIndex);
  double value1 = curve[index1];
  double value2 = curve[index1+1];
  double interpolationFactor = virtualIndex - index1;
  output = (1.0 - interpolationFactor) * value1 + interpolationFactor * value2;
}

The current webkit test HTML page only tests input values that fall between -1 and +1. The
error from the mid-point and end-point of the curve are disguised by the large number of
elements in the tested curve array.
&lt;/pre&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
var audioContextClass=(window.OfflineAudioContext||webkitOfflineAudioContext);
var c=new audioContextClass(1, 23, 48000);

//Create input values between -1.1 and + 1.1.
var b=c.createBuffer(1, 23, 48000);
var d=b.getChannelData(0);
for (var i=0; i&lt;23; i++){ d[i]=(i*.1)-1.1; }
var src=c.createBufferSource();
src.buffer=b;
src.start(0);

//Simple wave-shaper.
var ws=c.createWaveShaper();
var curve=new Float32Array(3);
curve[0]=0;
curve[1]=1;
curve[2]=0;
ws.curve=curve;
src.connect(ws);
ws.connect(c.destination);

//Execute.
c.oncomplete=function(ev){
  var inputData=b.getChannelData(0);
  var outputData=ev.renderedBuffer.getChannelData(0);
  var msgItems=[];
  for (var i=0; i&lt;23; i++){
    msgItems.push(&quot;Input value &quot; + inputData[i].toFixed(4) +
      &quot; =&gt; output value &quot; + outputData[i].toFixed(4));
  }
  alert(msgItems.join(&quot;\n&quot;));
};
c.startRendering();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>225181</attachid>
            <date>2014-02-25 13:43:08 -0800</date>
            <delta_ts>2014-02-28 01:35:38 -0800</delta_ts>
            <desc>HTML page that demonstates the bug (updated to work in Firefox too).</desc>
            <filename>test.html</filename>
            <type>text/html</type>
            <size>3151</size>
            <attacher name="Andy Harman">webaudio.at.pendragon</attacher>
            
              <data encoding="base64">PGh0bWw+DQo8Ym9keT4NCjxwcmU+DQpUaGUgaW50ZXJwb2xhdGlvbiBmb3IgdGhlIFdlYiBBdWRp
byBXYXZlU2hhcGVyTm9kZSBkb2VzIG5vdCB3b3JrIHByb3Blcmx5Lg0KDQpJIGhhdmUgY3JlYXRl
ZCB0aGUgZm9sbG93IEphdmFTY3JpcHQgdG8gZGVtb25zdHJhdGUgdGhlIDIgcHJvYmxlbXM6DQp2
YXIgYz1uZXcgd2Via2l0T2ZmbGluZUF1ZGlvQ29udGV4dCgxLCAyMywgNDgwMDApOw0KDQovL0Ny
ZWF0ZSBpbnB1dCB2YWx1ZXMgYmV0d2VlbiAtMS4xIGFuZCArIDEuMS4NCnZhciBiPWMuY3JlYXRl
QnVmZmVyKDEsIDIzLCA0ODAwMCk7DQp2YXIgZD1iLmdldENoYW5uZWxEYXRhKDApOw0KZm9yICh2
YXIgaT0wOyBpPDIzOyBpKyspeyBkW2ldPShpKi4xKS0xLjE7IH0NCnZhciBzcmM9Yy5jcmVhdGVC
dWZmZXJTb3VyY2UoKTsNCnNyYy5idWZmZXI9YjsNCnNyYy5zdGFydCgwKTsNCg0KLy9TaW1wbGUg
d2F2ZS1zaGFwZXIuIEl0IHNob3VsZCBtYXAgLTEgdG8gMCwgMCB0byAxLCBhbmQgKzEgdG8gMCAt
IGFuZCBpbnRlcnBvbGF0ZSBhbGwNCi8vcG9pbnRzIGJldHdlZW4uDQp2YXIgd3M9Yy5jcmVhdGVX
YXZlU2hhcGVyKCk7DQp2YXIgY3VydmU9bmV3IEZsb2F0MzJBcnJheSgzKTsNCmN1cnZlWzBdPTA7
DQpjdXJ2ZVsxXT0xOw0KY3VydmVbMl09MDsNCndzLmN1cnZlPWN1cnZlOw0Kc3JjLmNvbm5lY3Qo
d3MpOw0Kd3MuY29ubmVjdChjLmRlc3RpbmF0aW9uKTsNCg0KLy9FeGVjdXRlLg0KYy5vbmNvbXBs
ZXRlPWZ1bmN0aW9uKGV2KXsNCiAgdmFyIG91dHB1dERhdGE9ZXYucmVuZGVyZWRCdWZmZXIuZ2V0
Q2hhbm5lbERhdGEoMCk7DQogIHZhciBtc2dJdGVtcz1bXTsNCiAgZm9yICh2YXIgaT0wOyBpPDIz
OyBpKyspew0KICAgIG1zZ0l0ZW1zLnB1c2goIklucHV0IHZhbHVlICIgKyBkW2ldLnRvRml4ZWQo
NCkgKw0KICAgICAgIiA9PiBvdXRwdXQgdmFsdWUgIiArIG91dHB1dERhdGFbaV0udG9GaXhlZCg0
KSk7DQogIH0NCiAgYWxlcnQobXNnSXRlbXMuam9pbigiXG4iKSk7DQp9Ow0KYy5zdGFydFJlbmRl
cmluZygpOw0KDQpUaGUgc3BlY2lmaWNhdGlvbiBzYXlzICJBbnkgc2FtcGxlIHZhbHVlIGxlc3Mg
dGhhbiAtMSB3aWxsIGNvcnJlc3BvbmQgdG8gdGhlIGZpcnN0IHZhbHVlIGluIHRoZSBjdXJ2ZSBh
cnJheS4iDQoqIEFuIGlucHV0IG9mIC0xLjEgcmV0dXJucyBhIHZhbHVlIC0wLjE1MDAsIGl0IHNo
b3VsZCByZXR1cm4gMC4wMDAwDQoNClRoZSBzcGVjaWZpY2F0aW9uIHNheXMgIkVhY2ggaW5wdXQg
c2FtcGxlIHdpdGhpbiB0aGlzIHJhbmdlIHdpbGwgaW5kZXggaW50byB0aGUgc2hhcGluZyBjdXJ2
ZQ0Kd2l0aCBhIHNpZ25hbCBsZXZlbCBvZiB6ZXJvIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGNlbnRl
ciB2YWx1ZSBvZiB0aGUgY3VydmUgYXJyYXkuIg0KKiBBbiBpbnB1dCBvZiAwIHJldHVybnMgYSB2
YWx1ZSBvZiAwLjUwMDAsIGl0IHNob3VsZCByZXR1cm4gMS4wMDAwDQoqIEFuIGlucHV0IG9mIDAu
NCByZXR1cm5zIGEgdmFsdWUgb2YgMC4wMDAwLCBpdCBzaG91bGQgcmV0dXJuIDAuODAwMA0KDQpU
aGUgcHJvYmxlbSBhcHBlYXJzIHRvIGJlIGluIFdhdmVTaGFwZXJEU1BLZXJuZWwuY3BwIC0gSSB0
aGluayBpdCBzaG91bGQgYmUgc29tZXRoaW5nIGxpa2UgdGhpczoNCg0KZG91YmxlIHZpcnR1YWxJ
bmRleCA9IDAuNSAqIChpbnB1dCArIDEpICogY3VydmVMZW5ndGg7DQpkb3VibGUgb3V0cHV0Ow0K
aWYgKHZpcnR1YWxJbmRleCA8PSAtMSkgew0KICBvdXRwdXQgPSBjdXJ2ZVswXTsNCn0gZWxzZSBp
ZiAodmlydHVhbEluZGV4ID49IGN1cnZlW2N1cnZlTGVuZ3RoLTFdKSB7DQogIG91dHB1dCA9IGN1
cnZlW2N1cnZlTGVuZ3RoLTFdOw0KfSBlbHNlIHsNCiAgdmFyIGluZGV4MSA9IChpbnQpdmlydHVh
bEluZGV4Ow0KICB2YXIgdmFsdWUxID0gY3VydmVbaW5kZXgxXTsNCiAgdmFyIHZhbHVlMiA9IGN1
cnZlW2luZGV4MSsxXTsNCiAgdmFyIGludGVycG9sYXRpb25GYWN0b3IgPSB2aXJ0dWFsSW5kZXgg
LSBpbmRleDE7DQogIG91dHB1dCA9ICgxLjAgLSBpbnRlcnBvbGF0aW9uRmFjdG9yKSAqIHZhbHVl
MSArIGludGVycG9sYXRpb25GYWN0b3IgKiB2YWx1ZTI7DQp9DQoNClRoZSBjdXJyZW50IHRlc3Qg
SFRNTCBwYWdlIG9ubHkgdGVzdHMgaW5wdXQgdmFsdWVzIHRoYXQgZmFsbCBiZXR3ZWVuIC0xIGFu
ZCArMSAtIGFuZCB0aGUNCmVycm9yIGZyb20gdGhlIG1pZC1wb2ludCBhbmQgZW5kLXBvaW50IG9m
IHRoZSBjdXJ2ZSBhcmUgZGlzZ3Vpc2VkIGJ5IHRoZSBsYXJnZSBudW1iZXIgb2YNCmVsZW1lbnRz
IGluIHRoZSBjdXJ2ZSBhcnJheS4NCjwvcHJlPg0KPHNjcmlwdCB0eXBlPSJ0ZXh0L2phdmFzY3Jp
cHQiPg0KdmFyIGM9bmV3IHdlYmtpdE9mZmxpbmVBdWRpb0NvbnRleHQoMSwgMjMsIDQ4MDAwKTsN
Cg0KLy9DcmVhdGUgaW5wdXQgdmFsdWVzIGJldHdlZW4gLTEuMSBhbmQgKyAxLjEuDQp2YXIgYj1j
LmNyZWF0ZUJ1ZmZlcigxLCAyMywgNDgwMDApOw0KdmFyIGQ9Yi5nZXRDaGFubmVsRGF0YSgwKTsN
CmZvciAodmFyIGk9MDsgaTwyMzsgaSsrKXsgZFtpXT0oaSouMSktMS4xOyB9DQp2YXIgc3JjPWMu
Y3JlYXRlQnVmZmVyU291cmNlKCk7DQpzcmMuYnVmZmVyPWI7DQpzcmMuc3RhcnQoMCk7DQoNCi8v
U2ltcGxlIHdhdmUtc2hhcGVyLg0KdmFyIHdzPWMuY3JlYXRlV2F2ZVNoYXBlcigpOw0KdmFyIGN1
cnZlPW5ldyBGbG9hdDMyQXJyYXkoMyk7DQpjdXJ2ZVswXT0wOw0KY3VydmVbMV09MTsNCmN1cnZl
WzJdPTA7DQp3cy5jdXJ2ZT1jdXJ2ZTsNCnNyYy5jb25uZWN0KHdzKTsNCndzLmNvbm5lY3QoYy5k
ZXN0aW5hdGlvbik7DQoNCi8vRXhlY3V0ZS4NCmMub25jb21wbGV0ZT1mdW5jdGlvbihldil7DQog
IHZhciBvdXRwdXREYXRhPWV2LnJlbmRlcmVkQnVmZmVyLmdldENoYW5uZWxEYXRhKDApOw0KICB2
YXIgbXNnSXRlbXM9W107DQogIGZvciAodmFyIGk9MDsgaTwyMzsgaSsrKXsNCiAgICBtc2dJdGVt
cy5wdXNoKCJJbnB1dCB2YWx1ZSAiICsgZFtpXS50b0ZpeGVkKDQpICsNCiAgICAgICIgPT4gb3V0
cHV0IHZhbHVlICIgKyBvdXRwdXREYXRhW2ldLnRvRml4ZWQoNCkpOw0KICB9DQogIGFsZXJ0KG1z
Z0l0ZW1zLmpvaW4oIlxuIikpOw0KfTsNCmMuc3RhcnRSZW5kZXJpbmcoKTsNCjwvc2NyaXB0Pg0K
PC9ib2R5Pg0KPC9odG1sPg==
</data>

          </attachment>
      

    </bug>

</bugzilla>