| OLD | NEW | 
|    1 <!doctype html> |    1 <!doctype html> | 
|    2 <html> |    2 <html> | 
|    3   <head> |    3   <head> | 
|    4     <script src="../../resources/testharness.js"></script> |    4     <script src="../../resources/testharness.js"></script> | 
|    5     <script src="../../resources/testharnessreport.js"></script>  |    5     <script src="../../resources/testharnessreport.js"></script>  | 
|    6     <script src="../resources/audit-util.js"></script> |    6     <script src="../resources/audit-util.js"></script> | 
|    7     <script src="../resources/audio-testing.js"></script> |    7     <script src="../resources/audit.js"></script> | 
|    8     <title>Test AnalyserNode getFloatTimeDomainData</title> |    8     <title>Test AnalyserNode getFloatTimeDomainData</title> | 
|    9   </head> |    9   </head> | 
|   10  |   10  | 
|   11   <body> |   11   <body> | 
|   12     <script> |   12     <script> | 
|   13       // Use a power of two to eliminate any round-off in the computation of the
      times for |   13       // Use a power of two to eliminate any round-off in the computation of the
      times for | 
|   14       // context.suspend(). |   14       // context.suspend(). | 
|   15       var sampleRate = 32768; |   15       var sampleRate = 32768; | 
|   16  |   16  | 
|   17       // The largest FFT size for the analyser node is 32768.  We want to render
      longer than this so |   17       // The largest FFT size for the analyser node is 32768.  We want to render
      longer than this so | 
|   18       // that we have at least one complete buffer of data of 32768 samples. |   18       // that we have at least one complete buffer of data of 32768 samples. | 
|   19       var renderFrames = 2 * 32768; |   19       var renderFrames = 2 * 32768; | 
|   20       var renderDuration = renderFrames / sampleRate; |   20       var renderDuration = renderFrames / sampleRate; | 
|   21  |   21  | 
|   22       var audit = Audit.createTaskRunner(); |   22       var audit = Audit.createTaskRunner(); | 
|   23  |   23  | 
|   24       // Test that getFloatTimeDomainData handles short and long vectors correct
     ly. |   24       // Test that getFloatTimeDomainData handles short and long vectors correct
     ly. | 
