Coverage Report

Created: 2026-10-12 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gstreamer/subprojects/gst-plugins-base/gst-libs/gst/audio/audio-resampler-x86-sse2.c
Line
Count
Source
1
/* GStreamer
2
 * Copyright (C) <2016> Wim Taymans <wim.taymans@gmail.com>
3
 *
4
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Library General Public
6
 * License as published by the Free Software Foundation; either
7
 * version 2 of the License, or (at your option) any later version.
8
 *
9
 * This library is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 * Library General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Library General Public
15
 * License along with this library; if not, write to the
16
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17
 * Boston, MA 02110-1301, USA.
18
 */
19
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23
24
#include "audio-resampler-x86-sse2.h"
25
26
#include <immintrin.h>
27
28
static inline void
29
inner_product_gint16_full_1_sse2 (gint16 * o, const gint16 * a,
30
    const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
31
7.57M
{
32
7.57M
  gint i;
33
7.57M
  __m128i sum, t;
34
35
7.57M
  sum = _mm_setzero_si128 ();
36
37
28.7M
  for (i = 0; i < len; i += 16) {
38
21.1M
    t = _mm_loadu_si128 ((__m128i *) (a + i));
39
21.1M
    sum =
40
21.1M
        _mm_add_epi32 (sum, _mm_madd_epi16 (t,
41
21.1M
            _mm_load_si128 ((__m128i *) (b + i + 0))));
42
43
21.1M
    t = _mm_loadu_si128 ((__m128i *) (a + i + 8));
44
21.1M
    sum =
45
21.1M
        _mm_add_epi32 (sum, _mm_madd_epi16 (t,
46
21.1M
            _mm_load_si128 ((__m128i *) (b + i + 8))));
47
21.1M
  }
48
7.57M
  sum = _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (2, 3, 2, 3)));
49
7.57M
  sum = _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (1, 1, 1, 1)));
50
51
7.57M
  sum = _mm_add_epi32 (sum, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
52
7.57M
  sum = _mm_srai_epi32 (sum, PRECISION_S16);
53
7.57M
  sum = _mm_packs_epi32 (sum, sum);
54
7.57M
  *o = _mm_extract_epi16 (sum, 0);
55
7.57M
}
56
57
static inline void
58
inner_product_gint16_linear_1_sse2 (gint16 * o, const gint16 * a,
59
    const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
60
0
{
61
0
  gint i = 0;
62
0
  __m128i sum[2], t;
63
0
  __m128i f = _mm_set_epi64x (0, *((gint64 *) icoeff));
64
0
  const gint16 *c[2] = { (gint16 *) ((gint8 *) b + 0 * bstride),
65
0
    (gint16 *) ((gint8 *) b + 1 * bstride)
66
0
  };
67
68
0
  sum[0] = sum[1] = _mm_setzero_si128 ();
69
0
  f = _mm_unpacklo_epi16 (f, sum[0]);
70
71
0
  for (; i < len; i += 16) {
72
0
    t = _mm_loadu_si128 ((__m128i *) (a + i + 0));
73
0
    sum[0] =
74
0
        _mm_add_epi32 (sum[0], _mm_madd_epi16 (t,
75
0
            _mm_load_si128 ((__m128i *) (c[0] + i + 0))));
76
0
    sum[1] =
77
0
        _mm_add_epi32 (sum[1], _mm_madd_epi16 (t,
78
0
            _mm_load_si128 ((__m128i *) (c[1] + i + 0))));
79
80
0
    t = _mm_loadu_si128 ((__m128i *) (a + i + 8));
81
0
    sum[0] =
82
0
        _mm_add_epi32 (sum[0], _mm_madd_epi16 (t,
83
0
            _mm_load_si128 ((__m128i *) (c[0] + i + 8))));
84
0
    sum[1] =
85
0
        _mm_add_epi32 (sum[1], _mm_madd_epi16 (t,
86
0
            _mm_load_si128 ((__m128i *) (c[1] + i + 8))));
87
0
  }
88
0
  sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
89
0
  sum[1] = _mm_srai_epi32 (sum[1], PRECISION_S16);
90
91
0
  sum[0] =
92
0
      _mm_madd_epi16 (sum[0], _mm_shuffle_epi32 (f, _MM_SHUFFLE (0, 0, 0, 0)));
93
0
  sum[1] =
94
0
      _mm_madd_epi16 (sum[1], _mm_shuffle_epi32 (f, _MM_SHUFFLE (1, 1, 1, 1)));
95
0
  sum[0] = _mm_add_epi32 (sum[0], sum[1]);
96
97
0
  sum[0] =
98
0
      _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (2, 3, 2,
99
0
              3)));
