1 /*  _______         ____    __         ___    ___
2  * \    _  \       \    /  \  /       \   \  /   /       '   '  '
3  *  |  | \  \       |  |    ||         |   \/   |         .      .
4  *  |  |  |  |      |  |    ||         ||\  /|  |
5  *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
6  *  |  |  |  |      |  |    ||         ||    |  |         .      .
7  *  |  |_/  /        \  \__//          ||    |  |
8  * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
9  *                                                      /  \
10  *                                                     / .  \
11  * resample.c - Resampling helpers.                   / / \  \
12  *                                                   | <  /   \_
13  * By Bob and entheh.                                |  \/ /\   /
14  *                                                    \_  /  > /
15  * In order to find a good trade-off between            | \ / /
16  * speed and accuracy in this code, some tests          |  ' /
17  * were carried out regarding the behaviour of           \__/
18  * long long ints with gcc. The following code
19  * was tested:
20  *
21  * int a, b, c;
22  * c = ((long long)a * b) >> 16;
23  *
24  * DJGPP GCC Version 3.0.3 generated the following assembly language code for
25  * the multiplication and scaling, leaving the 32-bit result in EAX.
26  *
27  * movl  -8(%ebp), %eax    ; read one int into EAX
28  * imull -4(%ebp)          ; multiply by the other; result goes in EDX:EAX
29  * shrdl $16, %edx, %eax   ; shift EAX right 16, shifting bits in from EDX
30  *
31  * Note that a 32*32->64 multiplication is performed, allowing for high
32  * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
33  * so it is a minor concern when four multiplications are being performed
34  * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
35  * more cycles, so this method is unsuitable for use in the low-quality
36  * resamplers.
37  *
38  * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
39  * defined in dumb.h. We may investigate later what code MSVC generates, but
40  * if it seems too slow then we suggest you use a good compiler.
41  *
42  * FIXME: these comments are somewhat out of date now.
43  */
44 
45 #include <math.h>
46 #include "dumb.h"
47 
48 #include "internal/resampler.h"
49 #include "internal/mulsc.h"
50 
51 
52 
53 /* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
54  * called when it should be. There will be a considerable performance hit,
55  * since at least one condition has to be tested for every sample generated.
56  */
57 #ifdef HEAVYDEBUG
58 #define HEAVYASSERT(cond) ASSERT(cond)
59 #else
60 #define HEAVYASSERT(cond)
61 #endif
62 
63 
64 
65 /* Make MSVC shut the hell up about if ( upd ) UPDATE_VOLUME() conditions being constant */
66 #ifdef _MSC_VER
67 #pragma warning(disable:4127 4701)
68 #endif
69 
70 
71 
72 /* A global variable for controlling resampling quality wherever a local
73  * specification doesn't override it. The following values are valid:
74  *
75  *  0 - DUMB_RQ_ALIASING - fastest
76  *  1 - DUMB_RQ_BLEP     - nicer than aliasing, but slower
77  *  2 - DUMB_RQ_LINEAR
78  *  3 - DUMB_RQ_BLAM     - band-limited linear interpolation, nice but slower
79  *  4 - DUMB_RQ_CUBIC
80  *  5 - DUMB_RQ_FIR      - nicest
81  *
82  * Values outside the range 0-4 will behave the same as the nearest
83  * value within the range.
84  */
85 int dumb_resampling_quality = DUMB_RQ_CUBIC;
86 
87 
88 
89 /* From xs_Float.h ==============================================*/
90 #if __BIG_ENDIAN__
91 	#define _xs_iman_				1
92 #else
93 	#define _xs_iman_				0
94 #endif //BigEndian_
95 
96 #ifdef __GNUC__
97 #define finline inline
98 #else
99 #define finline __forceinline
100 #endif
101 
102 union _xs_doubleints
103 {
104 	double val;
105 	unsigned int ival[2];
106 };
107 
108 static const double _xs_doublemagic			= (6755399441055744.0); 	//2^52 * 1.5,  uses limited precisicion to floor
109 static const double _xs_doublemagicroundeps	= (.5f-(1.5e-8));			//almost .5f = .5f - 1e^(number of exp bit)
110 
xs_CRoundToInt(double val)111 static finline int xs_CRoundToInt(double val)
112 {
113 	union _xs_doubleints uval;
114 	val += _xs_doublemagic;
115 	uval.val = val;
116 	return uval.ival[_xs_iman_];
117 }
xs_FloorToInt(double val)118 static finline int xs_FloorToInt(double val)
119 {
120 	union _xs_doubleints uval;
121 	val -= _xs_doublemagicroundeps;
122 	val += _xs_doublemagic;
123 	uval.val = val;
124 	return uval.ival[_xs_iman_];
125 }
126 /* Not from xs_Float.h ==========================================*/
127 
128 
129 /* Executes the content 'iterator' times.
130  * Clobbers the 'iterator' variable.
131  * The loop is unrolled by four.
132  */
133 #if 0
134 #define LOOP4(iterator, CONTENT) \
135 { \
136 	if ((iterator) & 2) { \
137 		CONTENT; \
138 		CONTENT; \
139 	} \
140 	if ((iterator) & 1) { \
141 		CONTENT; \
142 	} \
143 	(iterator) >>= 2; \
144 	while (iterator) { \
145 		CONTENT; \
146 		CONTENT; \
147 		CONTENT; \
148 		CONTENT; \
149 		(iterator)--; \
150 	} \
151 }
152 #else
153 #define LOOP4(iterator, CONTENT) \
154 { \
155 	while ( (iterator)-- ) \
156 	{ \
157 		CONTENT; \
158 	} \
159 }
160 #endif
161 
162 #define PASTERAW(a, b) a ## b /* This does not expand macros in b ... */
163 #define PASTE(a, b) PASTERAW(a, b) /* ... but b is expanded during this substitution. */
164 
165 #define X PASTE(x.x, SRCBITS)
166 
167 
168 
169 /* Cubic resampler: look-up tables
170  *
171  * a = 1.5*x1 - 1.5*x2 + 0.5*x3 - 0.5*x0
172  * b = 2*x2 + x0 - 2.5*x1 - 0.5*x3
173  * c = 0.5*x2 - 0.5*x0
174  * d = x1
175  *
176  * x = a*t*t*t + b*t*t + c*t + d
177  *   = (-0.5*x0 + 1.5*x1 - 1.5*x2 + 0.5*x3) * t*t*t +
178  *     (   1*x0 - 2.5*x1 + 2  *x2 - 0.5*x3) * t*t +
179  *     (-0.5*x0          + 0.5*x2         ) * t +
180  *     (            1*x1                  )
181  *   = (-0.5*t*t*t + 1  *t*t - 0.5*t    ) * x0 +
182  *     ( 1.5*t*t*t - 2.5*t*t         + 1) * x1 +
183  *     (-1.5*t*t*t + 2  *t*t + 0.5*t    ) * x2 +
184  *     ( 0.5*t*t*t - 0.5*t*t            ) * x3
185  *   = A0(t) * x0 + A1(t) * x1 + A2(t) * x2 + A3(t) * x3
186  *
187  * A0, A1, A2 and A3 stay within the range [-1,1].
188  * In the tables, they are scaled with 14 fractional bits.
189  *
190  * Turns out we don't need to store A2 and A3; they are symmetrical to A1 and A0.
191  *
192  * TODO: A0 and A3 stay very small indeed. Consider different scale/resolution?
193  */
194 
195 static short cubicA0[1025], cubicA1[1025];
196 
_dumb_init_cubic(void)197 void _dumb_init_cubic(void)
198 {
199 	unsigned int t; /* 3*1024*1024*1024 is within range if it's unsigned */
200 	static int done = 0;
201 	if (done) return;
202 	for (t = 0; t < 1025; t++) {
203 		/* int casts to pacify warnings about negating unsigned values */
204 		cubicA0[t] = -(int)(  t*t*t >> 17) + (int)(  t*t >> 6) - (int)(t << 3);
205 		cubicA1[t] =  (int)(3*t*t*t >> 17) - (int)(5*t*t >> 7) + (int)(1 << 14);
206 	}
207 	resampler_init();
208 
209 	done = 1;
210 }
211 
212 
213 
214 /* Create resamplers for 24-in-32-bit source samples. */
215 
216 /* #define SUFFIX
217  * MSVC warns if we try to paste a null SUFFIX, so instead we define
218  * special macros for the function names that don't bother doing the
219  * corresponding paste. The more generic definitions are further down.
220  */
221 #define process_pickup PASTE(process_pickup, SUFFIX2)
222 #define dumb_resample PASTE(PASTE(dumb_resample, SUFFIX2), SUFFIX3)
223 #define dumb_resample_get_current_sample PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX2), SUFFIX3)
224 
225 #define SRCTYPE sample_t
226 #define SRCBITS 24
227 #define ALIAS(x, vol) MULSC(x, vol)
228 #define LINEAR(x0, x1) (x0 + MULSC(x1 - x0, subpos))
229 #define CUBIC(x0, x1, x2, x3) ( \
230 	MULSC(x0, cubicA0[subpos >> 6] << 2) + \
231 	MULSC(x1, cubicA1[subpos >> 6] << 2) + \
232 	MULSC(x2, cubicA1[1 + (subpos >> 6 ^ 1023)] << 2) + \
233 	MULSC(x3, cubicA0[1 + (subpos >> 6 ^ 1023)] << 2))
234 #define CUBICVOL(x, vol) MULSC(x, vol)
235 #define FIR(x) (x >> 8)
236 #include "resample.inc"
237 
238 /* Undefine the simplified macros. */
239 #undef dumb_resample_get_current_sample
240 #undef dumb_resample
241 #undef process_pickup
242 
243 
244 /* Now define the proper ones that use SUFFIX. */
245 #define dumb_reset_resampler PASTE(dumb_reset_resampler, SUFFIX)
246 #define dumb_start_resampler PASTE(dumb_start_resampler, SUFFIX)
247 #define process_pickup PASTE(PASTE(process_pickup, SUFFIX), SUFFIX2)
248 #define dumb_resample PASTE(PASTE(PASTE(dumb_resample, SUFFIX), SUFFIX2), SUFFIX3)
249 #define dumb_resample_get_current_sample PASTE(PASTE(PASTE(dumb_resample_get_current_sample, SUFFIX), SUFFIX2), SUFFIX3)
250 #define dumb_end_resampler PASTE(dumb_end_resampler, SUFFIX)
251 
252 /* Create resamplers for 16-bit source samples. */
253 #define SUFFIX _16
254 #define SRCTYPE short
255 #define SRCBITS 16
256 #define ALIAS(x, vol) (x * vol >> 8)
257 #define LINEAR(x0, x1) ((x0 << 8) + MULSC16(x1 - x0, subpos))
258 #define CUBIC(x0, x1, x2, x3) ( \
259 	x0 * cubicA0[subpos >> 6] + \
260 	x1 * cubicA1[subpos >> 6] + \
261 	x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
262 	x3 * cubicA0[1 + (subpos >> 6 ^ 1023)])
263 #define CUBICVOL(x, vol) MULSCV((x), ((vol) << 10))
264 #define FIR(x) (x)
265 #include "resample.inc"
266 
267 /* Create resamplers for 8-bit source samples. */
268 #define SUFFIX _8
269 #define SRCTYPE signed char
270 #define SRCBITS 8
271 #define ALIAS(x, vol) (x * vol)
272 #define LINEAR(x0, x1) ((x0 << 16) + (x1 - x0) * subpos)
273 #define CUBIC(x0, x1, x2, x3) (( \
274 	x0 * cubicA0[subpos >> 6] + \
275 	x1 * cubicA1[subpos >> 6] + \
276 	x2 * cubicA1[1 + (subpos >> 6 ^ 1023)] + \
277 	x3 * cubicA0[1 + (subpos >> 6 ^ 1023)]) << 6)
278 #define CUBICVOL(x, vol) MULSCV((x), ((vol) << 12))
279 #define FIR(x) (x << 8)
280 #include "resample.inc"
281 
282 
283 #undef dumb_reset_resampler
284 #undef dumb_start_resampler
285 #undef process_pickup
286 #undef dumb_resample
287 #undef dumb_resample_get_current_sample
288 #undef dumb_end_resampler
289 
290 
291 
dumb_reset_resampler_n(int n,DUMB_RESAMPLER * resampler,void * src,int src_channels,int32 pos,int32 start,int32 end,int quality)292 void dumb_reset_resampler_n(int n, DUMB_RESAMPLER *resampler, void *src, int src_channels, int32 pos, int32 start, int32 end, int quality)
293 {
294 	if (n == 8)
295 		dumb_reset_resampler_8(resampler, src, src_channels, pos, start, end, quality);
296 	else if (n == 16)
297 		dumb_reset_resampler_16(resampler, src, src_channels, pos, start, end, quality);
298 	else
299 		dumb_reset_resampler(resampler, src, src_channels, pos, start, end, quality);
300 }
301 
302 
303 
dumb_start_resampler_n(int n,void * src,int src_channels,int32 pos,int32 start,int32 end,int quality)304 DUMB_RESAMPLER *dumb_start_resampler_n(int n, void *src, int src_channels, int32 pos, int32 start, int32 end, int quality)
305 {
306 	if (n == 8)
307 		return dumb_start_resampler_8(src, src_channels, pos, start, end, quality);
308 	else if (n == 16)
309 		return dumb_start_resampler_16(src, src_channels, pos, start, end, quality);
310 	else
311 		return dumb_start_resampler(src, src_channels, pos, start, end, quality);
312 }
313 
314 
315 #if 0
316 int32 dumb_resample_n_1_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, DUMB_VOLUME_RAMP_INFO * volume, double delta)
317 {
318 	if (n == 8)
319 		return dumb_resample_8_1_1(resampler, dst, dst_size, volume, delta);
320 	else if (n == 16)
321 		return dumb_resample_16_1_1(resampler, dst, dst_size, volume, delta);
322 	else
323 		return dumb_resample_1_1(resampler, dst, dst_size, volume, delta);
324 }
325 #endif
326 
327 
dumb_resample_n_1_2(int n,DUMB_RESAMPLER * resampler,sample_t * dst,int32 dst_size,DUMB_VOLUME_RAMP_INFO * volume_left,DUMB_VOLUME_RAMP_INFO * volume_right,double delta)328 int32 dumb_resample_n_1_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, double delta)
329 {
330 	if (n == 8)
331 		return dumb_resample_8_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
332 	else if (n == 16)
333 		return dumb_resample_16_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
334 	else
335 		return dumb_resample_1_2(resampler, dst, dst_size, volume_left, volume_right, delta);
336 }
337 
338 
339 #if 0
340 int32 dumb_resample_n_2_1(int n, DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, double delta)
341 {
342 	if (n == 8)
343 		return dumb_resample_8_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
344 	else if (n == 16)
345 		return dumb_resample_16_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
346 	else
347 		return dumb_resample_2_1(resampler, dst, dst_size, volume_left, volume_right, delta);
348 }
349 #endif
350 
351 
dumb_resample_n_2_2(int n,DUMB_RESAMPLER * resampler,sample_t * dst,int32 dst_size,DUMB_VOLUME_RAMP_INFO * volume_left,DUMB_VOLUME_RAMP_INFO * volume_right,double delta)352 int32 dumb_resample_n_2_2(int n, DUMB_RESAMPLER *resampler, sample_t *dst, int32 dst_size, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, double delta)
353 {
354 	if (n == 8)
355 		return dumb_resample_8_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
356 	else if (n == 16)
357 		return dumb_resample_16_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
358 	else
359 		return dumb_resample_2_2(resampler, dst, dst_size, volume_left, volume_right, delta);
360 }
361 
362 
363 #if 0
364 void dumb_resample_get_current_sample_n_1_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume, sample_t *dst)
365 {
366 	if (n == 8)
367 		dumb_resample_get_current_sample_8_1_1(resampler, volume, dst);
368 	else if (n == 16)
369 		dumb_resample_get_current_sample_16_1_1(resampler, volume, dst);
370 	else
371 		dumb_resample_get_current_sample_1_1(resampler, volume, dst);
372 }
373 #endif
374 
375 
dumb_resample_get_current_sample_n_1_2(int n,DUMB_RESAMPLER * resampler,DUMB_VOLUME_RAMP_INFO * volume_left,DUMB_VOLUME_RAMP_INFO * volume_right,sample_t * dst)376 void dumb_resample_get_current_sample_n_1_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
377 {
378 	if (n == 8)
379 		dumb_resample_get_current_sample_8_1_2(resampler, volume_left, volume_right, dst);
380 	else if (n == 16)
381 		dumb_resample_get_current_sample_16_1_2(resampler, volume_left, volume_right, dst);
382 	else
383 		dumb_resample_get_current_sample_1_2(resampler, volume_left, volume_right, dst);
384 }
385 
386 
387 #if 0
388 void dumb_resample_get_current_sample_n_2_1(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
389 {
390 	if (n == 8)
391 		dumb_resample_get_current_sample_8_2_1(resampler, volume_left, volume_right, dst);
392 	else if (n == 16)
393 		dumb_resample_get_current_sample_16_2_1(resampler, volume_left, volume_right, dst);
394 	else
395 		dumb_resample_get_current_sample_2_1(resampler, volume_left, volume_right, dst);
396 }
397 #endif
398 
399 
dumb_resample_get_current_sample_n_2_2(int n,DUMB_RESAMPLER * resampler,DUMB_VOLUME_RAMP_INFO * volume_left,DUMB_VOLUME_RAMP_INFO * volume_right,sample_t * dst)400 void dumb_resample_get_current_sample_n_2_2(int n, DUMB_RESAMPLER *resampler, DUMB_VOLUME_RAMP_INFO * volume_left, DUMB_VOLUME_RAMP_INFO * volume_right, sample_t *dst)
401 {
402 	if (n == 8)
403 		dumb_resample_get_current_sample_8_2_2(resampler, volume_left, volume_right, dst);
404 	else if (n == 16)
405 		dumb_resample_get_current_sample_16_2_2(resampler, volume_left, volume_right, dst);
406 	else
407 		dumb_resample_get_current_sample_2_2(resampler, volume_left, volume_right, dst);
408 }
409 
410 
411 
dumb_end_resampler_n(int n,DUMB_RESAMPLER * resampler)412 void dumb_end_resampler_n(int n, DUMB_RESAMPLER *resampler)
413 {
414 	if (n == 8)
415 		dumb_end_resampler_8(resampler);
416 	else if (n == 16)
417 		dumb_end_resampler_16(resampler);
418 	else
419 		dumb_end_resampler(resampler);
420 }
421