OLD | NEW |
1 let sampleRate = 44100.0; | 1 let sampleRate = 44100.0; |
2 | 2 |
3 // HRTF extra frames. This is a magic constant currently in | 3 // HRTF extra frames. This is a magic constant currently in |
4 // AudioBufferSourceNode::process that always extends the | 4 // AudioBufferSourceNode::process that always extends the |
5 // duration by this number of samples. See bug 77224 | 5 // duration by this number of samples. See bug 77224 |
6 // (https://bugs.webkit.org/show_bug.cgi?id=77224). | 6 // (https://bugs.webkit.org/show_bug.cgi?id=77224). |
7 let extraFramesHRTF = 512; | 7 let extraFramesHRTF = 512; |
8 | 8 |
9 // How many grains to play. | 9 // How many grains to play. |
10 let numberOfTests = 100; | 10 let numberOfTests = 100; |
(...skipping 11 matching lines...) Expand all Loading... |
22 | 22 |
23 // How long to render to cover all of the grains. | 23 // How long to render to cover all of the grains. |
24 let renderTime = (numberOfTests + 1) * timeStep; | 24 let renderTime = (numberOfTests + 1) * timeStep; |
25 | 25 |
26 let context; | 26 let context; |
27 let renderedData; | 27 let renderedData; |
28 | 28 |
29 // Create a buffer containing the data that we want. The function f | 29 // Create a buffer containing the data that we want. The function f |
30 // returns the desired value at sample frame k. | 30 // returns the desired value at sample frame k. |
31 function createSignalBuffer(context, f) { | 31 function createSignalBuffer(context, f) { |
| 32 // Make sure the buffer has enough data for all of the possible |
| 33 // grain offsets and durations. Need to include the extra frames |
| 34 // for HRTF. The additional 1 is for any round-off errors. |
| 35 let signalLength = Math.floor( |
| 36 1 + extraFramesHRTF + |
| 37 sampleRate * (numberOfTests * grainOffsetStep + duration)); |
32 | 38 |
33 // Make sure the buffer has enough data for all of the possible | 39 let buffer = context.createBuffer(2, signalLength, sampleRate); |
34 // grain offsets and durations. Need to include the extra frames | 40 let data = buffer.getChannelData(0); |
35 // for HRTF. The additional 1 is for any round-off errors. | |
36 let signalLength = Math.floor( | |
37 1 + extraFramesHRTF + | |
38 sampleRate * (numberOfTests * grainOffsetStep + duration)); | |
39 | 41 |
40 let buffer = context.createBuffer(2, signalLength, sampleRate); | 42 for (let k = 0; k < signalLength; ++k) { |
41 let data = buffer.getChannelData(0); | 43 data[k] = f(k); |
| 44 } |
42 | 45 |
43 for (let k = 0; k < signalLength; ++k) { | 46 return buffer; |
44 data[k] = f(k); | |
45 } | |
46 | |
47 return buffer; | |
48 } | 47 } |
49 | 48 |
50 // From the data array, find the start and end sample frame for each | 49 // From the data array, find the start and end sample frame for each |
51 // grain. This depends on the data having 0's between grain, and | 50 // grain. This depends on the data having 0's between grain, and |
52 // that the grain is always strictly non-zero. | 51 // that the grain is always strictly non-zero. |
53 function findStartAndEndSamples(data) { | 52 function findStartAndEndSamples(data) { |
54 let nSamples = data.length; | 53 let nSamples = data.length; |
55 | 54 |
56 let startTime = []; | 55 let startTime = []; |
57 let endTime = []; | 56 let endTime = []; |
(...skipping 10 matching lines...) Expand all Loading... |
68 startTime.push(k); | 67 startTime.push(k); |
69 lookForStart = false; | 68 lookForStart = false; |
70 } | 69 } |
71 } else { | 70 } else { |
72 // Find a zero and record the end of the grain. | 71 // Find a zero and record the end of the grain. |
73 if (!renderedData[k]) { | 72 if (!renderedData[k]) { |
74 endTime.push(k); | 73 endTime.push(k); |
75 lookForStart = true; | 74 lookForStart = true; |
76 } | 75 } |
77 } | 76 } |
78 } | 77 } |
79 | 78 |
80 return {start : startTime, end : endTime}; | 79 return {start: startTime, end: endTime}; |
81 } | 80 } |
82 | 81 |
83 function playGrain(context, source, time, offset, duration) { | 82 function playGrain(context, source, time, offset, duration) { |
84 let bufferSource = context.createBufferSource(); | 83 let bufferSource = context.createBufferSource(); |
85 | 84 |
86 bufferSource.buffer = source; | 85 bufferSource.buffer = source; |
87 bufferSource.connect(context.destination); | 86 bufferSource.connect(context.destination); |
88 bufferSource.start(time, offset, duration); | 87 bufferSource.start(time, offset, duration); |
89 } | 88 } |
90 | 89 |
91 // Play out all grains. Returns a object containing two arrays, one | 90 // Play out all grains. Returns a object containing two arrays, one |
92 // for the start time and one for the grain offset time. | 91 // for the start time and one for the grain offset time. |
93 function playAllGrains(context, source, numberOfNotes) { | 92 function playAllGrains(context, source, numberOfNotes) { |
94 let startTimes = new Array(numberOfNotes); | 93 let startTimes = new Array(numberOfNotes); |
95 let offsets = new Array(numberOfNotes); | 94 let offsets = new Array(numberOfNotes); |
96 | 95 |
97 for (let k = 0; k < numberOfNotes; ++k) { | 96 for (let k = 0; k < numberOfNotes; ++k) { |
98 let timeOffset = k * timeStep; | 97 let timeOffset = k * timeStep; |
99 let grainOffset = k * grainOffsetStep; | 98 let grainOffset = k * grainOffsetStep; |
100 | 99 |
101 playGrain(context, source, timeOffset, grainOffset, duration); | 100 playGrain(context, source, timeOffset, grainOffset, duration); |
102 startTimes[k] = timeOffset; | 101 startTimes[k] = timeOffset; |
103 offsets[k] = grainOffset; | 102 offsets[k] = grainOffset; |
104 } | 103 } |
105 | 104 |
106 return { startTimes : startTimes, grainOffsetTimes : offsets }; | 105 return {startTimes: startTimes, grainOffsetTimes: offsets}; |
107 } | 106 } |
108 | 107 |
109 // Verify that the start and end frames for each grain match our | 108 // Verify that the start and end frames for each grain match our |
110 // expected start and end frames. | 109 // expected start and end frames. |
111 function verifyStartAndEndFrames(startEndFrames, should) { | 110 function verifyStartAndEndFrames(startEndFrames, should) { |
112 let startFrames = startEndFrames.start; | 111 let startFrames = startEndFrames.start; |
113 let endFrames = startEndFrames.end; | 112 let endFrames = startEndFrames.end; |
114 | 113 |
115 // Count of how many grains started at the incorrect time. | 114 // Count of how many grains started at the incorrect time. |
116 let errorCountStart = 0; | 115 let errorCountStart = 0; |
(...skipping 26 matching lines...) Expand all Loading... |
143 .beEqualToArray([expectedStart, expectedEnd]); | 142 .beEqualToArray([expectedStart, expectedEnd]); |
144 } | 143 } |
145 | 144 |
146 // Check that all the grains started or ended at the correct time. | 145 // Check that all the grains started or ended at the correct time. |
147 if (!errorCountStart) { | 146 if (!errorCountStart) { |
148 should( | 147 should( |
149 startFrames.length, 'Number of grains that started at the correct time') | 148 startFrames.length, 'Number of grains that started at the correct time') |
150 .beEqualTo(numberOfTests); | 149 .beEqualTo(numberOfTests); |
151 } else { | 150 } else { |
152 should( | 151 should( |
153 errorCountStart, 'Number of grains out of ' + numberOfTests + | 152 errorCountStart, |
| 153 'Number of grains out of ' + numberOfTests + |
154 'that started at the wrong time') | 154 'that started at the wrong time') |
155 .beEqualTo(0); | 155 .beEqualTo(0); |
156 } | 156 } |
157 | 157 |
158 if (!errorCountEnd) { | 158 if (!errorCountEnd) { |
159 should(endFrames.length, 'Number of grains that ended at the correct time') | 159 should(endFrames.length, 'Number of grains that ended at the correct time') |
160 .beEqualTo(numberOfTests); | 160 .beEqualTo(numberOfTests); |
161 } else { | 161 } else { |
162 should( | 162 should( |
163 errorCountEnd, 'Number of grains out of ' + numberOfTests + | 163 errorCountEnd, |
| 164 'Number of grains out of ' + numberOfTests + |
164 ' that ended at the wrong time') | 165 ' that ended at the wrong time') |
165 .beEqualTo(0); | 166 .beEqualTo(0); |
166 } | 167 } |
167 } | 168 } |
OLD | NEW |