2 * Copyright (C) <2015> Wim Taymans <wim.taymans@gmail.com>
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.
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.
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.
20 #if defined (HAVE_XMMINTRIN_H) && defined(__SSE__)
21 #include <xmmintrin.h>
24 inner_product_gfloat_none_1_sse (gfloat * o, const gfloat * a,
25 const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
28 __m128 sum = _mm_setzero_ps ();
30 for (; i < len; i += 8) {
32 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 0),
33 _mm_load_ps (b + i + 0)));
35 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 4),
36 _mm_load_ps (b + i + 4)));
38 sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
39 sum = _mm_add_ss (sum, _mm_shuffle_ps (sum, sum, 0x55));
40 _mm_store_ss (o, sum);
44 inner_product_gfloat_linear_1_sse (gfloat * o, const gfloat * a,
45 const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
48 __m128 sum = _mm_setzero_ps (), t, b0;
49 __m128 f = _mm_loadu_ps(icoeff);
51 for (; i < len; i += 4) {
52 t = _mm_loadu_ps (a + i);
54 b0 = _mm_loadh_pi (b0, (__m64 *) (b + (i+0)*oversample));
55 b0 = _mm_loadl_pi (b0, (__m64 *) (b + (i+1)*oversample));
58 _mm_add_ps (sum, _mm_mul_ps (_mm_unpacklo_ps (t, t), b0));
60 b0 = _mm_loadh_pi (b0, (__m64 *) (b + (i+2)*oversample));
61 b0 = _mm_loadl_pi (b0, (__m64 *) (b + (i+3)*oversample));
64 _mm_add_ps (sum, _mm_mul_ps (_mm_unpackhi_ps (t, t), b0));
66 sum = _mm_mul_ps (sum, f);
67 sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
68 sum = _mm_add_ss (sum, _mm_shuffle_ps (sum, sum, 0x55));
69 _mm_store_ss (o, sum);
73 inner_product_gfloat_cubic_1_sse (gfloat * o, const gfloat * a,
74 const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
77 __m128 sum = _mm_setzero_ps ();
78 __m128 f = _mm_loadu_ps(icoeff);
80 for (; i < len; i += 2) {
81 sum = _mm_add_ps (sum, _mm_mul_ps (_mm_load1_ps (a + i + 0),
82 _mm_loadu_ps (b + (i + 0) * oversample)));
83 sum = _mm_add_ps (sum, _mm_mul_ps (_mm_load1_ps (a + i + 1),
84 _mm_loadu_ps (b + (i + 1) * oversample)));
86 sum = _mm_mul_ps (sum, f);
87 sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
88 sum = _mm_add_ss (sum, _mm_shuffle_ps (sum, sum, 0x55));
89 _mm_store_ss (o, sum);
93 inner_product_gfloat_none_2_sse (gfloat * o, const gfloat * a,
94 const gfloat * b, gint len, const gfloat * icoeff, gint oversample)
97 __m128 sum = _mm_setzero_ps (), t;
99 for (; i < len; i += 8) {
100 t = _mm_load_ps (b + i);
102 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + 2 * i + 0),
103 _mm_unpacklo_ps (t, t)));
105 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + 2 * i + 4),
106 _mm_unpackhi_ps (t, t)));
108 t = _mm_load_ps (b + i + 4);
110 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + 2 * i + 8),
111 _mm_unpacklo_ps (t, t)));
113 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + 2 * i + 12),
114 _mm_unpackhi_ps (t, t)));
116 sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
117 *(gint64*)o = _mm_cvtsi128_si64 ((__m128i)sum);
120 MAKE_RESAMPLE_FUNC (gfloat, none, 1, sse);
121 MAKE_RESAMPLE_FUNC (gfloat, none, 2, sse);
122 MAKE_RESAMPLE_FUNC (gfloat, linear, 1, sse);
123 MAKE_RESAMPLE_FUNC (gfloat, cubic, 1, sse);
126 #if defined (HAVE_EMMINTRIN_H) && defined(__SSE2__)
127 #include <emmintrin.h>
130 inner_product_gint16_none_1_sse2 (gint16 * o, const gint16 * a,
131 const gint16 * b, gint len, const gint16 * icoeff, gint oversample)
136 sum = _mm_setzero_si128 ();
138 for (; i < len; i += 8) {
139 ta = _mm_loadu_si128 ((__m128i *) (a + i));
140 tb = _mm_load_si128 ((__m128i *) (b + i));
142 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (ta, tb));
145 _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (2, 3, 2,
148 _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (1, 1, 1,
151 sum = _mm_add_epi32 (sum, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
152 sum = _mm_srai_epi32 (sum, PRECISION_S16);
153 sum = _mm_packs_epi32 (sum, sum);
154 *o = _mm_extract_epi16 (sum, 0);
158 inner_product_gdouble_none_1_sse2 (gdouble * o, const gdouble * a,
159 const gdouble * b, gint len, const gdouble * icoeff, gint oversample)
162 __m128d sum = _mm_setzero_pd ();
164 for (; i < len; i += 8) {
166 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 0),
167 _mm_load_pd (b + i + 0)));
169 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 2),
170 _mm_load_pd (b + i + 2)));
172 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 4),
173 _mm_load_pd (b + i + 4)));
175 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 6),
176 _mm_load_pd (b + i + 6)));
178 sum = _mm_add_sd (sum, _mm_unpackhi_pd (sum, sum));
179 _mm_store_sd (o, sum);
183 inner_product_gint16_none_2_sse2 (gint16 * o, const gint16 * a,
184 const gint16 * b, gint len, const gint16 * icoeff, gint oversample)
187 __m128i sum, ta, tb, t1;
189 sum = _mm_setzero_si128 ();
191 for (; i < len; i += 8) {
192 tb = _mm_load_si128 ((__m128i *) (b + i));
194 t1 = _mm_unpacklo_epi16 (tb, tb);
195 ta = _mm_loadu_si128 ((__m128i *) (a + 2 * i));
197 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (ta, t1));
199 t1 = _mm_unpackhi_epi16 (tb, tb);
200 ta = _mm_loadu_si128 ((__m128i *) (a + 2 * i + 8));
202 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (ta, t1));
205 _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (2, 3, 2,
208 sum = _mm_add_epi32 (sum, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
209 sum = _mm_srai_epi32 (sum, PRECISION_S16);
210 sum = _mm_packs_epi32 (sum, sum);
211 *(gint32*)o = _mm_cvtsi128_si32 (sum);
215 inner_product_gdouble_none_2_sse2 (gdouble * o, const gdouble * a,
216 const gdouble * b, gint len, const gdouble * icoeff, gint oversample)
219 __m128d sum = _mm_setzero_pd (), t;
221 for (; i < len; i += 4) {
222 t = _mm_load_pd (b + i);
224 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i),
225 _mm_unpacklo_pd (t, t)));
227 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i + 2),
228 _mm_unpackhi_pd (t, t)));
230 t = _mm_load_pd (b + i + 2);
232 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i + 4),
233 _mm_unpacklo_pd (t, t)));
235 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i + 6),
236 _mm_unpackhi_pd (t, t)));
238 _mm_store_pd (o, sum);
241 MAKE_RESAMPLE_FUNC (gint16, none, 1, sse2);
242 MAKE_RESAMPLE_FUNC (gdouble, none, 1, sse2);
243 MAKE_RESAMPLE_FUNC (gint16, none, 2, sse2);
244 MAKE_RESAMPLE_FUNC (gdouble, none, 2, sse2);
247 #if defined (HAVE_SMMINTRIN_H) && defined(__SSE4_1__)
248 #include <smmintrin.h>
251 inner_product_gint32_none_1_sse41 (gint32 * o, const gint32 * a,
252 const gint32 * b, gint len, const gint32 * icoeff, gint oversample)
258 sum = _mm_setzero_si128 ();
260 for (; i < len; i += 8) {
261 ta = _mm_loadu_si128 ((__m128i *) (a + i));
262 tb = _mm_load_si128 ((__m128i *) (b + i));
265 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
266 _mm_unpacklo_epi32 (tb, tb)));
268 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
269 _mm_unpackhi_epi32 (tb, tb)));
271 ta = _mm_loadu_si128 ((__m128i *) (a + i + 4));
272 tb = _mm_load_si128 ((__m128i *) (b + i + 4));
275 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpacklo_epi32 (ta, ta),
276 _mm_unpacklo_epi32 (tb, tb)));
278 _mm_add_epi64 (sum, _mm_mul_epi32 (_mm_unpackhi_epi32 (ta, ta),
279 _mm_unpackhi_epi32 (tb, tb)));
281 sum = _mm_add_epi64 (sum, _mm_unpackhi_epi64 (sum, sum));
282 res = _mm_cvtsi128_si64 (sum);
284 res = (res + (1 << (PRECISION_S32 - 1))) >> PRECISION_S32;
285 *o = CLAMP (res, -(1L << 31), (1L << 31) - 1);
288 MAKE_RESAMPLE_FUNC (gint32, none, 1, sse41);
292 audio_resampler_check_x86 (const gchar *option)
294 if (!strcmp (option, "sse")) {
295 #if defined (HAVE_XMMINTRIN_H) && defined(__SSE__)
296 GST_DEBUG ("enable SSE optimisations");
297 resample_gfloat_none_1 = resample_gfloat_none_1_sse;
298 resample_gfloat_none_2 = resample_gfloat_none_2_sse;
299 resample_gfloat_linear_1 = resample_gfloat_linear_1_sse;
300 resample_gfloat_cubic_1 = resample_gfloat_cubic_1_sse;
302 } else if (!strcmp (option, "sse2")) {
303 #if defined (HAVE_EMMINTRIN_H) && defined(__SSE2__)
304 GST_DEBUG ("enable SSE2 optimisations");
305 resample_gint16_none_1 = resample_gint16_none_1_sse2;
306 resample_gfloat_none_1 = resample_gfloat_none_1_sse;
307 resample_gfloat_none_2 = resample_gfloat_none_2_sse;
308 resample_gdouble_none_1 = resample_gdouble_none_1_sse2;
309 resample_gint16_none_2 = resample_gint16_none_2_sse2;
310 resample_gdouble_none_2 = resample_gdouble_none_2_sse2;
311 resample_gfloat_linear_1 = resample_gfloat_linear_1_sse;
312 resample_gfloat_cubic_1 = resample_gfloat_cubic_1_sse;
314 } else if (!strcmp (option, "sse41")) {
315 #if defined (HAVE_SMMINTRIN_H) && defined(__SSE4_1__)
316 GST_DEBUG ("enable SSE41 optimisations");
317 resample_gint32_none_1 = resample_gint32_none_1_sse41;