• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-sse.h"
25 
26 #if defined (HAVE_XMMINTRIN_H) && defined(__SSE__)
27 #include <xmmintrin.h>
28 
29 static inline void
inner_product_gfloat_full_1_sse(gfloat * o,const gfloat * a,const gfloat * b,gint len,const gfloat * icoeff,gint bstride)30 inner_product_gfloat_full_1_sse (gfloat * o, const gfloat * a,
31     const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
32 {
33   gint i = 0;
34   __m128 sum = _mm_setzero_ps ();
35 
36   for (; i < len; i += 8) {
37     sum =
38         _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 0),
39             _mm_load_ps (b + i + 0)));
40     sum =
41         _mm_add_ps (sum, _mm_mul_ps (_mm_loadu_ps (a + i + 4),
42             _mm_load_ps (b + i + 4)));
43   }
44   sum = _mm_add_ps (sum, _mm_movehl_ps (sum, sum));
45   sum = _mm_add_ss (sum, _mm_shuffle_ps (sum, sum, 0x55));
46   _mm_store_ss (o, sum);
47 }
48 
49 static inline void
inner_product_gfloat_linear_1_sse(gfloat * o,const gfloat * a,const gfloat * b,gint len,const gfloat * icoeff,gint bstride)50 inner_product_gfloat_linear_1_sse (gfloat * o, const gfloat * a,
51     const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
52 {
53   gint i = 0;
54   __m128 sum[2], t;
55   const gfloat *c[2] = { (gfloat *) ((gint8 *) b + 0 * bstride),
56     (gfloat *) ((gint8 *) b + 1 * bstride)
57   };
58 
59   sum[0] = sum[1] = _mm_setzero_ps ();
60 
61   for (; i < len; i += 8) {
62     t = _mm_loadu_ps (a + i + 0);
63     sum[0] = _mm_add_ps (sum[0], _mm_mul_ps (t, _mm_load_ps (c[0] + i + 0)));
64     sum[1] = _mm_add_ps (sum[1], _mm_mul_ps (t, _mm_load_ps (c[1] + i + 0)));
65     t = _mm_loadu_ps (a + i + 4);
66     sum[0] = _mm_add_ps (sum[0], _mm_mul_ps (t, _mm_load_ps (c[0] + i + 4)));
67     sum[1] = _mm_add_ps (sum[1], _mm_mul_ps (t, _mm_load_ps (c[1] + i + 4)));
68   }
69   sum[0] = _mm_mul_ps (_mm_sub_ps (sum[0], sum[1]), _mm_load1_ps (icoeff));
70   sum[0] = _mm_add_ps (sum[0], sum[1]);
71   sum[0] = _mm_add_ps (sum[0], _mm_movehl_ps (sum[0], sum[0]));
72   sum[0] = _mm_add_ss (sum[0], _mm_shuffle_ps (sum[0], sum[0], 0x55));
73   _mm_store_ss (o, sum[0]);
74 }
75 
76 static inline void
inner_product_gfloat_cubic_1_sse(gfloat * o,const gfloat * a,const gfloat * b,gint len,const gfloat * icoeff,gint bstride)77 inner_product_gfloat_cubic_1_sse (gfloat * o, const gfloat * a,
78     const gfloat * b, gint len, const gfloat * icoeff, gint bstride)
79 {
80   gint i = 0;
81   __m128 sum[4];
82   __m128 t, f = _mm_loadu_ps (icoeff);
83   const gfloat *c[4] = { (gfloat *) ((gint8 *) b + 0 * bstride),
84     (gfloat *) ((gint8 *) b + 1 * bstride),
85     (gfloat *) ((gint8 *) b + 2 * bstride),
86     (gfloat *) ((gint8 *) b + 3 * bstride)
87   };
88 
89   sum[0] = sum[1] = sum[2] = sum[3] = _mm_setzero_ps ();
90 
91   for (; i < len; i += 4) {
92     t = _mm_loadu_ps (a + i);
93     sum[0] = _mm_add_ps (sum[0], _mm_mul_ps (t, _mm_load_ps (c[0] + i)));
94     sum[1] = _mm_add_ps (sum[1], _mm_mul_ps (t, _mm_load_ps (c[1] + i)));
95     sum[2] = _mm_add_ps (sum[2], _mm_mul_ps (t, _mm_load_ps (c[2] + i)));
96     sum[3] = _mm_add_ps (sum[3], _mm_mul_ps (t, _mm_load_ps (c[3] + i)));
97   }
98   sum[0] = _mm_mul_ps (sum[0], _mm_shuffle_ps (f, f, 0x00));
99   sum[1] = _mm_mul_ps (sum[1], _mm_shuffle_ps (f, f, 0x55));
100   sum[2] = _mm_mul_ps (sum[2], _mm_shuffle_ps (f, f, 0xaa));
101   sum[3] = _mm_mul_ps (sum[3], _mm_shuffle_ps (f, f, 0xff));
102   sum[0] = _mm_add_ps (sum[0], sum[1]);
103   sum[2] = _mm_add_ps (sum[2], sum[3]);
104   sum[0] = _mm_add_ps (sum[0], sum[2]);
105   sum[0] = _mm_add_ps (sum[0], _mm_movehl_ps (sum[0], sum[0]));
106   sum[0] = _mm_add_ss (sum[0], _mm_shuffle_ps (sum[0], sum[0], 0x55));
107   _mm_store_ss (o, sum[0]);
108 }
109 
110 MAKE_RESAMPLE_FUNC (gfloat, full, 1, sse);
111 MAKE_RESAMPLE_FUNC (gfloat, linear, 1, sse);
112 MAKE_RESAMPLE_FUNC (gfloat, cubic, 1, sse);
113 
114 void
interpolate_gfloat_linear_sse(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)115 interpolate_gfloat_linear_sse (gpointer op, const gpointer ap,
116     gint len, const gpointer icp, gint astride)
117 {
118   gint i;
119   gfloat *o = op, *a = ap, *ic = icp;
120   __m128 f[2], t1, t2;
121   const gfloat *c[2] = { (gfloat *) ((gint8 *) a + 0 * astride),
122     (gfloat *) ((gint8 *) a + 1 * astride)
123   };
124 
125   f[0] = _mm_load1_ps (ic + 0);
126   f[1] = _mm_load1_ps (ic + 1);
127 
128   for (i = 0; i < len; i += 8) {
129     t1 = _mm_mul_ps (_mm_load_ps (c[0] + i + 0), f[0]);
130     t2 = _mm_mul_ps (_mm_load_ps (c[1] + i + 0), f[1]);
131     _mm_store_ps (o + i + 0, _mm_add_ps (t1, t2));
132 
133     t1 = _mm_mul_ps (_mm_load_ps (c[0] + i + 4), f[0]);
134     t2 = _mm_mul_ps (_mm_load_ps (c[1] + i + 4), f[1]);
135     _mm_store_ps (o + i + 4, _mm_add_ps (t1, t2));
136   }
137 }
138 
139 void
interpolate_gfloat_cubic_sse(gpointer op,const gpointer ap,gint len,const gpointer icp,gint astride)140 interpolate_gfloat_cubic_sse (gpointer op, const gpointer ap,
141     gint len, const gpointer icp, gint astride)
142 {
143   gint i;
144   gfloat *o = op, *a = ap, *ic = icp;
145   __m128 f[4], t[4];
146   const gfloat *c[4] = { (gfloat *) ((gint8 *) a + 0 * astride),
147     (gfloat *) ((gint8 *) a + 1 * astride),
148     (gfloat *) ((gint8 *) a + 2 * astride),
149     (gfloat *) ((gint8 *) a + 3 * astride)
150   };
151 
152   f[0] = _mm_load1_ps (ic + 0);
153   f[1] = _mm_load1_ps (ic + 1);
154   f[2] = _mm_load1_ps (ic + 2);
155   f[3] = _mm_load1_ps (ic + 3);
156 
157   for (i = 0; i < len; i += 4) {
158     t[0] = _mm_mul_ps (_mm_load_ps (c[0] + i + 0), f[0]);
159     t[1] = _mm_mul_ps (_mm_load_ps (c[1] + i + 0), f[1]);
160     t[2] = _mm_mul_ps (_mm_load_ps (c[2] + i + 0), f[2]);
161     t[3] = _mm_mul_ps (_mm_load_ps (c[3] + i + 0), f[3]);
162     t[0] = _mm_add_ps (t[0], t[1]);
163     t[2] = _mm_add_ps (t[2], t[3]);
164     _mm_store_ps (o + i + 0, _mm_add_ps (t[0], t[2]));
165   }
166 }
167 
168 #endif
169