OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 | |
3 <html> | |
4 <head> | |
5 <script src="../resources/js-test.js"></script> | |
6 <script src="resources/compatibility.js"></script> | |
7 <script src="resources/audit-util.js"></script> | |
8 <script src="resources/audio-testing.js"></script> | |
9 <script type="text/javascript" src="resources/buffer-loader.js"></script> | |
10 </head> | |
11 | |
12 <body> | |
13 | |
14 <div id="description"></div> | |
15 <div id="console"></div> | |
16 | |
17 <script> | |
18 description("Tests that WaveShaperNode applies proper non-linear distortion."); | |
19 | |
20 var sampleRate = 44100; | |
21 var lengthInSeconds = 4; | |
22 var numberOfRenderFrames = sampleRate * lengthInSeconds; | |
23 var numberOfCurveFrames = 65536; | |
24 var inputBuffer; | |
25 var waveShapingCurve; | |
26 | |
27 var context; | |
28 | |
29 function generateInputBuffer() { | |
30 // Create mono input buffer. | |
31 var buffer = context.createBuffer(1, numberOfRenderFrames, context.sampleRat
e); | |
32 var data = buffer.getChannelData(0); | |
33 | |
34 // Generate an input vector with values from -1 -> +1 over a duration of len
gthInSeconds. | |
35 // This exercises the full nominal input range and will touch every point of
the shaping curve. | |
36 for (var i = 0; i < numberOfRenderFrames; ++i) { | |
37 var x = i / numberOfRenderFrames; // 0 -> 1 | |
38 x = 2 * x - 1; // -1 -> +1 | |
39 data[i] = x; | |
40 } | |
41 | |
42 return buffer; | |
43 } | |
44 | |
45 // Generates a symmetric curve: Math.atan(5 * x) / (0.5 * Math.PI) | |
46 // (with x == 0 corresponding to the center of the array) | |
47 // This curve is arbitrary, but would be useful in the real-world. | |
48 // To some extent, the actual curve we choose is not important in this test, | |
49 // since the input vector walks through all possible curve values. | |
50 function generateWaveShapingCurve() { | |
51 var curve = new Float32Array(numberOfCurveFrames); | |
52 | |
53 var n = numberOfCurveFrames; | |
54 var n2 = n / 2; | |
55 | |
56 for (var i = 0; i < n; ++i) { | |
57 var x = (i - n2) / n2; | |
58 var y = Math.atan(5 * x) / (0.5 * Math.PI); | |
59 } | |
60 | |
61 return curve; | |
62 } | |
63 | |
64 function checkShapedCurve(event) { | |
65 var buffer = event.renderedBuffer; | |
66 | |
67 var inputData = inputBuffer.getChannelData(0); | |
68 var outputData = buffer.getChannelData(0); | |
69 | |
70 var success = true; | |
71 | |
72 // Go through every sample and make sure it has been shaped exactly accordin
g to the shaping curve we gave it. | |
73 for (var i = 0; i < buffer.length; ++i) { | |
74 var input = inputData[i]; | |
75 | |
76 // Calculate an index based on input -1 -> +1 with 0 being at the center
of the curve data. | |
77 var index = Math.floor(numberOfCurveFrames * 0.5 * (input + 1)); | |
78 | |
79 // Clip index to the input range of the curve. | |
80 // This takes care of input outside of nominal range -1 -> +1 | |
81 index = index < 0 ? 0 : index; | |
82 index = index > numberOfCurveFrames - 1 ? numberOfCurveFrames - 1 : inde
x; | |
83 | |
84 var expectedOutput = waveShapingCurve[index]; | |
85 | |
86 var output = outputData[i]; | |
87 | |
88 if (output != expectedOutput) { | |
89 success = false; | |
90 break; | |
91 } | |
92 } | |
93 | |
94 if (success) { | |
95 testPassed("WaveShaperNode properly applied non-linear distortion."); | |
96 } else { | |
97 testFailed("WaveShaperNode did not properly apply non-linear distortion.
"); | |
98 } | |
99 | |
100 finishJSTest(); | |
101 } | |
102 | |
103 function runTest() { | |
104 if (window.testRunner) { | |
105 testRunner.dumpAsText(); | |
106 testRunner.waitUntilDone(); | |
107 } | |
108 | |
109 window.jsTestIsAsync = true; | |
110 | |
111 // Create offline audio context. | |
112 context = new OfflineAudioContext(1, numberOfRenderFrames, sampleRate); | |
113 | |
114 // source -> waveshaper -> destination | |
115 var source = context.createBufferSource(); | |
116 var waveshaper = context.createWaveShaper(); | |
117 source.connect(waveshaper); | |
118 waveshaper.connect(context.destination); | |
119 | |
120 // Create an input test vector. | |
121 inputBuffer = generateInputBuffer(); | |
122 source.buffer = inputBuffer; | |
123 | |
124 // We'll apply non-linear distortion according to this shaping curve. | |
125 waveShapingCurve = generateWaveShapingCurve(); | |
126 waveshaper.curve = waveShapingCurve; | |
127 | |
128 source.start(0); | |
129 | |
130 context.oncomplete = checkShapedCurve; | |
131 context.startRendering(); | |
132 } | |
133 | |
134 runTest(); | |
135 | |
136 </script> | |
137 | |
138 </body> | |
139 </html> | |
OLD | NEW |