100
0
  sum[0] =
101
0
      _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (1, 1, 1,
102
0
              1)));
103
104
0
  sum[0] = _mm_add_epi32 (sum[0], _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
105
0
  sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
106
0
  sum[0] = _mm_packs_epi32 (sum[0], sum[0]);
107
0
  *o = _mm_extract_epi16 (sum[0], 0);
108
0
}
109
110
static inline void
111
inner_product_gint16_cubic_1_sse2 (gint16 * o, const gint16 * a,
112
    const gint16 * b, gint len, const gint16 * icoeff, gint bstride)
113
3.23M
{
114
3.23M
  gint i = 0;
115
3.23M
  __m128i sum[4], t[4];
116
3.23M
  __m128i f = _mm_set_epi64x (0, *((long long *) icoeff));
117
3.23M
  const gint16 *c[4] = { (gint16 *) ((gint8 *) b + 0 * bstride),
118
3.23M
    (gint16 *) ((gint8 *) b + 1 * bstride),
119
3.23M
    (gint16 *) ((gint8 *) b + 2 * bstride),
120
3.23M
    (gint16 *) ((gint8 *) b + 3 * bstride)
121
3.23M
  };
122
123
3.23M
  sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_si128 ();
124
3.23M
  f = _mm_unpacklo_epi16 (f, sum[0]);
125
126
24.0M
  for (; i < len; i += 8) {
127
20.7M
    t[0] = _mm_loadu_si128 ((__m128i *) (a + i));
128
20.7M
    sum[0] =
129
20.7M
        _mm_add_epi32 (sum[0], _mm_madd_epi16 (t[0],
130
20.7M
            _mm_load_si128 ((__m128i *) (c[0] + i))));
131
20.7M
    sum[1] =
132
20.7M
        _mm_add_epi32 (sum[1], _mm_madd_epi16 (t[0],
133
20.7M
            _mm_load_si128 ((__m128i *) (c[1] + i))));
134
20.7M
    sum[2] =
135
20.7M
        _mm_add_epi32 (sum[2], _mm_madd_epi16 (t[0],
136
20.7M
            _mm_load_si128 ((__m128i *) (c[2] + i))));
137
20.7M
    sum[3] =
138
20.7M
        _mm_add_epi32 (sum[3], _mm_madd_epi16 (t[0],
139
20.7M
            _mm_load_si128 ((__m128i *) (c[3] + i))));
140
20.7M
  }
141
3.23M
  t[0] = _mm_unpacklo_epi32 (sum[0], sum[1]);
142
3.23M
  t[1] = _mm_unpacklo_epi32 (sum[2], sum[3]);
143
3.23M
  t[2] = _mm_unpackhi_epi32 (sum[0], sum[1]);
144
3.23M
  t[3] = _mm_unpackhi_epi32 (sum[2], sum[3]);
145
146
3.23M
  sum[0] =
147
3.23M
      _mm_add_epi32 (_mm_unpacklo_epi64 (t[0], t[1]), _mm_unpackhi_epi64 (t[0],
148
3.23M
          t[1]));
149
3.23M
  sum[2] =
150
3.23M
      _mm_add_epi32 (_mm_unpacklo_epi64 (t[2], t[3]), _mm_unpackhi_epi64 (t[2],
151
3.23M
          t[3]));
152
3.23M
  sum[0] = _mm_add_epi32 (sum[0], sum[2]);
153
154
3.23M
  sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
155
3.23M
  sum[0] = _mm_madd_epi16 (sum[0], f);
156
157
3.23M
  sum[0] =
158
3.23M
      _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (2, 3, 2,
159
3.23M
              3)));
160
3.23M
  sum[0] =
161
3.23M
      _mm_add_epi32 (sum[0], _mm_shuffle_epi32 (sum[0], _MM_SHUFFLE (1, 1, 1,
162
3.23M
              1)));
163
164
3.23M
  sum[0] = _mm_add_epi32 (sum[0], _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
165
3.23M
  sum[0] = _mm_srai_epi32 (sum[0], PRECISION_S16);
166
3.23M
  sum[0] = _mm_packs_epi32 (sum[0], sum[0]);
167
3.23M
  *o = _mm_extract_epi16 (sum[0], 0);
168
3.23M
}
169
170
static inline void
171
inner_product_gdouble_full_1_sse2 (gdouble * o, const gdouble * a,
172
    const gdouble * b, gint len, const gdouble * icoeff, gint bstride)
