]> git.sesse.net Git - nageru/blob - patches/zita-resampler-sse.diff
Add some useful (pending) upstream patches that have not gone in yet.
[nageru] / patches / zita-resampler-sse.diff
1 diff -ur orig/zita-resampler-1.3.0/libs/resampler.cc zita-resampler-1.3.0/libs/resampler.cc
2 --- orig/zita-resampler-1.3.0/libs/resampler.cc 2012-10-26 22:58:55.000000000 +0200
3 +++ zita-resampler-1.3.0/libs/resampler.cc      2015-11-15 12:27:42.764591015 +0100
4 @@ -24,6 +24,10 @@
5  #include <math.h>
6  #include <zita-resampler/resampler.h>
7  
8 +#ifdef __SSE2__
9 +#include <xmmintrin.h>
10 +#endif
11 +
12  
13  static unsigned int gcd (unsigned int a, unsigned int b)
14  {
15 @@ -47,6 +51,45 @@
16      return 1; 
17  }
18  
19 +#ifdef __SSE2__
20 +
21 +static inline void calc_stereo_sample_sse (unsigned int hl,
22 +                                           float *c1,
23 +                                           float *c2,
24 +                                           float *q1,
25 +                                           float *q2,
26 +                                           float *out_data)
27 +{
28 +    unsigned int   i;
29 +    __m128         denorm, s, w1, w2;
30 +
31 +    denorm = _mm_set1_ps (1e-20f);
32 +    s = denorm;
33 +    for (i = 0; i < hl; i += 4)
34 +    {
35 +       q2 -= 8;
36 +
37 +       // s += *q1 * c1 [i];
38 +       w1 = _mm_loadu_ps (&c1 [i]);
39 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (q1),     _mm_unpacklo_ps (w1, w1)));
40 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (q1 + 4), _mm_unpackhi_ps (w1, w1)));
41 +
42 +       // s += *q2 * c2 [i];
43 +       w2 = _mm_loadu_ps (&c2 [i]);
44 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (q2 + 4), _mm_shuffle_ps (w2, w2, _MM_SHUFFLE (0, 0, 1, 1))));
45 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (q2),     _mm_shuffle_ps (w2, w2, _MM_SHUFFLE (2, 2, 3, 3))));
46 +
47 +       q1 += 8;
48 +    }
49 +    s = _mm_sub_ps (s, denorm);
50 +    s = _mm_add_ps (s, _mm_shuffle_ps (s, s, _MM_SHUFFLE (1, 0, 3, 2)));
51 +
52 +    // Writes two bytes more than we want, but this is fine since out_count >= 2.
53 +    _mm_storeu_ps (out_data, s);
54 +}
55 +
56 +#endif
57 +
58  
59  Resampler::Resampler (void) :
60      _table (0),
61 @@ -213,18 +256,28 @@
62                 {
63                     float *c1 = _table->_ctab + hl * ph;
64                     float *c2 = _table->_ctab + hl * (np - ph);
65 -                   for (c = 0; c < _nchan; c++)
66 +#ifdef __SSE2__
67 +                   if ((hl % 4) == 0 && _nchan == 2 && out_count >= 2)
68                     {
69 -                       float *q1 = p1 + c;
70 -                       float *q2 = p2 + c;
71 -                       float s = 1e-20f;
72 -                       for (i = 0; i < hl; i++)
73 +                       calc_stereo_sample_sse (hl, c1, c2, p1, p2, out_data);
74 +                       out_data += 2;
75 +                   }
76 +                   else
77 +#endif
78 +                    {
79 +                       for (c = 0; c < _nchan; c++)
80                         {
81 -                           q2 -= _nchan;
82 -                           s += *q1 * c1 [i] + *q2 * c2 [i];
83 -                           q1 += _nchan;
84 +                           float *q1 = p1 + c;
85 +                           float *q2 = p2 + c;
86 +                           float s = 1e-20f;
87 +                           for (i = 0; i < hl; i++)
88 +                           {
89 +                               q2 -= _nchan;
90 +                               s += *q1 * c1 [i] + *q2 * c2 [i];
91 +                               q1 += _nchan;
92 +                           }
93 +                           *out_data++ = s - 1e-20f;
94                         }
95 -                       *out_data++ = s - 1e-20f;
96                     }
97                 }
98                 else
99 @@ -260,4 +313,3 @@
100      return 0;
101  }
102  
103 -
104 diff -ur orig/zita-resampler-1.3.0/libs/vresampler.cc zita-resampler-1.3.0/libs/vresampler.cc
105 --- orig/zita-resampler-1.3.0/libs/vresampler.cc        2012-10-26 22:58:55.000000000 +0200
106 +++ zita-resampler-1.3.0/libs/vresampler.cc     2015-11-15 12:27:58.424544882 +0100
107 @@ -25,6 +25,58 @@
108  #include <zita-resampler/vresampler.h>
109  
110  
111 +#ifdef __SSE2__
112 +
113 +#include <xmmintrin.h>
114 +
115 +static inline void calc_stereo_sample_sse (int hl,
116 +                                           float b,
117 +                                           float *p1,
118 +                                           float *p2,
119 +                                           float *q1,
120 +                                           float *q2,
121 +                                           float *out_data)
122 +{
123 +    int            i;
124 +    __m128         denorm, bs, s, c1, c2, w1, w2;
125 +
126 +    denorm = _mm_set1_ps (1e-25f);
127 +    bs = _mm_set1_ps (b);
128 +    s = denorm;
129 +    for (i = 0; i < hl; i += 4)
130 +    {
131 +       p2 -= 8;
132 +
133 +       // _c1 [i] = q1 [i] + b * (q1 [i + hl] - q1 [i]);
134 +       w1 = _mm_loadu_ps (&q1 [i]);
135 +       w2 = _mm_loadu_ps (&q1 [i + hl]);
136 +       c1 = _mm_add_ps (w1, _mm_mul_ps(bs, _mm_sub_ps (w2, w1)));
137 +
138 +       // _c2 [i] = q2 [i] + b * (q2 [i - hl] - q2 [i]);
139 +       w1 = _mm_loadu_ps (&q2 [i]);
140 +       w2 = _mm_loadu_ps (&q2 [i - hl]);
141 +       c2 = _mm_add_ps (w1, _mm_mul_ps(bs, _mm_sub_ps (w2, w1)));
142 +
143 +       // s += *p1 * _c1 [i];
144 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (p1),     _mm_unpacklo_ps (c1, c1)));
145 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (p1 + 4), _mm_unpackhi_ps (c1, c1)));
146 +
147 +       // s += *p2 * _c2 [i];
148 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (p2 + 4), _mm_shuffle_ps (c2, c2, _MM_SHUFFLE (0, 0, 1, 1))));
149 +       s = _mm_add_ps (s, _mm_mul_ps (_mm_loadu_ps (p2),     _mm_shuffle_ps (c2, c2, _MM_SHUFFLE (2, 2, 3, 3))));
150 +
151 +       p1 += 8;
152 +    }
153 +    s = _mm_sub_ps (s, denorm);
154 +    s = _mm_add_ps (s, _mm_shuffle_ps (s, s, _MM_SHUFFLE (1, 0, 3, 2)));
155 +
156 +    // Writes two bytes more than we want, but this is fine since out_count >= 2.
157 +    _mm_storeu_ps (out_data, s);
158 +}
159 +
160 +#endif
161 +
162 +
163  VResampler::VResampler (void) :
164      _table (0),
165      _nchan (0),
166 @@ -212,23 +264,33 @@
167                     a = 1.0f - b;
168                     q1 = _table->_ctab + hl * k;
169                     q2 = _table->_ctab + hl * (np - k);
170 -                   for (i = 0; i < hl; i++)
171 +#ifdef __SSE2__
172 +                   if ((hl % 4) == 0 && _nchan == 2 && out_count >= 2)
173                     {
174 -                        _c1 [i] = a * q1 [i] + b * q1 [i + hl];
175 -                       _c2 [i] = a * q2 [i] + b * q2 [i - hl];
176 +                       calc_stereo_sample_sse (hl, b, p1, p2, q1, q2, out_data);
177 +                       out_data += 2;
178                     }
179 -                   for (c = 0; c < _nchan; c++)
180 +                   else
181 +#endif
182                     {
183 -                       q1 = p1 + c;
184 -                       q2 = p2 + c;
185 -                       a = 1e-25f;
186 -                       for (i = 0; i < hl; i++)
187 -                       {
188 -                           q2 -= _nchan;
189 -                           a += *q1 * _c1 [i] + *q2 * _c2 [i];
190 -                           q1 += _nchan;
191 -                       }
192 -                       *out_data++ = a - 1e-25f;
193 +                       for (i = 0; i < hl; i++)
194 +                       {
195 +                           _c1 [i] = a * q1 [i] + b * q1 [i + hl];
196 +                           _c2 [i] = a * q2 [i] + b * q2 [i - hl];
197 +                       }
198 +                       for (c = 0; c < _nchan; c++)
199 +                       {
200 +                           q1 = p1 + c;
201 +                           q2 = p2 + c;
202 +                           a = 1e-25f;
203 +                           for (i = 0; i < hl; i++)
204 +                           {
205 +                               q2 -= _nchan;
206 +                               a += *q1 * _c1 [i] + *q2 * _c2 [i];
207 +                               q1 += _nchan;
208 +                           }
209 +                           *out_data++ = a - 1e-25f;
210 +                       }
211                     }
212                 }
213                 else