1/*
2 * Copyright (C) 2012 Intel Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include "config.h"
30
31#if ENABLE(WEB_AUDIO)
32
33#include "DirectConvolver.h"
34
35#if OS(DARWIN)
36#include <Accelerate/Accelerate.h>
37#endif
38
39#include "VectorMath.h"
40
41namespace WebCore {
42
43using namespace VectorMath;
44
45DirectConvolver::DirectConvolver(size_t inputBlockSize)
46 : m_inputBlockSize(inputBlockSize)
47 , m_buffer(inputBlockSize * 2)
48{
49}
50
51void DirectConvolver::process(AudioFloatArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess)
52{
53 ASSERT(framesToProcess == m_inputBlockSize);
54 if (framesToProcess != m_inputBlockSize)
55 return;
56
57 // Only support kernelSize <= m_inputBlockSize
58 size_t kernelSize = convolutionKernel->size();
59 ASSERT(kernelSize <= m_inputBlockSize);
60 if (kernelSize > m_inputBlockSize)
61 return;
62
63 float* kernelP = convolutionKernel->data();
64
65 // Sanity check
66 bool isCopyGood = kernelP && sourceP && destP && m_buffer.data();
67 ASSERT(isCopyGood);
68 if (!isCopyGood)
69 return;
70
71 float* inputP = m_buffer.data() + m_inputBlockSize;
72
73 // Copy samples to 2nd half of input buffer.
74 memcpy(inputP, sourceP, sizeof(float) * framesToProcess);
75
76#if USE(ACCELERATE)
77 vDSP_conv(inputP - kernelSize + 1, 1, kernelP + kernelSize - 1, -1, destP, 1, framesToProcess, kernelSize);
78#else
79 // FIXME: The macro can be further optimized to avoid pipeline stalls. One possibility is to maintain 4 separate sums and change the macro to CONVOLVE_FOUR_SAMPLES.
80#define CONVOLVE_ONE_SAMPLE \
81 sum += inputP[i - j] * kernelP[j]; \
82 j++;
83
84 size_t i = 0;
85 while (i < framesToProcess) {
86 size_t j = 0;
87 float sum = 0;
88
89 // FIXME: SSE optimization may be applied here.
90 if (kernelSize == 32) {
91 CONVOLVE_ONE_SAMPLE // 1
92 CONVOLVE_ONE_SAMPLE // 2
93 CONVOLVE_ONE_SAMPLE // 3
94 CONVOLVE_ONE_SAMPLE // 4
95 CONVOLVE_ONE_SAMPLE // 5
96 CONVOLVE_ONE_SAMPLE // 6
97 CONVOLVE_ONE_SAMPLE // 7
98 CONVOLVE_ONE_SAMPLE // 8
99 CONVOLVE_ONE_SAMPLE // 9
100 CONVOLVE_ONE_SAMPLE // 10
101
102 CONVOLVE_ONE_SAMPLE // 11
103 CONVOLVE_ONE_SAMPLE // 12
104 CONVOLVE_ONE_SAMPLE // 13
105 CONVOLVE_ONE_SAMPLE // 14
106 CONVOLVE_ONE_SAMPLE // 15
107 CONVOLVE_ONE_SAMPLE // 16
108 CONVOLVE_ONE_SAMPLE // 17
109 CONVOLVE_ONE_SAMPLE // 18
110 CONVOLVE_ONE_SAMPLE // 19
111 CONVOLVE_ONE_SAMPLE // 20
112
113 CONVOLVE_ONE_SAMPLE // 21
114 CONVOLVE_ONE_SAMPLE // 22
115 CONVOLVE_ONE_SAMPLE // 23
116 CONVOLVE_ONE_SAMPLE // 24
117 CONVOLVE_ONE_SAMPLE // 25
118 CONVOLVE_ONE_SAMPLE // 26
119 CONVOLVE_ONE_SAMPLE // 27
120 CONVOLVE_ONE_SAMPLE // 28
121 CONVOLVE_ONE_SAMPLE // 29
122 CONVOLVE_ONE_SAMPLE // 30
123
124 CONVOLVE_ONE_SAMPLE // 31
125 CONVOLVE_ONE_SAMPLE // 32
126
127 } else if (kernelSize == 64) {
128 CONVOLVE_ONE_SAMPLE // 1
129 CONVOLVE_ONE_SAMPLE // 2
130 CONVOLVE_ONE_SAMPLE // 3
131 CONVOLVE_ONE_SAMPLE // 4
132 CONVOLVE_ONE_SAMPLE // 5
133 CONVOLVE_ONE_SAMPLE // 6
134 CONVOLVE_ONE_SAMPLE // 7
135 CONVOLVE_ONE_SAMPLE // 8
136 CONVOLVE_ONE_SAMPLE // 9
137 CONVOLVE_ONE_SAMPLE // 10
138
139 CONVOLVE_ONE_SAMPLE // 11
140 CONVOLVE_ONE_SAMPLE // 12
141 CONVOLVE_ONE_SAMPLE // 13
142 CONVOLVE_ONE_SAMPLE // 14
143 CONVOLVE_ONE_SAMPLE // 15
144 CONVOLVE_ONE_SAMPLE // 16
145 CONVOLVE_ONE_SAMPLE // 17
146 CONVOLVE_ONE_SAMPLE // 18
147 CONVOLVE_ONE_SAMPLE // 19
148 CONVOLVE_ONE_SAMPLE // 20
149
150 CONVOLVE_ONE_SAMPLE // 21
151 CONVOLVE_ONE_SAMPLE // 22
152 CONVOLVE_ONE_SAMPLE // 23
153 CONVOLVE_ONE_SAMPLE // 24
154 CONVOLVE_ONE_SAMPLE // 25
155 CONVOLVE_ONE_SAMPLE // 26
156 CONVOLVE_ONE_SAMPLE // 27
157 CONVOLVE_ONE_SAMPLE // 28
158 CONVOLVE_ONE_SAMPLE // 29
159 CONVOLVE_ONE_SAMPLE // 30
160
161 CONVOLVE_ONE_SAMPLE // 31
162 CONVOLVE_ONE_SAMPLE // 32
163 CONVOLVE_ONE_SAMPLE // 33
164 CONVOLVE_ONE_SAMPLE // 34
165 CONVOLVE_ONE_SAMPLE // 35
166 CONVOLVE_ONE_SAMPLE // 36
167 CONVOLVE_ONE_SAMPLE // 37
168 CONVOLVE_ONE_SAMPLE // 38
169 CONVOLVE_ONE_SAMPLE // 39
170 CONVOLVE_ONE_SAMPLE // 40
171
172 CONVOLVE_ONE_SAMPLE // 41
173 CONVOLVE_ONE_SAMPLE // 42
174 CONVOLVE_ONE_SAMPLE // 43
175 CONVOLVE_ONE_SAMPLE // 44
176 CONVOLVE_ONE_SAMPLE // 45
177 CONVOLVE_ONE_SAMPLE // 46
178 CONVOLVE_ONE_SAMPLE // 47
179 CONVOLVE_ONE_SAMPLE // 48
180 CONVOLVE_ONE_SAMPLE // 49
181 CONVOLVE_ONE_SAMPLE // 50
182
183 CONVOLVE_ONE_SAMPLE // 51
184 CONVOLVE_ONE_SAMPLE // 52
185 CONVOLVE_ONE_SAMPLE // 53
186 CONVOLVE_ONE_SAMPLE // 54
187 CONVOLVE_ONE_SAMPLE // 55
188 CONVOLVE_ONE_SAMPLE // 56
189 CONVOLVE_ONE_SAMPLE // 57
190 CONVOLVE_ONE_SAMPLE // 58
191 CONVOLVE_ONE_SAMPLE // 59
192 CONVOLVE_ONE_SAMPLE // 60
193
194 CONVOLVE_ONE_SAMPLE // 61
195 CONVOLVE_ONE_SAMPLE // 62
196 CONVOLVE_ONE_SAMPLE // 63
197 CONVOLVE_ONE_SAMPLE // 64
198
199 } else if (kernelSize == 128) {
200 CONVOLVE_ONE_SAMPLE // 1
201 CONVOLVE_ONE_SAMPLE // 2
202 CONVOLVE_ONE_SAMPLE // 3
203 CONVOLVE_ONE_SAMPLE // 4
204 CONVOLVE_ONE_SAMPLE // 5
205 CONVOLVE_ONE_SAMPLE // 6
206 CONVOLVE_ONE_SAMPLE // 7
207 CONVOLVE_ONE_SAMPLE // 8
208 CONVOLVE_ONE_SAMPLE // 9
209 CONVOLVE_ONE_SAMPLE // 10
210
211 CONVOLVE_ONE_SAMPLE // 11
212 CONVOLVE_ONE_SAMPLE // 12
213 CONVOLVE_ONE_SAMPLE // 13
214 CONVOLVE_ONE_SAMPLE // 14
215 CONVOLVE_ONE_SAMPLE // 15
216 CONVOLVE_ONE_SAMPLE // 16
217 CONVOLVE_ONE_SAMPLE // 17
218 CONVOLVE_ONE_SAMPLE // 18
219 CONVOLVE_ONE_SAMPLE // 19
220 CONVOLVE_ONE_SAMPLE // 20
221
222 CONVOLVE_ONE_SAMPLE // 21
223 CONVOLVE_ONE_SAMPLE // 22
224 CONVOLVE_ONE_SAMPLE // 23
225 CONVOLVE_ONE_SAMPLE // 24
226 CONVOLVE_ONE_SAMPLE // 25
227 CONVOLVE_ONE_SAMPLE // 26
228 CONVOLVE_ONE_SAMPLE // 27
229 CONVOLVE_ONE_SAMPLE // 28
230 CONVOLVE_ONE_SAMPLE // 29
231 CONVOLVE_ONE_SAMPLE // 30
232
233 CONVOLVE_ONE_SAMPLE // 31
234 CONVOLVE_ONE_SAMPLE // 32
235 CONVOLVE_ONE_SAMPLE // 33
236 CONVOLVE_ONE_SAMPLE // 34
237 CONVOLVE_ONE_SAMPLE // 35
238 CONVOLVE_ONE_SAMPLE // 36
239 CONVOLVE_ONE_SAMPLE // 37
240 CONVOLVE_ONE_SAMPLE // 38
241 CONVOLVE_ONE_SAMPLE // 39
242 CONVOLVE_ONE_SAMPLE // 40
243
244 CONVOLVE_ONE_SAMPLE // 41
245 CONVOLVE_ONE_SAMPLE // 42
246 CONVOLVE_ONE_SAMPLE // 43
247 CONVOLVE_ONE_SAMPLE // 44
248 CONVOLVE_ONE_SAMPLE // 45
249 CONVOLVE_ONE_SAMPLE // 46
250 CONVOLVE_ONE_SAMPLE // 47
251 CONVOLVE_ONE_SAMPLE // 48
252 CONVOLVE_ONE_SAMPLE // 49
253 CONVOLVE_ONE_SAMPLE // 50
254
255 CONVOLVE_ONE_SAMPLE // 51
256 CONVOLVE_ONE_SAMPLE // 52
257 CONVOLVE_ONE_SAMPLE // 53
258 CONVOLVE_ONE_SAMPLE // 54
259 CONVOLVE_ONE_SAMPLE // 55
260 CONVOLVE_ONE_SAMPLE // 56
261 CONVOLVE_ONE_SAMPLE // 57
262 CONVOLVE_ONE_SAMPLE // 58
263 CONVOLVE_ONE_SAMPLE // 59
264 CONVOLVE_ONE_SAMPLE // 60
265
266 CONVOLVE_ONE_SAMPLE // 61
267 CONVOLVE_ONE_SAMPLE // 62
268 CONVOLVE_ONE_SAMPLE // 63
269 CONVOLVE_ONE_SAMPLE // 64
270 CONVOLVE_ONE_SAMPLE // 65
271 CONVOLVE_ONE_SAMPLE // 66
272 CONVOLVE_ONE_SAMPLE // 67
273 CONVOLVE_ONE_SAMPLE // 68
274 CONVOLVE_ONE_SAMPLE // 69
275 CONVOLVE_ONE_SAMPLE // 70
276
277 CONVOLVE_ONE_SAMPLE // 71
278 CONVOLVE_ONE_SAMPLE // 72
279 CONVOLVE_ONE_SAMPLE // 73
280 CONVOLVE_ONE_SAMPLE // 74
281 CONVOLVE_ONE_SAMPLE // 75
282 CONVOLVE_ONE_SAMPLE // 76
283 CONVOLVE_ONE_SAMPLE // 77
284 CONVOLVE_ONE_SAMPLE // 78
285 CONVOLVE_ONE_SAMPLE // 79
286 CONVOLVE_ONE_SAMPLE // 80
287
288 CONVOLVE_ONE_SAMPLE // 81
289 CONVOLVE_ONE_SAMPLE // 82
290 CONVOLVE_ONE_SAMPLE // 83
291 CONVOLVE_ONE_SAMPLE // 84
292 CONVOLVE_ONE_SAMPLE // 85
293 CONVOLVE_ONE_SAMPLE // 86
294 CONVOLVE_ONE_SAMPLE // 87
295 CONVOLVE_ONE_SAMPLE // 88
296 CONVOLVE_ONE_SAMPLE // 89
297 CONVOLVE_ONE_SAMPLE // 90
298
299 CONVOLVE_ONE_SAMPLE // 91
300 CONVOLVE_ONE_SAMPLE // 92
301 CONVOLVE_ONE_SAMPLE // 93
302 CONVOLVE_ONE_SAMPLE // 94
303 CONVOLVE_ONE_SAMPLE // 95
304 CONVOLVE_ONE_SAMPLE // 96
305 CONVOLVE_ONE_SAMPLE // 97
306 CONVOLVE_ONE_SAMPLE // 98
307 CONVOLVE_ONE_SAMPLE // 99
308 CONVOLVE_ONE_SAMPLE // 100
309
310 CONVOLVE_ONE_SAMPLE // 101
311 CONVOLVE_ONE_SAMPLE // 102
312 CONVOLVE_ONE_SAMPLE // 103
313 CONVOLVE_ONE_SAMPLE // 104
314 CONVOLVE_ONE_SAMPLE // 105
315 CONVOLVE_ONE_SAMPLE // 106
316 CONVOLVE_ONE_SAMPLE // 107
317 CONVOLVE_ONE_SAMPLE // 108
318 CONVOLVE_ONE_SAMPLE // 109
319 CONVOLVE_ONE_SAMPLE // 110
320
321 CONVOLVE_ONE_SAMPLE // 111
322 CONVOLVE_ONE_SAMPLE // 112
323 CONVOLVE_ONE_SAMPLE // 113
324 CONVOLVE_ONE_SAMPLE // 114
325 CONVOLVE_ONE_SAMPLE // 115
326 CONVOLVE_ONE_SAMPLE // 116
327 CONVOLVE_ONE_SAMPLE // 117
328 CONVOLVE_ONE_SAMPLE // 118
329 CONVOLVE_ONE_SAMPLE // 119
330 CONVOLVE_ONE_SAMPLE // 120
331
332 CONVOLVE_ONE_SAMPLE // 121
333 CONVOLVE_ONE_SAMPLE // 122
334 CONVOLVE_ONE_SAMPLE // 123
335 CONVOLVE_ONE_SAMPLE // 124
336 CONVOLVE_ONE_SAMPLE // 125
337 CONVOLVE_ONE_SAMPLE // 126
338 CONVOLVE_ONE_SAMPLE // 127
339 CONVOLVE_ONE_SAMPLE // 128
340 } else {
341 while (j < kernelSize) {
342 // Non-optimized using actual while loop.
343 CONVOLVE_ONE_SAMPLE
344 }
345 }
346 destP[i++] = sum;
347 }
348#endif // USE(ACCELERATE)
349
350 // Copy 2nd half of input buffer to 1st half.
351 memcpy(m_buffer.data(), inputP, sizeof(float) * framesToProcess);
352}
353
354void DirectConvolver::reset()
355{
356 m_buffer.zero();
357}
358
359} // namespace WebCore
360
361#endif // ENABLE(WEB_AUDIO)
362