173
69.4M
{
174
69.4M
  gint i = 0;
175
69.4M
  __m128d sum = _mm_setzero_pd ();
176
177
544M
  for (; i < len; i += 8) {
178
475M
    sum =
179
475M
        _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 0),
180
475M
            _mm_load_pd (b + i + 0)));
181
475M
    sum =
182
475M
        _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 2),
183
475M
            _mm_load_pd (b + i + 2)));
184
475M
    sum =
185
475M
        _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 4),
186
475M
            _mm_load_pd (b + i + 4)));
187
475M
    sum =
188
475M
        _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 6),
189
475M
            _mm_load_pd (b + i + 6)));
190
475M
  }
191
69.4M
  sum = _mm_add_sd (sum, _mm_unpackhi_pd (sum, sum));
192
69.4M
  _mm_store_sd (o, sum);
193
69.4M
}
194
195
static inline void
196
inner_product_gdouble_linear_1_sse2 (gdouble * o, const gdouble * a,
197
    const gdouble * b, gint len, const gdouble * icoeff, gint bstride)
198
0
{
199
0
  gint i = 0;
200
0
  __m128d sum[2], t;
201
0
  const gdouble *c[2] = { (gdouble *) ((gint8 *) b + 0 * bstride),
202
0
    (gdouble *) ((gint8 *) b + 1 * bstride)
203
0
  };
204
205
0
  sum[0] = sum[1] = _mm_setzero_pd ();
206
207
0
  for (; i < len; i += 4) {
208
0
    t = _mm_loadu_pd (a + i + 0);
209
0
    sum[0] = _mm_add_pd (sum[0], _mm_mul_pd (t, _mm_load_pd (c[0] + i + 0)));
210
0
    sum[1] = _mm_add_pd (sum[1], _mm_mul_pd (t, _mm_load_pd (c[1] + i + 0)));
211
0
    t = _mm_loadu_pd (a + i + 2);
212
0
    sum[0] = _mm_add_pd (sum[0], _mm_mul_pd (t, _mm_load_pd (c[0] + i + 2)));
213
0
    sum[1] = _mm_add_pd (sum[1], _mm_mul_pd (t, _mm_load_pd (c[1] + i + 2)));
214
0
  }
215
0
  sum[0] = _mm_mul_pd (_mm_sub_pd (sum[0], sum[1]), _mm_load1_pd (icoeff));
216
0
  sum[0] = _mm_add_pd (sum[0], sum[1]);
217
0
  sum[0] = _mm_add_sd (sum[0], _mm_unpackhi_pd (sum[0], sum[0]));
218
0
  _mm_store_sd (o, sum[0]);
219
0
}
220
221
static inline void
222
inner_product_gdouble_cubic_1_sse2 (gdouble * o, const gdouble * a,
223
    const gdouble * b, gint len, const gdouble * icoeff, gint bstride)
224
166M
{
225
166M
  gint i;
226
166M
  __m128d f[2], sum[4], t;
227
166M
  const gdouble *c[4] = { (gdouble *) ((gint8 *) b + 0 * bstride),
228
166M
    (gdouble *) ((gint8 *) b + 1 * bstride),
229
166M
    (gdouble *) ((gint8 *) b + 2 * bstride),
230
166M
    (gdouble *) ((gint8 *) b + 3 * bstride)
231
166M
  };
232
233
166M
  f[0] = _mm_loadu_pd (icoeff + 0);
234
166M
  f[1] = _mm_loadu_pd (icoeff + 2);
235
166M
  sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_pd ();
236
237
4.19G
  for (i = 0; i < len; i += 2) {
238
4.02G
    t = _mm_loadu_pd (a + i + 0);
239
4.02G
    sum[0] = _mm_add_pd (sum[0], _mm_mul_pd (t, _mm_load_pd (c[0] + i)));
240
4.02G
    sum[1] = _mm_add_pd (sum[1], _mm_mul_pd (t, _mm_load_pd (c[1] + i)));
241
4.02G
    sum[2] = _mm_add_pd (sum[2], _mm_mul_pd (t, _mm_load_pd (c[2] + i)));
242
4.02G
    sum[3] = _mm_add_pd (sum[3], _mm_mul_pd (t, _mm_load_pd (c[3] + i)));
243
4.02G
  }
244
166M
  sum[0] =
245
166M
      _mm_mul_pd (sum[0], _mm_shuffle_pd (f[0], f[0], _MM_SHUFFLE2 (0, 0)));
246
166M
  sum[1] =
247
166M
      _mm_mul_pd (sum[1], _mm_shuffle_pd (f[0], f[0], _MM_SHUFFLE2 (1, 1)));
248
166M
  sum[2] =
249
166M
      _mm_mul_pd (sum[2], _mm_shuffle_pd (f[1], f[1], _MM_SHUFFLE2 (0, 0)));
250
166M
  sum[3] =
251
166M
      _mm_mul_pd (sum[3], _mm_shuffle_pd (f[1], f[1], _MM_SHUFFLE2 (1, 1)));
252
166M
  sum[0] = _mm_add_pd (sum[0], sum[1]);
253
166M
  sum[2] = _mm_add_pd (sum[2], sum[3]);
254
166M
  sum[0] = _mm_add_pd (sum[0], sum[2]);
255
166M
  sum[0] = _mm_add_sd (sum[0], _mm_unpackhi_pd (sum[0], sum[0]));
256
166M
  _mm_store_sd (o, sum[0]);
257
166M
}
258
259
MAKE_RESAMPLE_FUNC (gint16, full, 1, sse2);
260
MAKE_RESAMPLE_FUNC (gint16, linear, 1, sse2);
261
MAKE_RESAMPLE_FUNC (gint16, cubic, 1, sse2);
262
263
MAKE_RESAMPLE_FUNC (gdouble, full, 1, sse2);
264
MAKE_RESAMPLE_FUNC (gdouble, linear, 1, sse2);
265
MAKE_RESAMPLE_FUNC (gdouble, cubic, 1, sse2);
266
267
void
268
interpolate_gint16_linear_sse2 (gpointer op, const gpointer ap,
269
    gint len, const gpointer icp, gint astride)
