constant-source-output.html (7962B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title> 5 Test ConstantSourceNode Output 6 </title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="../../resources/audit-util.js"></script> 10 <script src="../../resources/audit.js"></script> 11 <script src="../../resources/audioparam-testing.js"></script> 12 </head> 13 <body> 14 <script id="layout-test-code"> 15 let sampleRate = 48000; 16 let renderDuration = 0.125; 17 let renderFrames = sampleRate * renderDuration; 18 19 let audit = Audit.createTaskRunner(); 20 21 audit.define('constant source', (task, should) => { 22 // Verify a constant source outputs the correct (fixed) constant. 23 let context = new OfflineAudioContext(1, renderFrames, sampleRate); 24 let node = new ConstantSourceNode(context, {offset: 0.5}); 25 node.connect(context.destination); 26 node.start(); 27 28 context.startRendering() 29 .then(function(buffer) { 30 let actual = buffer.getChannelData(0); 31 let expected = new Float32Array(actual.length); 32 expected.fill(node.offset.value); 33 34 should(actual, 'Basic: ConstantSourceNode({offset: 0.5})') 35 .beEqualToArray(expected); 36 }) 37 .then(() => task.done()); 38 }); 39 40 audit.define('stop before start', (task, should) => { 41 let context = new OfflineAudioContext(1, renderFrames, sampleRate); 42 let node = new ConstantSourceNode(context, {offset: 1}); 43 node.connect(context.destination); 44 node.start(61 / context.sampleRate); 45 node.stop(31 / context.sampleRate); 46 47 context.startRendering() 48 .then(function(buffer) { 49 let actual = buffer.getChannelData(0); 50 should(actual, 51 "ConstantSourceNode with stop before " + 52 "start must output silence") 53 .beConstantValueOf(0); 54 }) 55 .then(() => task.done()); 56 }); 57 58 audit.define('stop equal to start', (task, should) => { 59 let context = new OfflineAudioContext(1, renderFrames, sampleRate); 60 let node = new ConstantSourceNode(context, {offset: 1}); 61 node.connect(context.destination); 62 node.start(31 / context.sampleRate); 63 node.stop(31 / context.sampleRate); 64 65 context.startRendering() 66 .then(function(buffer) { 67 let actual = buffer.getChannelData(0); 68 should(actual, 69 "ConstantSourceNode with stop equal to start " + 70 " must output silence") 71 .beConstantValueOf(0); 72 }) 73 .then(() => task.done()); 74 }); 75 76 audit.define('start/stop', (task, should) => { 77 // Verify a constant source starts and stops at the correct time and has 78 // the correct (fixed) value. 79 let context = new OfflineAudioContext(1, renderFrames, sampleRate); 80 let node = new ConstantSourceNode(context, {offset: 1}); 81 node.connect(context.destination); 82 83 let startFrame = 10; 84 let stopFrame = 300; 85 86 node.start(startFrame / context.sampleRate); 87 node.stop(stopFrame / context.sampleRate); 88 89 context.startRendering() 90 .then(function(buffer) { 91 let actual = buffer.getChannelData(0); 92 let expected = new Float32Array(actual.length); 93 // The expected output is all 1s from start to stop time. 94 expected.fill(0); 95 96 for (let k = startFrame; k < stopFrame; ++k) { 97 expected[k] = node.offset.value; 98 } 99 100 let prefix = 'start/stop: '; 101 should(actual.slice(0, startFrame), 102 prefix + 'ConstantSourceNode frames [0, ' + 103 startFrame + ')') 104 .beConstantValueOf(0); 105 106 should(actual.slice(startFrame, stopFrame), 107 prefix + 'ConstantSourceNode frames [' + 108 startFrame + ', ' + stopFrame + ')') 109 .beConstantValueOf(1); 110 111 should( 112 actual.slice(stopFrame), 113 prefix + 'ConstantSourceNode frames [' + stopFrame + 114 ', ' + renderFrames + ')') 115 .beConstantValueOf(0); 116 }) 117 .then(() => task.done()); 118 119 }); 120 121 audit.define('basic automation', (task, should) => { 122 // Verify that automation works as expected. 123 let context = new OfflineAudioContext(1, renderFrames, sampleRate); 124 let source = context.createConstantSource(); 125 source.connect(context.destination); 126 127 let rampEndTime = renderDuration / 2; 128 source.offset.setValueAtTime(0.5, 0); 129 source.offset.linearRampToValueAtTime(1, rampEndTime); 130 131 source.start(); 132 133 context.startRendering() 134 .then(function(buffer) { 135 let actual = buffer.getChannelData(0); 136 let expected = createLinearRampArray( 137 0, rampEndTime, 0.5, 1, context.sampleRate); 138 139 let rampEndFrame = Math.ceil(rampEndTime * context.sampleRate); 140 let prefix = 'Automation: '; 141 142 should(actual.slice(0, rampEndFrame), 143 prefix + 'ConstantSourceNode.linearRamp(1, 0.5)') 144 .beCloseToArray(expected, { 145 // Experimentally determined threshold. 146 relativeThreshold: 7.1610e-7 147 }); 148 149 should(actual.slice(rampEndFrame), 150 prefix + 'ConstantSourceNode after ramp') 151 .beConstantValueOf(1); 152 }) 153 .then(() => task.done()); 154 }); 155 156 audit.define('connected audioparam', (task, should) => { 157 // Verify the constant source output with connected AudioParam produces 158 // the correct output. 159 let context = new OfflineAudioContext(2, renderFrames, sampleRate) 160 context.destination.channelInterpretation = 'discrete'; 161 let source = new ConstantSourceNode(context, {offset: 1}); 162 let osc = context.createOscillator(); 163 let merger = context.createChannelMerger(2); 164 merger.connect(context.destination); 165 166 source.connect(merger, 0, 0); 167 osc.connect(merger, 0, 1); 168 osc.connect(source.offset); 169 170 osc.start(); 171 let sourceStartFrame = 10; 172 source.start(sourceStartFrame / context.sampleRate); 173 174 context.startRendering() 175 .then(function(buffer) { 176 // Channel 0 and 1 should be identical, except channel 0 (the 177 // source) is silent at the beginning. 178 let actual = buffer.getChannelData(0); 179 let expected = buffer.getChannelData(1); 180 // The expected output should be oscillator + 1 because offset 181 // is 1. 182 expected = expected.map(x => 1 + x); 183 let prefix = 'Connected param: '; 184 185 // The initial part of the output should be silent because the 186 // source node hasn't started yet. 187 should( 188 actual.slice(0, sourceStartFrame), 189 prefix + 'ConstantSourceNode frames [0, ' + sourceStartFrame + 190 ')') 191 .beConstantValueOf(0); 192 // The rest of the output should be the same as the oscillator (in 193 // channel 1) 194 should( 195 actual.slice(sourceStartFrame), 196 prefix + 'ConstantSourceNode frames [' + sourceStartFrame + 197 ', ' + renderFrames + ')') 198 .beCloseToArray(expected.slice(sourceStartFrame), 0); 199 200 }) 201 .then(() => task.done()); 202 }); 203 204 audit.run(); 205 </script> 206 </body> 207 </html>