| OLD | NEW |
| 1 <!doctype html> | 1 <!DOCTYPE html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title> |
| 5 Test AnalyserNode Downmixing |
| 6 </title> |
| 4 <script src="../../resources/testharness.js"></script> | 7 <script src="../../resources/testharness.js"></script> |
| 5 <script src="../../resources/testharnessreport.js"></script> | 8 <script src="../../resources/testharnessreport.js"></script> |
| 6 <script src="../resources/audit-util.js"></script> | 9 <script src="../resources/audit-util.js"></script> |
| 7 <script src="../resources/audit.js"></script> | 10 <script src="../resources/audit.js"></script> |
| 8 <script src="../resources/fft.js"></script> | 11 <script src="../resources/fft.js"></script> |
| 9 <script src="../resources/realtimeanalyser-testing.js"></script> | 12 <script src="../resources/realtimeanalyser-testing.js"></script> |
| 10 <title>Test AnalyserNode Downmixing</title> | |
| 11 </head> | 13 </head> |
| 12 | |
| 13 <body> | 14 <body> |
| 14 <script> | 15 <script id="layout-test-code"> |
| 15 let sampleRate = 44100; | 16 let sampleRate = 44100; |
| 16 let renderFrames = 2048; | 17 let renderFrames = 2048; |
| 17 | 18 |
| 18 let audit = Audit.createTaskRunner(); | 19 let audit = Audit.createTaskRunner(); |
| 19 | 20 |
| 20 let testConfigs = [{ | 21 let testConfigs = [ |
| 21 channelCount: 1, | 22 {channelCount: 1, message: 'mono', floatRelError: 6.3283e-8}, |
| 22 message: "mono", | 23 {channelCount: 2, message: 'stereo', floatRelError: 1.1681e-7}, |
| 23 floatRelError: 6.3283e-8 | 24 {channelCount: 4, message: 'quad', floatRelError: 4.9793e-7}, |
| 24 }, { | 25 {channelCount: 6, message: '5.1', floatRelError: 2.0215e-7}, |
| 25 channelCount: 2, | 26 {channelCount: 3, message: '3-channel', floatRelError: 6.3283e-8} |
| 26 message: "stereo", | 27 ]; |
| 27 floatRelError: 1.1681e-7 | |
| 28 }, { | |
| 29 channelCount: 4, | |
| 30 message: "quad", | |
| 31 floatRelError: 4.9793e-7 | |
| 32 }, { | |
| 33 channelCount: 6, | |
| 34 message: "5.1", | |
| 35 floatRelError: 2.0215e-7 | |
| 36 }, { | |
| 37 channelCount: 3, | |
| 38 message: "3-channel", | |
| 39 floatRelError: 6.3283e-8 | |
| 40 }]; | |
| 41 | 28 |
| 42 // Create tasks for each entry in testConfigs | 29 // Create tasks for each entry in testConfigs |
| 43 for (k in testConfigs) { | 30 for (k in testConfigs) { |
| 44 audit.define(testConfigs[k].message, (function (config) { | 31 audit.define(testConfigs[k].message, (function(config) { |
| 45 return function(task, should) { | 32 return function(task, should) { |
| 46 runTest(config, should).then(() => task.done()); | 33 runTest(config, should).then(() => task.done()); |
| 47 }; | 34 }; |
| 48 })(testConfigs[k])); | 35 })(testConfigs[k])); |
| 49 } | 36 } |
| 50 | 37 |
| 51 audit.run(); | 38 audit.run(); |
| 52 | 39 |
| 53 // Test downmixing of the AnalyserNode time data. We use the downmixing t
hat automatically | 40 // Test downmixing of the AnalyserNode time data. We use the downmixing |
| 54 // happens in the destination node to generate the reference data which is
compared to the | 41 // that automatically happens in the destination node to generate the |
| 55 // data that the Analyser node has captured. | 42 // reference data which is compared to the data that the Analyser node has |
| 43 // captured. |
| 56 function runTest(options, should) { | 44 function runTest(options, should) { |
| 57 // Context MUST have exactly one channel so that we downmix the source t
o mono to generate | 45 // Context MUST have exactly one channel so that we downmix the source |
| 58 // the reference. | 46 // to mono to generate the reference. |
| 59 let context = new OfflineAudioContext(1, renderFrames, sampleRate); | 47 let context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| 60 | 48 |
| 61 let channels = options.channelCount || 1; | 49 let channels = options.channelCount || 1; |
| 62 let source = context.createBufferSource(); | 50 let source = context.createBufferSource(); |
| 63 | 51 |
| 64 // The signals in each channel. Doesn't matter much what is in here, but
it's best if the | 52 // The signals in each channel. Doesn't matter much what is in here, but |
| 65 // values aren't linearly increasing so that the average of the values i
sn't one of the | 53 // it's best if the values aren't linearly increasing so that the |
| 66 // values (in case the implementation does something silly). Only need
to support up to 6 | 54 // average of the values isn't one of the values (in case the |
| 55 // implementation does something silly). Only need to support up to 6 |
| 67 // channels. | 56 // channels. |
| 68 let bufferValues = [1, 2, 3, 4, 5, 6].map(function (x) { | 57 let bufferValues = [1, 2, 3, 4, 5, 6].map(function(x) { |
| 69 return x * x | 58 return x * x |
| 70 });; | 59 }); |
| 71 source.buffer = createConstantBuffer(context, renderFrames, bufferValues
.slice(0, channels)); | 60 ; |
| 61 source.buffer = createConstantBuffer( |
| 62 context, renderFrames, bufferValues.slice(0, channels)); |
| 72 | 63 |
| 73 let analyser = context.createAnalyser(); | 64 let analyser = context.createAnalyser(); |
| 74 analyser.smoothingTimeConstant = 0; | 65 analyser.smoothingTimeConstant = 0; |
| 75 analyser.fftSize = 256; | 66 analyser.fftSize = 256; |
| 76 | 67 |
| 77 // Run analyser as an automatic pull node. Do NOT connect to the destina
tion. We don't want | 68 // Run analyser as an automatic pull node. Do NOT connect to the |
| 78 // the output of the analyser to mix in with the source that is also dir
ectly connected to | 69 // destination. We don't want the output of the analyser to mix in with |
| 79 // the destination. | 70 // the source that is also directly connected to the destination. |
| 80 source.connect(analyser); | 71 source.connect(analyser); |
| 81 source.connect(context.destination); | 72 source.connect(context.destination); |
| 82 | 73 |
| 83 let timeData = new Float32Array(analyser.fftSize); | 74 let timeData = new Float32Array(analyser.fftSize); |
| 84 let freqData = new Float32Array(analyser.frequencyBinCount); | 75 let freqData = new Float32Array(analyser.frequencyBinCount); |
| 85 | 76 |
| 86 let suspendFrame = analyser.fftSize; | 77 let suspendFrame = analyser.fftSize; |
| 87 context.suspend(suspendFrame / context.sampleRate).then(function () { | 78 context.suspend(suspendFrame / context.sampleRate) |
| 88 analyser.getFloatTimeDomainData(timeData); | 79 .then(function() { |
| 89 analyser.getFloatFrequencyData(freqData); | 80 analyser.getFloatTimeDomainData(timeData); |
| 90 }).then(context.resume.bind(context)); | 81 analyser.getFloatFrequencyData(freqData); |
| 82 }) |
| 83 .then(context.resume.bind(context)); |
| 91 | 84 |
| 92 source.start(); | 85 source.start(); |
| 93 return context.startRendering().then(function (renderedBuffer) { | 86 return context.startRendering().then(function(renderedBuffer) { |
| 94 // Verify the time domain data is correct. | 87 // Verify the time domain data is correct. |
| 95 let prefix = "Analyser downmix " + options.message + " to mono" | 88 let prefix = 'Analyser downmix ' + options.message + ' to mono' |
| 96 should(timeData, prefix + " time data") | 89 should(timeData, prefix + ' time data') |
| 97 .beEqualToArray(renderedBuffer.getChannelData(0).subarray(0, analyse
r.fftSize)); | 90 .beEqualToArray(renderedBuffer.getChannelData(0).subarray( |
| 91 0, analyser.fftSize)); |
| 98 | 92 |
| 99 let expectedTimeData = renderedBuffer.getChannelData(0).subarray(0, an
alyser.fftSize); | 93 let expectedTimeData = |
| 94 renderedBuffer.getChannelData(0).subarray(0, analyser.fftSize); |
| 100 let fftOrder = Math.floor(Math.log2(analyser.fftSize)); | 95 let fftOrder = Math.floor(Math.log2(analyser.fftSize)); |
| 101 let expectedFreqData = computeFFTMagnitude(expectedTimeData, fftOrder)
.map(linearToDb); | 96 let expectedFreqData = |
| 97 computeFFTMagnitude(expectedTimeData, fftOrder).map(linearToDb); |
| 102 | 98 |
| 103 compareFloatFreq(prefix + " freq data", freqData, | 99 compareFloatFreq( |
| 104 expectedFreqData, should, { | 100 prefix + ' freq data', freqData, expectedFreqData, should, { |
| 105 precision: 6, | 101 precision: 6, |
| 106 floatRelError: options.floatRelError, | 102 floatRelError: options.floatRelError, |
| 107 }); | 103 }); |
| 108 }); | 104 }); |
| 109 } | 105 } |
| 110 </script> | 106 </script> |
| 111 </body> | 107 </body> |
| 112 </html> | 108 </html> |
| OLD | NEW |