| OLD | NEW |
| (Empty) |
| 1 <!doctype html> | |
| 2 <html> | |
| 3 <head> | |
| 4 <script src="../resources/js-test.js"></script> | |
| 5 <script src="resources/compatibility.js"></script> | |
| 6 <script src="resources/audit-util.js"></script> | |
| 7 <script src="resources/audio-testing.js"></script> | |
| 8 <script src="resources/realtimeanalyser-testing.js"></script> | |
| 9 <script src="resources/fft.js"></script> | |
| 10 <title>Test Analyser getFloatFrequencyData and getByteFrequencyData, Smoothi
ng</title> | |
| 11 | |
| 12 </head> | |
| 13 | |
| 14 <body> | |
| 15 <script> | |
| 16 description("Test AnalyserNode getFloatFrequencyData and getByteFrequencyD
ata, Smoothing"); | |
| 17 window.jsTestIsAsync = true; | |
| 18 | |
| 19 // Use a power of two to eliminate any round-off in the computation of the
times for | |
| 20 // context.suspend(). | |
| 21 var sampleRate = 32768; | |
| 22 | |
| 23 // The largest FFT size for the analyser node is 32768. We want to render
longer than this so | |
| 24 // that we have at least one complete buffer of data of 32768 samples. | |
| 25 var renderFrames = 2 * 32768; | |
| 26 var renderDuration = renderFrames / sampleRate; | |
| 27 | |
| 28 var audit = Audit.createTaskRunner(); | |
| 29 | |
| 30 // Do one basic test of smoothing of the FFT data. | |
| 31 audit.defineTask("smoothing test", function (done) { | |
| 32 // Test only 512-point FFT. The size isn't too important as long as it'
s greater than 128 | |
| 33 // (a rendering quantum). | |
| 34 var options = { | |
| 35 order: 9, | |
| 36 smoothing: 0.5, | |
| 37 floatRelError: 5.9207e-6 | |
| 38 }; | |
| 39 | |
| 40 var success = true; | |
| 41 | |
| 42 var graph = createGraph(options); | |
| 43 | |
| 44 context = graph.context; | |
| 45 analyser = graph.analyser; | |
| 46 | |
| 47 var smoothedFloatResult = new Float32Array(analyser.frequencyBinCount); | |
| 48 smoothedFloatResult.fill(0); | |
| 49 | |
| 50 // Stop after one analyser frame to get the initial FFT | |
| 51 var suspendFrame = analyser.fftSize; | |
| 52 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 53 var timeData = new Float32Array(analyser.fftSize); | |
| 54 var freqData = new Float32Array(analyser.frequencyBinCount); | |
| 55 analyser.getFloatTimeDomainData(timeData); | |
| 56 analyser.getFloatFrequencyData(freqData); | |
| 57 | |
| 58 var expectedFreq = computeFFTMagnitude(timeData, options.order); | |
| 59 smoothFFT(smoothedFloatResult, expectedFreq, options.smoothing); | |
| 60 | |
| 61 var message = "First " + analyser.fftSize + "-point FFT at frame " + (
context.currentTime * | |
| 62 sampleRate); | |
| 63 var comparison = compareFloatFreq(message, freqData, smoothedFloatResu
lt.map( | |
| 64 linearToDb), options); | |
| 65 success = success && comparison.success; | |
| 66 | |
| 67 // Test the byte frequency data. | |
| 68 var byteFreqData = new Uint8Array(analyser.frequencyBinCount); | |
| 69 var expectedByteData = new Float32Array(analyser.frequencyBinCount); | |
| 70 analyser.getByteFrequencyData(byteFreqData); | |
| 71 | |
| 72 // Convert the expected float frequency data to byte data. | |
| 73 var expectedByteData = convertFloatToByte(smoothedFloatResult.map(line
arToDb), | |
| 74 analyser.minDecibels, analyser.maxDecibels); | |
| 75 | |
| 76 success = Should(analyser.fftSize + "-point byte FFT", byteFreqData) | |
| 77 .beCloseToArray(expectedByteData, 0) && success; | |
| 78 | |
| 79 }).then(context.resume.bind(context)); | |
| 80 | |
| 81 // Skip an analyser frame and grab another to verify that the smoothing
is done correctly. | |
| 82 suspendFrame += 2 * analyser.fftSize; | |
| 83 context.suspend(suspendFrame / sampleRate).then(function () { | |
| 84 var timeData = new Float32Array(analyser.fftSize); | |
| 85 var freqDataInDb = new Float32Array(analyser.frequencyBinCount); | |
| 86 | |
| 87 // Grab the time domain and frequency domain data | |
| 88 analyser.getFloatTimeDomainData(timeData); | |
| 89 analyser.getFloatFrequencyData(freqDataInDb); | |
| 90 | |
| 91 var newFreqData = computeFFTMagnitude(timeData, options.order); | |
| 92 // Smooth the data together | |
| 93 | |
| 94 smoothFFT(smoothedFloatResult, newFreqData, options.smoothing); | |
| 95 var message = "Smoothed " + analyser.fftSize + "-point FFT at frame "
+ | |
| 96 (context.currentTime * sampleRate); | |
| 97 var comparison = compareFloatFreq(message, | |
| 98 freqDataInDb, smoothedFloatResult.map(linearToDb), { | |
| 99 order: options.order, | |
| 100 smoothing: options.smoothing, | |
| 101 floatRelError: 2.5332e-5 | |
| 102 }); | |
| 103 success = success && comparison.success; | |
| 104 | |
| 105 // Test the byte frequency data. | |
| 106 var byteFreqData = new Uint8Array(analyser.frequencyBinCount); | |
| 107 var expectedByteData = new Float32Array(analyser.frequencyBinCount); | |
| 108 analyser.getByteFrequencyData(byteFreqData); | |
| 109 | |
| 110 // Convert the expected float frequency data to byte data. | |
| 111 var expectedByteData = convertFloatToByte(smoothedFloatResult.map(line
arToDb), | |
| 112 analyser.minDecibels, analyser.maxDecibels); | |
| 113 | |
| 114 success = Should(analyser.fftSize + "-point byte FFT", byteFreqData) | |
| 115 .beCloseToArray(expectedByteData, 0) && success; | |
| 116 | |
| 117 }).then(context.resume.bind(context)); | |
| 118 | |
| 119 context.startRendering().then(function (buffer) { | |
| 120 var prefix = "FFT smoothing performed "; | |
| 121 var suffix = " with smoothing constant " + analyser.smoothingTimeConst
ant + ".\n" | |
| 122 | |
| 123 if (success) | |
| 124 testPassed(prefix + "correctly" + suffix); | |
| 125 else | |
| 126 testFailed(prefix + "incorrectly" + suffix); | |
| 127 }).then(done); | |
| 128 }); | |
| 129 | |
| 130 audit.defineTask("finish", function (done) { | |
| 131 finishJSTest(); | |
| 132 done(); | |
| 133 }); | |
| 134 | |
| 135 audit.runTasks(); | |
| 136 | |
| 137 </script> | |
| 138 </body> | |
| 139 </html> | |
| OLD | NEW |