|   25       audit.defineTask("short and long vector", function (done) { |   25       audit.define("short and long vector", (task, should) =>  { | 
|   26         var fftSize = 32; |   26         var fftSize = 32; | 
|   27         var graphInfo = createGraph(fftSize); |   27         var graphInfo = createGraph(fftSize); | 
|   28         var context = graphInfo.context; |   28         var context = graphInfo.context; | 
|   29         var analyser = graphInfo.analyser; |   29         var analyser = graphInfo.analyser; | 
|   30         var signalBuffer = graphInfo.signalBuffer; |   30         var signalBuffer = graphInfo.signalBuffer; | 
|   31         var signal = signalBuffer.getChannelData(0); |   31         var signal = signalBuffer.getChannelData(0); | 
|   32  |   32  | 
|   33         var success = true; |   33         var success = true; | 
|   34         var sampleFrame = 128; |   34         var sampleFrame = 128; | 
|   35  |   35  | 
|   36         context.suspend(sampleFrame / sampleRate).then(function () { |   36         context.suspend(sampleFrame / sampleRate).then(function () { | 
|   37           var shortData = new Float32Array(8); |   37           var shortData = new Float32Array(8); | 
|   38           // Initialize the array to Infinity to represent uninitialize data. |   38           // Initialize the array to Infinity to represent uninitialize data. | 
|   39           shortData.fill(Infinity); |   39           shortData.fill(Infinity); | 
|   40  |   40  | 
|   41           analyser.getFloatTimeDomainData(shortData); |   41           analyser.getFloatTimeDomainData(shortData); | 
|   42  |   42  | 
|   43           // The short array should be filled with the expected data, with no er
     rors thrown. |   43           // The short array should be filled with the expected data, with no er
     rors thrown. | 
|   44  |   44  | 
|   45           var expected = signal.subarray(sampleFrame - fftSize, sampleFrame); |   45           var expected = signal.subarray(sampleFrame - fftSize, sampleFrame); | 
|   46           success = Should(shortData.length + "-element time domain data", short
     Data) |   46           should(shortData, shortData.length + "-element time domain data") | 
|   47             .beEqualToArray(expected.subarray(0, shortData.length)) && success; |   47             .beEqualToArray(expected.subarray(0, shortData.length)); | 
|   48  |   48  | 
|   49           var longData = new Float32Array(2 * fftSize); |   49           var longData = new Float32Array(2 * fftSize); | 
|   50           // Initialize the array to Infinity to represent uninitialize data. |   50           // Initialize the array to Infinity to represent uninitialize data. | 
|   51           longData.fill(Infinity); |   51           longData.fill(Infinity); | 
|   52  |   52  | 
|   53           analyser.getFloatTimeDomainData(longData); |   53           analyser.getFloatTimeDomainData(longData); | 
|   54  |   54  | 
|   55           // The long array should filled with the expected data but the extra e
     lements should be |   55           // The long array should filled with the expected data but the extra e
     lements should be | 
|   56           // untouched. |   56           // untouched. | 
|   57           success = Should("longData.subarray(0, " + fftSize + ")", |   57           should(longData.subarray(0, fftSize), "longData.subarray(0, " + fftSiz
     e + ")") | 
|   58               longData.subarray(0, fftSize), { |   58             .beEqualToArray(expected); | 
|   59                 numberOfArrayLog: 32 |  | 
|   60               }) |  | 
|   61             .beEqualToArray(expected) && success; |  | 
|   62  |   59  | 
|   63           success = Should("Unfilled elements longData.subarray(" + fftSize + ")
     ", |   60           should(longData.subarray(fftSize), "Unfilled elements longData.subarra
     y(" + fftSize + ")") | 
|   64               longData.subarray(fftSize)) |   61             .beConstantValueOf(Infinity); | 
|   65             .beConstantValueOf(Infinity) && success; |  | 
|   66         }).then(context.resume.bind(context)); |   62         }).then(context.resume.bind(context)); | 
|   67  |   63  | 
|   68         context.startRendering().then(function (buffer) { |   64         context.startRendering().then(() => task.done()); | 
|   69           Should("Long and short time domain arrays handled", success) |  | 
|   70             .summarize("correctly.", "incorrectly."); |  | 
|   71         }).then(done); |  | 
|   72       }); |   65       }); | 
|   73  |   66  | 
|   74       var success = true; |   67       var success = true; | 
|   75  |   68  | 
|   76       // Generate tests for all valid FFT sizes for an AnalyserNode. |   69       // Generate tests for all valid FFT sizes for an AnalyserNode. | 
|   77       for (var k = 5; k < 16; ++k) { |   70       for (var k = 5; k < 16; ++k) { | 
|   78         var fftSize = Math.pow(2, k); |   71         var fftSize = Math.pow(2, k); | 
|   79         (function (n) { |   72         (function (n) { | 
|   80           // We grab a sample at (roughly) half the rendering duration. |   73           // We grab a sample at (roughly) half the rendering duration. | 
|   81           audit.defineTask("fftSize " + n, function (done) { |   74           audit.define("fftSize " + n, (task, should) =>  { | 
|   82             runTest(n, renderDuration / 2).then(done); |   75             runTest(n, renderDuration / 2, should).then(() => task.done()); | 
|   83           }); |   76           }); | 
|   84         })(fftSize); |   77         })(fftSize); | 
|   85       } |   78       } | 
|   86  |   79  | 
|   87       audit.defineTask("summarize size tests", function (done) { |  | 
|   88         Should("Time domain data", success) |  | 
|   89           .summarize("contained the correct data for each size.", |  | 
|   90                      "did not contain the correct data for each size."); |  | 
|   91  |  | 
|   92         done(); |  | 
|   93       }); |  | 
|   94  |  | 
|   95       // Special case for a large size, but the sampling point is early.  The in
     itial part of the |   80       // Special case for a large size, but the sampling point is early.  The in
     itial part of the | 
