Optimize for IPP in DirectConvolver::process()
[WebKit-https.git] / Source / WebCore / platform / audio / DirectConvolver.cpp
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 Computer, 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 #include "VectorMath.h"
36
37 namespace WebCore {
38
39 using namespace VectorMath;
40     
41 DirectConvolver::DirectConvolver(size_t inputBlockSize)
42     : m_inputBlockSize(inputBlockSize)
43 #if USE(WEBAUDIO_IPP)
44     , m_overlayBuffer(inputBlockSize)
45 #endif // USE(WEBAUDIO_IPP)
46     , m_buffer(inputBlockSize * 2)
47 {
48 }
49
50 void DirectConvolver::process(AudioFloatArray* convolutionKernel, const float* sourceP, float* destP, size_t framesToProcess)
51 {
52     // FIXME: Optimize for DARWIN, conv() function in Accelerate.framework can be used here.
53     // https://bugs.webkit.org/show_bug.cgi?id=80256
54
55     ASSERT(framesToProcess == m_inputBlockSize);
56     if (framesToProcess != m_inputBlockSize)
57         return;
58
59     // Only support kernelSize <= m_inputBlockSize
60     size_t kernelSize = convolutionKernel->size();
61     ASSERT(kernelSize <= m_inputBlockSize);
62     if (kernelSize > m_inputBlockSize)
63         return;
64
65     float* kernelP = convolutionKernel->data();
66
67     // Sanity check
68     bool isCopyGood = kernelP && sourceP && destP && m_buffer.data();
69     ASSERT(isCopyGood);
70     if (!isCopyGood)
71         return;
72
73 #if USE(WEBAUDIO_IPP)
74     float* outputBuffer = m_buffer.data();
75     float* overlayBuffer = m_overlayBuffer.data();
76     bool isCopyGood2 = overlayBuffer && m_overlayBuffer.size() >= kernelSize && m_buffer.size() == m_inputBlockSize * 2;
77     ASSERT(isCopyGood2);
78     if (!isCopyGood2)
79         return;
80
81     ippsConv_32f(static_cast<const Ipp32f*>(sourceP), framesToProcess, static_cast<Ipp32f*>(kernelP), kernelSize, static_cast<Ipp32f*>(outputBuffer));
82
83     vadd(outputBuffer, 1, overlayBuffer, 1, destP, 1, framesToProcess);
84     memcpy(overlayBuffer, outputBuffer + m_inputBlockSize, sizeof(float) * kernelSize);
85 #else
86     float* inputP = m_buffer.data() + m_inputBlockSize;
87
88     // Copy samples to 2nd half of input buffer.
89     memcpy(inputP, sourceP, sizeof(float) * framesToProcess);
90
91     // 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.
92 #define CONVOLVE_ONE_SAMPLE             \
93     sum += inputP[i - j] * kernelP[j];  \
94     j++;
95
96     size_t i = 0;
97     while (i < framesToProcess) {
98         size_t j = 0;
99         float sum = 0;
100         
101         // FIXME: SSE optimization may be applied here.
102         if (kernelSize == 32) {
103             CONVOLVE_ONE_SAMPLE // 1
104             CONVOLVE_ONE_SAMPLE // 2
105             CONVOLVE_ONE_SAMPLE // 3
106             CONVOLVE_ONE_SAMPLE // 4
107             CONVOLVE_ONE_SAMPLE // 5
108             CONVOLVE_ONE_SAMPLE // 6
109             CONVOLVE_ONE_SAMPLE // 7
110             CONVOLVE_ONE_SAMPLE // 8
111             CONVOLVE_ONE_SAMPLE // 9
112             CONVOLVE_ONE_SAMPLE // 10
113
114             CONVOLVE_ONE_SAMPLE // 11
115             CONVOLVE_ONE_SAMPLE // 12
116             CONVOLVE_ONE_SAMPLE // 13
117             CONVOLVE_ONE_SAMPLE // 14
118             CONVOLVE_ONE_SAMPLE // 15
119             CONVOLVE_ONE_SAMPLE // 16
120             CONVOLVE_ONE_SAMPLE // 17
121             CONVOLVE_ONE_SAMPLE // 18
122             CONVOLVE_ONE_SAMPLE // 19
123             CONVOLVE_ONE_SAMPLE // 20
124
125             CONVOLVE_ONE_SAMPLE // 21
126             CONVOLVE_ONE_SAMPLE // 22
127             CONVOLVE_ONE_SAMPLE // 23
128             CONVOLVE_ONE_SAMPLE // 24
129             CONVOLVE_ONE_SAMPLE // 25
130             CONVOLVE_ONE_SAMPLE // 26
131             CONVOLVE_ONE_SAMPLE // 27
132             CONVOLVE_ONE_SAMPLE // 28
133             CONVOLVE_ONE_SAMPLE // 29
134             CONVOLVE_ONE_SAMPLE // 30
135
136             CONVOLVE_ONE_SAMPLE // 31
137             CONVOLVE_ONE_SAMPLE // 32
138
139         } else if (kernelSize == 64) {
140             CONVOLVE_ONE_SAMPLE // 1
141             CONVOLVE_ONE_SAMPLE // 2
142             CONVOLVE_ONE_SAMPLE // 3
143             CONVOLVE_ONE_SAMPLE // 4
144             CONVOLVE_ONE_SAMPLE // 5
145             CONVOLVE_ONE_SAMPLE // 6
146             CONVOLVE_ONE_SAMPLE // 7
147             CONVOLVE_ONE_SAMPLE // 8
148             CONVOLVE_ONE_SAMPLE // 9
149             CONVOLVE_ONE_SAMPLE // 10
150
151             CONVOLVE_ONE_SAMPLE // 11
152             CONVOLVE_ONE_SAMPLE // 12
153             CONVOLVE_ONE_SAMPLE // 13
154             CONVOLVE_ONE_SAMPLE // 14
155             CONVOLVE_ONE_SAMPLE // 15
156             CONVOLVE_ONE_SAMPLE // 16
157             CONVOLVE_ONE_SAMPLE // 17
158             CONVOLVE_ONE_SAMPLE // 18
159             CONVOLVE_ONE_SAMPLE // 19
160             CONVOLVE_ONE_SAMPLE // 20
161
162             CONVOLVE_ONE_SAMPLE // 21
163             CONVOLVE_ONE_SAMPLE // 22
164             CONVOLVE_ONE_SAMPLE // 23
165             CONVOLVE_ONE_SAMPLE // 24
166             CONVOLVE_ONE_SAMPLE // 25
167             CONVOLVE_ONE_SAMPLE // 26
168             CONVOLVE_ONE_SAMPLE // 27
169             CONVOLVE_ONE_SAMPLE // 28
170             CONVOLVE_ONE_SAMPLE // 29
171             CONVOLVE_ONE_SAMPLE // 30
172
173             CONVOLVE_ONE_SAMPLE // 31
174             CONVOLVE_ONE_SAMPLE // 32
175             CONVOLVE_ONE_SAMPLE // 33
176             CONVOLVE_ONE_SAMPLE // 34
177             CONVOLVE_ONE_SAMPLE // 35
178             CONVOLVE_ONE_SAMPLE // 36
179             CONVOLVE_ONE_SAMPLE // 37
180             CONVOLVE_ONE_SAMPLE // 38
181             CONVOLVE_ONE_SAMPLE // 39
182             CONVOLVE_ONE_SAMPLE // 40
183
184             CONVOLVE_ONE_SAMPLE // 41
185             CONVOLVE_ONE_SAMPLE // 42
186             CONVOLVE_ONE_SAMPLE // 43
187             CONVOLVE_ONE_SAMPLE // 44
188             CONVOLVE_ONE_SAMPLE // 45
189             CONVOLVE_ONE_SAMPLE // 46
190             CONVOLVE_ONE_SAMPLE // 47
191             CONVOLVE_ONE_SAMPLE // 48
192             CONVOLVE_ONE_SAMPLE // 49
193             CONVOLVE_ONE_SAMPLE // 50
194
195             CONVOLVE_ONE_SAMPLE // 51
196             CONVOLVE_ONE_SAMPLE // 52
197             CONVOLVE_ONE_SAMPLE // 53
198             CONVOLVE_ONE_SAMPLE // 54
199             CONVOLVE_ONE_SAMPLE // 55
200             CONVOLVE_ONE_SAMPLE // 56
201             CONVOLVE_ONE_SAMPLE // 57
202             CONVOLVE_ONE_SAMPLE // 58
203             CONVOLVE_ONE_SAMPLE // 59
204             CONVOLVE_ONE_SAMPLE // 60
205
206             CONVOLVE_ONE_SAMPLE // 61
207             CONVOLVE_ONE_SAMPLE // 62
208             CONVOLVE_ONE_SAMPLE // 63
209             CONVOLVE_ONE_SAMPLE // 64
210
211         } else if (kernelSize == 128) {
212             CONVOLVE_ONE_SAMPLE // 1
213             CONVOLVE_ONE_SAMPLE // 2
214             CONVOLVE_ONE_SAMPLE // 3
215             CONVOLVE_ONE_SAMPLE // 4
216             CONVOLVE_ONE_SAMPLE // 5
217             CONVOLVE_ONE_SAMPLE // 6
218             CONVOLVE_ONE_SAMPLE // 7
219             CONVOLVE_ONE_SAMPLE // 8
220             CONVOLVE_ONE_SAMPLE // 9
221             CONVOLVE_ONE_SAMPLE // 10
222
223             CONVOLVE_ONE_SAMPLE // 11
224             CONVOLVE_ONE_SAMPLE // 12
225             CONVOLVE_ONE_SAMPLE // 13
226             CONVOLVE_ONE_SAMPLE // 14
227             CONVOLVE_ONE_SAMPLE // 15
228             CONVOLVE_ONE_SAMPLE // 16
229             CONVOLVE_ONE_SAMPLE // 17
230             CONVOLVE_ONE_SAMPLE // 18
231             CONVOLVE_ONE_SAMPLE // 19
232             CONVOLVE_ONE_SAMPLE // 20
233
234             CONVOLVE_ONE_SAMPLE // 21
235             CONVOLVE_ONE_SAMPLE // 22
236             CONVOLVE_ONE_SAMPLE // 23
237             CONVOLVE_ONE_SAMPLE // 24
238             CONVOLVE_ONE_SAMPLE // 25
239             CONVOLVE_ONE_SAMPLE // 26
240             CONVOLVE_ONE_SAMPLE // 27
241             CONVOLVE_ONE_SAMPLE // 28
242             CONVOLVE_ONE_SAMPLE // 29
243             CONVOLVE_ONE_SAMPLE // 30
244
245             CONVOLVE_ONE_SAMPLE // 31
246             CONVOLVE_ONE_SAMPLE // 32
247             CONVOLVE_ONE_SAMPLE // 33
248             CONVOLVE_ONE_SAMPLE // 34
249             CONVOLVE_ONE_SAMPLE // 35
250             CONVOLVE_ONE_SAMPLE // 36
251             CONVOLVE_ONE_SAMPLE // 37
252             CONVOLVE_ONE_SAMPLE // 38
253             CONVOLVE_ONE_SAMPLE // 39
254             CONVOLVE_ONE_SAMPLE // 40
255
256             CONVOLVE_ONE_SAMPLE // 41
257             CONVOLVE_ONE_SAMPLE // 42
258             CONVOLVE_ONE_SAMPLE // 43
259             CONVOLVE_ONE_SAMPLE // 44
260             CONVOLVE_ONE_SAMPLE // 45
261             CONVOLVE_ONE_SAMPLE // 46
262             CONVOLVE_ONE_SAMPLE // 47
263             CONVOLVE_ONE_SAMPLE // 48
264             CONVOLVE_ONE_SAMPLE // 49
265             CONVOLVE_ONE_SAMPLE // 50
266
267             CONVOLVE_ONE_SAMPLE // 51
268             CONVOLVE_ONE_SAMPLE // 52
269             CONVOLVE_ONE_SAMPLE // 53
270             CONVOLVE_ONE_SAMPLE // 54
271             CONVOLVE_ONE_SAMPLE // 55
272             CONVOLVE_ONE_SAMPLE // 56
273             CONVOLVE_ONE_SAMPLE // 57
274             CONVOLVE_ONE_SAMPLE // 58
275             CONVOLVE_ONE_SAMPLE // 59
276             CONVOLVE_ONE_SAMPLE // 60
277
278             CONVOLVE_ONE_SAMPLE // 61
279             CONVOLVE_ONE_SAMPLE // 62
280             CONVOLVE_ONE_SAMPLE // 63
281             CONVOLVE_ONE_SAMPLE // 64
282             CONVOLVE_ONE_SAMPLE // 65
283             CONVOLVE_ONE_SAMPLE // 66
284             CONVOLVE_ONE_SAMPLE // 67
285             CONVOLVE_ONE_SAMPLE // 68
286             CONVOLVE_ONE_SAMPLE // 69
287             CONVOLVE_ONE_SAMPLE // 70
288
289             CONVOLVE_ONE_SAMPLE // 71
290             CONVOLVE_ONE_SAMPLE // 72
291             CONVOLVE_ONE_SAMPLE // 73
292             CONVOLVE_ONE_SAMPLE // 74
293             CONVOLVE_ONE_SAMPLE // 75
294             CONVOLVE_ONE_SAMPLE // 76
295             CONVOLVE_ONE_SAMPLE // 77
296             CONVOLVE_ONE_SAMPLE // 78
297             CONVOLVE_ONE_SAMPLE // 79
298             CONVOLVE_ONE_SAMPLE // 80
299
300             CONVOLVE_ONE_SAMPLE // 81
301             CONVOLVE_ONE_SAMPLE // 82
302             CONVOLVE_ONE_SAMPLE // 83
303             CONVOLVE_ONE_SAMPLE // 84
304             CONVOLVE_ONE_SAMPLE // 85
305             CONVOLVE_ONE_SAMPLE // 86
306             CONVOLVE_ONE_SAMPLE // 87
307             CONVOLVE_ONE_SAMPLE // 88
308             CONVOLVE_ONE_SAMPLE // 89
309             CONVOLVE_ONE_SAMPLE // 90
310
311             CONVOLVE_ONE_SAMPLE // 91
312             CONVOLVE_ONE_SAMPLE // 92
313             CONVOLVE_ONE_SAMPLE // 93
314             CONVOLVE_ONE_SAMPLE // 94
315             CONVOLVE_ONE_SAMPLE // 95
316             CONVOLVE_ONE_SAMPLE // 96
317             CONVOLVE_ONE_SAMPLE // 97
318             CONVOLVE_ONE_SAMPLE // 98
319             CONVOLVE_ONE_SAMPLE // 99
320             CONVOLVE_ONE_SAMPLE // 100
321
322             CONVOLVE_ONE_SAMPLE // 101
323             CONVOLVE_ONE_SAMPLE // 102
324             CONVOLVE_ONE_SAMPLE // 103
325             CONVOLVE_ONE_SAMPLE // 104
326             CONVOLVE_ONE_SAMPLE // 105
327             CONVOLVE_ONE_SAMPLE // 106
328             CONVOLVE_ONE_SAMPLE // 107
329             CONVOLVE_ONE_SAMPLE // 108
330             CONVOLVE_ONE_SAMPLE // 109
331             CONVOLVE_ONE_SAMPLE // 110
332
333             CONVOLVE_ONE_SAMPLE // 111
334             CONVOLVE_ONE_SAMPLE // 112
335             CONVOLVE_ONE_SAMPLE // 113
336             CONVOLVE_ONE_SAMPLE // 114
337             CONVOLVE_ONE_SAMPLE // 115
338             CONVOLVE_ONE_SAMPLE // 116
339             CONVOLVE_ONE_SAMPLE // 117
340             CONVOLVE_ONE_SAMPLE // 118
341             CONVOLVE_ONE_SAMPLE // 119
342             CONVOLVE_ONE_SAMPLE // 120
343
344             CONVOLVE_ONE_SAMPLE // 121
345             CONVOLVE_ONE_SAMPLE // 122
346             CONVOLVE_ONE_SAMPLE // 123
347             CONVOLVE_ONE_SAMPLE // 124
348             CONVOLVE_ONE_SAMPLE // 125
349             CONVOLVE_ONE_SAMPLE // 126
350             CONVOLVE_ONE_SAMPLE // 127
351             CONVOLVE_ONE_SAMPLE // 128
352         } else {
353             while (j < kernelSize) {
354                 // Non-optimized using actual while loop.
355                 CONVOLVE_ONE_SAMPLE
356             }
357         }
358         destP[i++] = sum;
359     }
360
361     // Copy 2nd half of input buffer to 1st half.
362     memcpy(m_buffer.data(), inputP, sizeof(float) * framesToProcess);
363 #endif
364 }
365
366 void DirectConvolver::reset()
367 {
368     m_buffer.zero();
369 #if USE(WEBAUDIO_IPP)
370     m_overlayBuffer.zero();
371 #endif // USE(WEBAUDIO_IPP)
372 }
373
374 } // namespace WebCore
375
376 #endif // ENABLE(WEB_AUDIO)