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 |