|   96       // buffer should be filled with zeroes. |   81       // buffer should be filled with zeroes. | 
|   97  |   82  | 
|   98       audit.defineTask("initial zeroes", function (done) { |   83       audit.define("initial zeroes", (task, should) =>  { | 
|   99         // Somewhat arbitrary size for the analyser.  It should be greater than 
     one rendering |   84         // Somewhat arbitrary size for the analyser.  It should be greater than 
     one rendering | 
|  100         // quantum. |   85         // quantum. | 
|  101         var fftSize = 2048; |   86         var fftSize = 2048; | 
|  102         var graphInfo = createGraph(fftSize); |   87         var graphInfo = createGraph(fftSize); | 
|  103         var context = graphInfo.context; |   88         var context = graphInfo.context; | 
|  104         var analyser = graphInfo.analyser; |   89         var analyser = graphInfo.analyser; | 
|  105         var signalBuffer = graphInfo.signalBuffer; |   90         var signalBuffer = graphInfo.signalBuffer; | 
|  106  |   91  | 
|  107         var data = new Float32Array(fftSize); |   92         var data = new Float32Array(fftSize); | 
|  108  |   93  | 
|  109         success = true; |   94         success = true; | 
|  110         // Suspend every rendering quantum and examine the analyser data. |   95         // Suspend every rendering quantum and examine the analyser data. | 
|  111         for (var k = 128; k <= fftSize; k += 128) { |   96         for (var k = 128; k <= fftSize; k += 128) { | 
|  112           context.suspend(k / sampleRate).then(function () { |   97           context.suspend(k / sampleRate).then(function () { | 
|  113             analyser.getFloatTimeDomainData(data); |   98             analyser.getFloatTimeDomainData(data); | 
|  114             var sampleFrame = context.currentTime * sampleRate; |   99             var sampleFrame = context.currentTime * sampleRate; | 
|  115  |  100  | 
|  116             // Verify that the last k frames are not zero, but the first fftSize
      - k frames are. |  101             // Verify that the last k frames are not zero, but the first fftSize
      - k frames are. | 
|  117             var prefix = "At frame " + (sampleFrame - 1) + ": data.subarray"; |  102             var prefix = "At frame " + (sampleFrame - 1) + ": data.subarray"; | 
|  118             if (sampleFrame < fftSize) { |  103             if (sampleFrame < fftSize) { | 
|  119               success = Should(prefix + "(0, " + (fftSize - sampleFrame) + ")", |  104               should(data.subarray(0, fftSize - sampleFrame), | 
|  120                   data.subarray(0, fftSize - sampleFrame)) |  105                   prefix + "(0, " + (fftSize - sampleFrame) + ")") | 
|  121                 .beConstantValueOf(0) && success; |  106                 .beConstantValueOf(0) && success; | 
|  122             } |  107             } | 
|  123  |  108  | 
|  124             var signal = signalBuffer.getChannelData(0); |  109             var signal = signalBuffer.getChannelData(0); | 
|  125             success = Should(prefix + "(" + (fftSize - sampleFrame) + ", " + fft
     Size + ")", |  110             should(data.subarray(fftSize - sampleFrame, fftSize), | 
|  126                 data.subarray(fftSize - sampleFrame, fftSize)) |  111               prefix + "(" + (fftSize - sampleFrame) + ", " + fftSize + ")") | 
|  127               .beEqualToArray(signal.subarray(0, sampleFrame)) && success; |  112               .beEqualToArray(signal.subarray(0, sampleFrame)) && success; | 
|  128           }).then(context.resume.bind(context)); |  113           }).then(context.resume.bind(context)); | 
|  129         } |  114         } | 
|  130  |  115  | 
|  131         context.startRendering().then(function (b) { |  116         context.startRendering().then(() => task.done()); | 
|  132           Should("Time domain data", success) |  | 
|  133             .summarize( |  | 
|  134               "contained initial zeroes and correct data as expected", |  | 
|  135               "did not contain initial zeroes and correct data as expected."); |  | 
|  136         }).then(done); |  | 
|  137       }); |  117       }); | 
|  138  |  118  | 
|  139       audit.defineTask("finish", function (done) { |  119       audit.run(); | 
|  140         done(); |  | 
|  141       }); |  | 
|  142  |  | 
|  143       audit.runTasks(); |  | 
|  144  |  120  | 
|  145       // Run test of an AnalyserNode with fftSize of |fftSize|, and with the dat
     a from the node |  121       // Run test of an AnalyserNode with fftSize of |fftSize|, and with the dat
     a from the node | 
