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 #ifdef HAVE_EMMINTRIN_H
21 #include <emmintrin.h>
24 inner_product_gint16_1_sse2 (gint16 * o, const gint16 * a, const gint16 * b, gint len)
29 sum = _mm_setzero_si128 ();
31 for (; i < len; i += 8) {
32 ta = _mm_loadu_si128 ((__m128i *) (a + i));
33 tb = _mm_load_si128 ((__m128i *) (b + i));
35 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (ta, tb));
38 _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (2, 3, 2,
41 _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (1, 1, 1,
44 sum = _mm_add_epi32 (sum, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
45 sum = _mm_srai_epi32 (sum, PRECISION_S16);
46 sum = _mm_packs_epi32 (sum, sum);
47 *o = _mm_extract_epi16 (sum, 0);
51 inner_product_gfloat_1_sse (gfloat * o, const gfloat * a, const gfloat * b, gint len)
54 __m128 sum = _mm_setzero_ps ();
56 for (; i < len; i += 8) {
58 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 0),
59 _mm_load_ps (b + i + 0)));
61 _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 4),
62 _mm_load_ps (b + i + 4)));
64 sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
65 sum = _mm_add_ss (sum, _mm_shuffle_ps (sum, sum, 0x55));
66 _mm_store_ss (o, sum);
70 inner_product_gdouble_1_sse2 (gdouble * o, const gdouble * a, const gdouble * b,
74 __m128d sum = _mm_setzero_pd ();
76 for (; i < len; i += 8) {
78 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 0),
79 _mm_load_pd (b + i + 0)));
81 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 2),
82 _mm_load_pd (b + i + 2)));
84 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 4),
85 _mm_load_pd (b + i + 4)));
87 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + i + 6),
88 _mm_load_pd (b + i + 6)));
90 sum = _mm_add_sd (sum, _mm_unpackhi_pd (sum, sum));
91 _mm_store_sd (o, sum);
95 inner_product_gint16_2_sse2 (gint16 * o, const gint16 * a, const gint16 * b, gint len)
98 __m128i sum, ta, tb, t1;
100 sum = _mm_setzero_si128 ();
102 for (; i < len; i += 8) {
103 tb = _mm_load_si128 ((__m128i *) (b + i));
105 t1 = _mm_unpacklo_epi16 (tb, tb);
106 ta = _mm_loadu_si128 ((__m128i *) (a + 2 * i));
108 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (ta, t1));
110 t1 = _mm_unpackhi_epi16 (tb, tb);
111 ta = _mm_loadu_si128 ((__m128i *) (a + 2 * i + 8));
113 sum = _mm_add_epi32 (sum, _mm_madd_epi16 (ta, t1));
116 _mm_add_epi32 (sum, _mm_shuffle_epi32 (sum, _MM_SHUFFLE (2, 3, 2,
119 sum = _mm_add_epi32 (sum, _mm_set1_epi32 (1 << (PRECISION_S16 - 1)));
120 sum = _mm_srai_epi32 (sum, PRECISION_S16);
121 sum = _mm_packs_epi32 (sum, sum);
122 *(gint32*)o = _mm_cvtsi128_si32 (sum);
126 inner_product_gdouble_2_sse2 (gdouble * o, const gdouble * a, const gdouble * b,
130 __m128d sum = _mm_setzero_pd (), t;
132 for (; i < len; i += 4) {
133 t = _mm_load_pd (b + i);
135 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i),
136 _mm_unpacklo_pd (t, t)));
138 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i + 2),
139 _mm_unpackhi_pd (t, t)));
141 t = _mm_load_pd (b + i + 2);
143 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i + 4),
144 _mm_unpacklo_pd (t, t)));
146 _mm_add_pd (sum, _mm_mul_pd (_mm_loadu_pd (a + 2 * i + 6),
147 _mm_unpackhi_pd (t, t)));
149 _mm_store_pd (o, sum);
152 MAKE_RESAMPLE_FUNC (gint16, 1, sse2);
153 MAKE_RESAMPLE_FUNC (gfloat, 1, sse);
154 MAKE_RESAMPLE_FUNC (gdouble, 1, sse2);
155 MAKE_RESAMPLE_FUNC (gint16, 2, sse2);
156 MAKE_RESAMPLE_FUNC (gdouble, 2, sse2);
160 audio_resampler_check_x86 (const gchar *option)
162 #ifdef HAVE_EMMINTRIN_H
163 if (!strcmp (option, "sse")) {
164 GST_DEBUG ("enable SSE optimisations");
165 resample_gfloat_1 = resample_gfloat_1_sse;
166 } else if (!strcmp (option, "sse2")) {
167 GST_DEBUG ("enable SSE2 optimisations");
168 resample_gint16_1 = resample_gint16_1_sse2;
169 resample_gfloat_1 = resample_gfloat_1_sse;
170 resample_gdouble_1 = resample_gdouble_1_sse2;
171 resample_gint16_2 = resample_gint16_2_sse2;
172 resample_gdouble_2 = resample_gdouble_2_sse2;