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