|  146       // being requested at time |sampletime|.  The result from the analyser nod
     e is compared |  122       // being requested at time |sampletime|.  The result from the analyser nod
     e is compared | 
|  147       // against the expected data.  The result of startRendering() is returned. |  123       // against the expected data.  The result of startRendering() is returned. | 
|  148       function runTest(fftSize, sampleTime) { |  124       function runTest(fftSize, sampleTime, should) { | 
|  149         var graphInfo = createGraph(fftSize); |  125         var graphInfo = createGraph(fftSize); | 
|  150         var context = graphInfo.context; |  126         var context = graphInfo.context; | 
|  151         var analyser = graphInfo.analyser; |  127         var analyser = graphInfo.analyser; | 
|  152         var signalBuffer = graphInfo.signalBuffer; |  128         var signalBuffer = graphInfo.signalBuffer; | 
|  153  |  129  | 
|  154         // Grab the data at the requested time. |  130         // Grab the data at the requested time. | 
|  155         context.suspend(sampleTime).then(function () { |  131         context.suspend(sampleTime).then(function () { | 
|  156           var lastFrame = Math.floor(context.currentTime * sampleRate); |  132           var lastFrame = Math.floor(context.currentTime * sampleRate); | 
|  157  |  133  | 
|  158           // Grab the time domain data from the analyzer and compare against the
      expected result. |  134           // Grab the time domain data from the analyzer and compare against the
      expected result. | 
|  159           var actualFloatData = new Float32Array(fftSize); |  135           var actualFloatData = new Float32Array(fftSize); | 
|  160           analyser.getFloatTimeDomainData(actualFloatData); |  136           analyser.getFloatTimeDomainData(actualFloatData); | 
|  161  |  137  | 
|  162           // Compare against the expected result. |  138           // Compare against the expected result. | 
|  163           var signal = signalBuffer.getChannelData(0); |  139           var signal = signalBuffer.getChannelData(0); | 
|  164           var message = actualFloatData.length + "-point analyser time domain da
     ta"; |  140           var message = actualFloatData.length + "-point analyser time domain da
     ta"; | 
|  165           success = Should(message, actualFloatData) |  141           should(actualFloatData, message) | 
|  166             .beEqualToArray(signal.subarray(lastFrame - actualFloatData.length, 
     lastFrame)) && success; |  142             .beEqualToArray(signal.subarray(lastFrame - actualFloatData.length, 
     lastFrame)) && success; | 
|  167         }).then(context.resume.bind(context)); |  143         }).then(context.resume.bind(context)); | 
|  168  |  144  | 
|  169         return context.startRendering(); |  145         return context.startRendering(); | 
|  170       } |  146       } | 
|  171  |  147  | 
|  172       // Create the audio graph with an AnalyserNode with fftSize |fftSize|.  A 
     simple |  148       // Create the audio graph with an AnalyserNode with fftSize |fftSize|.  A 
     simple | 
|  173       // integer-valued linear ramp is the source so we can easily verify the re
     sults.  A dictionary |  149       // integer-valued linear ramp is the source so we can easily verify the re
     sults.  A dictionary | 
|  174       // consisting of the context, the analyser node, and the signal is returne
     d. |  150       // consisting of the context, the analyser node, and the signal is returne
     d. | 
|  175       function createGraph(fftSize) { |  151       function createGraph(fftSize) { | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|  196  |  172  | 
|  197         return { |  173         return { | 
|  198           context: context, |  174           context: context, | 
|  199           analyser: analyser, |  175           analyser: analyser, | 
|  200           signalBuffer: signalBuffer |  176           signalBuffer: signalBuffer | 
|  201         }; |  177         }; | 
|  202       } |  178       } | 
|  203     </script> |  179     </script> | 
|  204   </body> |  180   </body> | 
|  205 </html> |  181 </html> | 
| OLD | NEW |