270
0
{
271
0
  gint i = 0;
272
0
  gint16 *o = op, *a = ap, *ic = icp;
273
0
  __m128i ta, tb, t1, t2;
274
0
  __m128i f = _mm_set_epi64x (0, *((gint64 *) ic));
275
0
  const gint16 *c[2] = { (gint16 *) ((gint8 *) a + 0 * astride),
276
0
    (gint16 *) ((gint8 *) a + 1 * astride)
277
0
  };
278
279
0
  f = _mm_unpacklo_epi32 (f, f);
280
0
  f = _mm_unpacklo_epi64 (f, f);
281
282
0
  for (; i < len; i += 8) {
283
0
    ta = _mm_load_si128 ((__m128i *) (c[0] + i));
284
0
    tb = _mm_load_si128 ((__m128i *) (c[1] + i));
285
286
0
    t1 = _mm_madd_epi16 (_mm_unpacklo_epi16 (ta, tb), f);
287
0
    t2 = _mm_madd_epi16 (_mm_unpackhi_epi16 (ta, tb), f);
288
289
0
    t1 = _mm_add_epi32 (t1, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
290
0
    t2 = _mm_add_epi32 (t2, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
291
292
0
    t1 = _mm_srai_epi32 (t1, PRECISION_S16);
293
0
    t2 = _mm_srai_epi32 (t2, PRECISION_S16);
294
295
0
    t1 = _mm_packs_epi32 (t1, t2);
296
0
    _mm_store_si128 ((__m128i *) (o + i), t1);
297
0
  }
298
0
}
299
300
void
301
interpolate_gint16_cubic_sse2 (gpointer op, const gpointer ap,
302
    gint len, const gpointer icp, gint astride)
303
31.6k
{
304
31.6k
  gint i = 0;
305
31.6k
  gint16 *o = op, *a = ap, *ic = icp;
306
31.6k
  __m128i ta, tb, tl1, tl2, th1, th2;
307
31.6k
  __m128i f[2];
308
31.6k
  const gint16 *c[4] = { (gint16 *) ((gint8 *) a + 0 * astride),
309
31.6k
    (gint16 *) ((gint8 *) a + 1 * astride),
310
31.6k
    (gint16 *) ((gint8 *) a + 2 * astride),
311
31.6k
    (gint16 *) ((gint8 *) a + 3 * astride)
312
31.6k
  };
313
314
31.6k
  f[0] = _mm_set_epi16 (ic[1], ic[0], ic[1], ic[0], ic[1], ic[0], ic[1], ic[0]);
315
31.6k
  f[1] = _mm_set_epi16 (ic[3], ic[2], ic[3], ic[2], ic[3], ic[2], ic[3], ic[2]);
316
317
434k
  for (; i < len; i += 8) {
318
402k
    ta = _mm_load_si128 ((__m128i *) (c[0] + i));
319
402k
    tb = _mm_load_si128 ((__m128i *) (c[1] + i));
320
321
402k
    tl1 = _mm_madd_epi16 (_mm_unpacklo_epi16 (ta, tb), f[0]);
322
402k
    th1 = _mm_madd_epi16 (_mm_unpackhi_epi16 (ta, tb), f[0]);
323
324
402k
    ta = _mm_load_si128 ((__m128i *) (c[2] + i));
325
402k
    tb = _mm_load_si128 ((__m128i *) (c[3] + i));
326
327
402k
    tl2 = _mm_madd_epi16 (_mm_unpacklo_epi16 (ta, tb), f[1]);
328
402k
    th2 = _mm_madd_epi16 (_mm_unpackhi_epi16 (ta, tb), f[1]);
329
330
402k
    tl1 = _mm_add_epi32 (tl1, tl2);
331
402k
    th1 = _mm_add_epi32 (th1, th2);
332
333
402k
    tl1 = _mm_add_epi32 (tl1, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
334
402k
    th1 = _mm_add_epi32 (th1, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
335
336
402k
    tl1 = _mm_srai_epi32 (tl1, PRECISION_S16);
337
402k
    th1 = _mm_srai_epi32 (th1, PRECISION_S16);
338
339
402k
    tl1 = _mm_packs_epi32 (tl1, th1);
340
402k
    _mm_store_si128 ((__m128i *) (o + i), tl1);
341
402k
  }
342
31.6k
}
343
344
void
345
interpolate_gdouble_linear_sse2 (gpointer op, const gpointer ap,
346
    gint len, const gpointer icp, gint astride)
347
0
{
348
0
  gint i;
349
0
  gdouble *o = op, *a = ap, *ic = icp;
350
0
  __m128d f[2], t1, t2;
351
0
  const gdouble *c[2] = { (gdouble *) ((gint8 *) a + 0 * astride),
352
0
    (gdouble *) ((gint8 *) a + 1 * astride)
353
0
  };
354
355
0
  f[0] = _mm_load1_pd (ic + 0);
356
0
  f[1] = _mm_load1_pd (ic + 1);
357
358
0
  for (i = 0; i < len; i += 4) {
359
0
    t1 = _mm_mul_pd (_mm_load_pd (c[0] + i + 0), f[0]);
360
0
    t2 = _mm_mul_pd (_mm_load_pd (c[1] + i + 0), f[1]);
361
0
    _mm_store_pd (o + i + 0, _mm_add_pd (t1, t2));
362
363
0
    t1 = _mm_mul_pd (_mm_load_pd (c[0] + i + 2), f[0]);
364
0
    t2 = _mm_mul_pd (_mm_load_pd (c[1] + i + 2), f[1]);
365
0
    _mm_store_pd (o + i + 2, _mm_add_pd (t1, t2));
366
0
  }
367
0
}
368
369
void
370
interpolate_gdouble_cubic_sse2 (gpointer op, const gpointer ap,
371
    gint len, const gpointer icp, gint astride)
372
35.2k
{
373
35.2k
  gint i;
374
35.2k
  gdouble *o = op, *a = ap, *ic = icp;
375
35.2k
  __m128d f[4], t[4];
376
35.2k
  const gdouble *c[4] = { (gdouble *) ((gint8 *) a + 0 * astride),
377
35.2k
    (gdouble *) ((gint8 *) a + 1 * astride),
378
35.2k
    (gdouble *) ((gint8 *) a + 2 * astride),
379
35.2k
    (gdouble *) ((gint8 *) a + 3 * astride)
380
35.2k
  };
381
382
35.2k
  f[0] = _mm_load1_pd (ic + 0);
383
35.2k
  f[1] = _mm_load1_pd (ic + 1);
384
35.2k
  f[2] = _mm_load1_pd (ic + 2);
385
35.2k
  f[3] = _mm_load1_pd (ic + 3);
386
387
1.10M
  for (i = 0; i < len; i += 2) {
388
1.06M
    t[0] = _mm_mul_pd (_mm_load_pd (c[0] + i + 0), f[0]);
389
1.06M
    t[1] = _mm_mul_pd (_mm_load_pd (c[1] + i + 0), f[1]);
390
1.06M
    t[2] = _mm_mul_pd (_mm_load_pd (c[2] + i + 0), f[2]);
391
1.06M
    t[3] = _mm_mul_pd (_mm_load_pd (c[3] + i + 0), f[3]);
392
1.06M
    t[0] = _mm_add_pd (t[0], t[1]);
393
1.06M
    t[2] = _mm_add_pd (t[2], t[3]);
394
1.06M
    _mm_store_pd (o + i + 0, _mm_add_pd (t[0], t[2]));
395
1.06M
  }
396
35.2k
}