1/*  _______         ____    __         ___    ___
2 * \    _  \       \    /  \  /       \   \  /   /       '   '  '
3 *  |  | \  \       |  |    ||         |   \/   |         .      .
4 *  |  |  |  |      |  |    ||         ||\  /|  |
5 *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
6 *  |  |  |  |      |  |    ||         ||    |  |         .      .
7 *  |  |_/  /        \  \__//          ||    |  |
8 * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
9 *                                                      /  \
10 *                                                     / .  \
11 * resample.inc - Resampling helper template.         / / \  \
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
46
47void dumb_reset_resampler(DUMB_RESAMPLER *resampler, SRCTYPE *src, int src_channels, long pos, long start, long end)
48{
49	int i;
50	resampler->src = src;
51	resampler->pos = pos;
52	resampler->subpos = 0;
53	resampler->start = start;
54	resampler->end = end;
55	resampler->dir = 1;
56	resampler->pickup = NULL;
57	resampler->pickup_data = NULL;
58	resampler->min_quality = 0;
59	resampler->max_quality = DUMB_RQ_N_LEVELS - 1;
60	for (i = 0; i < src_channels*3; i++) resampler->X[i] = 0;
61	resampler->overshot = -1;
62}
63
64
65
66DUMB_RESAMPLER *dumb_start_resampler(SRCTYPE *src, int src_channels, long pos, long start, long end)
67{
68	DUMB_RESAMPLER *resampler = malloc(sizeof(*resampler));
69	if (!resampler) return NULL;
70	dumb_reset_resampler(resampler, src, src_channels, pos, start, end);
71	return resampler;
72}
73
74
75
76/* Create mono source resampler. */
77#define SUFFIX2 _1
78#define SRC_CHANNELS 1
79#define DIVIDE_BY_SRC_CHANNELS(x) (x)
80#define COPYSRC(dstarray, dstindex, srcarray, srcindex) (dstarray)[dstindex] = (srcarray)[srcindex]
81#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) (dstarray)[dstindex] = condition ? (srcarray)[srcindex] : 0
82#define MONO_DEST_VOLUME_PARAMETERS float volume
83#define MONO_DEST_VOLUME_VARIABLES vol
84#define MONO_DEST_VOLUME_ZEROS 0
85#define SET_MONO_DEST_VOLUME_VARIABLES vol = (int)floor(volume * 65536.0 + 0.5)
86#define MONO_DEST_VOLUMES_ARE_ZERO (vol == 0)
87#define MONO_DEST_MIX_ALIAS(op, offset) *dst++ op ALIAS(x[offset], vol)
88#define STEREO_DEST_MIX_ALIAS(op, offset) { \
89	int xm = x[offset]; \
90	*dst++ op ALIAS(xm, lvol); \
91	*dst++ op ALIAS(xm, rvol); \
92}
93#define MONO_DEST_MIX_LINEAR(op, o0, o1) *dst++ op MULSC(LINEAR(x[o0], x[o1]), vol)
94#define STEREO_DEST_MIX_LINEAR(op, o0, o1) { \
95	int xm = LINEAR(x[o0], x[o1]); \
96	*dst++ op MULSC(xm, lvol); \
97	*dst++ op MULSC(xm, rvol); \
98}
99#define MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) *dst++ op CUBICVOL(CUBIC(x0[o0], x[o1], x[o2], x3[o3]), vol)
100#define STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) { \
101	int xm = CUBIC(x0[o0], x[o1], x[o2], x3[o3]); \
102	*dst++ op CUBICVOL(xm, lvol); \
103	*dst++ op CUBICVOL(xm, rvol); \
104}
105#include "resamp2.inc"
106
107/* Create stereo source resampler. */
108#define SUFFIX2 _2
109#define SRC_CHANNELS 2
110#define DIVIDE_BY_SRC_CHANNELS(x) ((x) >> 1)
111#define COPYSRC(dstarray, dstindex, srcarray, srcindex) { \
112	(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
113	(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
114}
115#define COPYSRC2(dstarray, dstindex, condition, srcarray, srcindex) { \
116	if (condition) { \
117		(dstarray)[(dstindex)*2] = (srcarray)[(srcindex)*2]; \
118		(dstarray)[(dstindex)*2+1] = (srcarray)[(srcindex)*2+1]; \
119	} else { \
120		(dstarray)[(dstindex)*2] = 0; \
121		(dstarray)[(dstindex)*2+1] = 0; \
122	} \
123}
124#define MONO_DEST_VOLUME_PARAMETERS float volume_left, float volume_right
125#define MONO_DEST_VOLUME_VARIABLES lvol, rvol
126#define MONO_DEST_VOLUME_ZEROS 0, 0
127#define SET_MONO_DEST_VOLUME_VARIABLES { \
128	lvol = (int)floor(volume_left * 65536.0 + 0.5); \
129	rvol = (int)floor(volume_right * 65536.0 + 0.5); \
130}
131#define MONO_DEST_VOLUMES_ARE_ZERO (lvol == 0 && rvol == 0)
132#define MONO_DEST_MIX_ALIAS(op, offset) *dst++ op ALIAS(x[(offset)*2], lvol) + ALIAS(x[(offset)*2+1], rvol)
133#define STEREO_DEST_MIX_ALIAS(op, offset) { \
134	*dst++ op ALIAS(x[(offset)*2], lvol); \
135	*dst++ op ALIAS(x[(offset)*2+1], rvol); \
136}
137#define MONO_DEST_MIX_LINEAR(op, o0, o1) *dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol) + MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol)
138#define STEREO_DEST_MIX_LINEAR(op, o0, o1) { \
139	*dst++ op MULSC(LINEAR(x[(o0)*2], x[(o1)*2]), lvol); \
140	*dst++ op MULSC(LINEAR(x[(o0)*2+1], x[(o1)*2+1]), rvol); \
141}
142#define MONO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) *dst++ op \
143	CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol) + \
144	CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol)
145#define STEREO_DEST_MIX_CUBIC(op, x0, x3, o0, o1, o2, o3) { \
146	*dst++ op CUBICVOL(CUBIC(x0[(o0)*2], x[(o1)*2], x[(o2)*2], x3[(o3)*2]), lvol); \
147	*dst++ op CUBICVOL(CUBIC(x0[(o0)*2+1], x[(o1)*2+1], x[(o2)*2+1], x3[(o3)*2+1]), rvol); \
148}
149#include "resamp2.inc"
150
151
152
153void dumb_end_resampler(DUMB_RESAMPLER *resampler)
154{
155	if (resampler)
156		free(resampler);
157}
158
159
160
161#undef CUBICVOL
162#undef CUBIC
163#undef LINEAR
164#undef ALIAS
165#undef SRCBITS
166#undef SRCTYPE
167#undef SUFFIX
168