dumb_resample.cpp

Go to the documentation of this file.
00001 /*  _______         ____    __         ___    ___
00002  * \    _  \       \    /  \  /       \   \  /   /       '   '  '
00003  *  |  | \  \       |  |    ||         |   \/   |         .      .
00004  *  |  |  |  |      |  |    ||         ||\  /|  |
00005  *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
00006  *  |  |  |  |      |  |    ||         ||    |  |         .      .
00007  *  |  |_/  /        \  \__//          ||    |  |
00008  * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
00009  *                                                      /  \
00010  *                                                     / .  \
00011  * resample.c - Resampling helper.                    / / \  \
00012  *                                                   | <  /   \_
00013  * By Bob and entheh.                                |  \/ /\   /
00014  *                                                    \_  /  > /
00015  * In order to find a good trade-off between            | \ / /
00016  * speed and accuracy in this code, some tests          |  ' /
00017  * were carried out regarding the behaviour of           \__/
00018  * long long ints with gcc. The following code
00019  * was tested:
00020  *
00021  * int a, b, c;
00022  * c = ((long long)a * b) >> 16;
00023  *
00024  * DJGPP GCC Version 3.0.3 generated the following assembly language code for
00025  * the multiplication and scaling, leaving the 32-bit result in EAX.
00026  *
00027  * movl  -8(%ebp), %eax    ; read one int into EAX
00028  * imull -4(%ebp)          ; multiply by the other; result goes in EDX:EAX
00029  * shrdl $16, %edx, %eax   ; shift EAX right 16, shifting bits in from EDX
00030  *
00031  * Note that a 32*32->64 multiplication is performed, allowing for high
00032  * accuracy. On the Pentium 2 and above, shrdl takes two cycles (generally),
00033  * so it is a minor concern when four multiplications are being performed
00034  * (the cubic resampler). On the Pentium MMX and earlier, it takes four or
00035  * more cycles, so this method is unsuitable for use in the low-quality
00036  * resamplers.
00037  *
00038  * Since "long long" is a gcc-specific extension, we use LONG_LONG instead,
00039  * defined in dumb.h. We may investigate later what code MSVC generates, but
00040  * if it seems too slow then we suggest you use a good compiler.
00041  *
00042  * FIXME: these comments are somewhat out of date now.
00043  */
00044 
00045 #include <math.h>
00046 #include "dumb_resample.h"
00047 
00048 namespace audiere {
00049 
00050 /* Compile with -DHEAVYDEBUG if you want to make sure the pick-up function is
00051  * called when it should be. There will be a considerable performance hit,
00052  * since at least one condition has to be tested for every sample generated.
00053  */
00054 #ifdef HEAVYDEBUG
00055 #define HEAVYASSERT(cond) ASSERT(cond)
00056 #else
00057 #define HEAVYASSERT(cond)
00058 #endif
00059 
00060 
00061 
00062 //#define MULSC(a, b) ((int)((LONG_LONG)(a) * (b) >> 16))
00063 //#define MULSC(a, b) ((a) * ((b) >> 2) >> 14)
00064 #define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
00065 
00066 
00067 
00068 /* A global variable for controlling resampling quality wherever a local
00069  * specification doesn't override it. The following values are valid:
00070  *
00071  *  0 - DUMB_RQ_ALIASING - fastest
00072  *  1 - DUMB_RQ_LINEAR
00073  *  2 - DUMB_RQ_CUBIC    - nicest
00074  *
00075  * Values outside the range 0-2 will behave the same as the nearest
00076  * value within the range.
00077  */
00078 int dumb_resampling_quality = 2;
00079 
00080 
00081 
00082 void dumb_reset_resampler(DUMB_RESAMPLER *resampler, sample_t *src, long pos, long start, long end)
00083 {
00084         resampler->src = src;
00085         resampler->pos = pos;
00086         resampler->subpos = 0;
00087         resampler->start = start;
00088         resampler->end = end;
00089         resampler->dir = 1;
00090         resampler->pickup = NULL;
00091         resampler->pickup_data = NULL;
00092         resampler->min_quality = 0;
00093         resampler->max_quality = DUMB_RQ_N_LEVELS - 1;
00094         resampler->x[2] = resampler->x[1] = resampler->x[0] = 0;
00095         resampler->overshot = -1;
00096 }
00097 
00098 
00099 
00100 DUMB_RESAMPLER *dumb_start_resampler(sample_t *src, long pos, long start, long end)
00101 {
00102         DUMB_RESAMPLER *resampler = (DUMB_RESAMPLER*)malloc(sizeof(*resampler));
00103         if (!resampler) return NULL;
00104         dumb_reset_resampler(resampler, src, pos, start, end);
00105         return resampler;
00106 }
00107 
00108 
00109 
00110 /* For convenience, returns nonzero on stop. */
00111 static int process_pickup(DUMB_RESAMPLER *resampler)
00112 {
00113         if (resampler->overshot < 0) {
00114                 resampler->overshot = 0;
00115                 dumb_resample(resampler, NULL, 2, 0, 1.0f);
00116                 resampler->x[0] = resampler->x[1];
00117         }
00118 
00119         for (;;) {
00120                 if (resampler->dir < 0) {
00121                         if (resampler->overshot >= 3 && resampler->pos+3 >= resampler->start) resampler->x[0] = resampler->src[resampler->pos+3];
00122                         if (resampler->overshot >= 2 && resampler->pos+2 >= resampler->start) resampler->x[1] = resampler->src[resampler->pos+2];
00123                         if (resampler->overshot >= 1 && resampler->pos+1 >= resampler->start) resampler->x[2] = resampler->src[resampler->pos+1];
00124                         resampler->overshot = resampler->start - resampler->pos - 1;
00125                 } else {
00126                         if (resampler->overshot >= 3 && resampler->pos-3 < resampler->end) resampler->x[0] = resampler->src[resampler->pos-3];
00127                         if (resampler->overshot >= 2 && resampler->pos-2 < resampler->end) resampler->x[1] = resampler->src[resampler->pos-2];
00128                         if (resampler->overshot >= 1 && resampler->pos-1 < resampler->end) resampler->x[2] = resampler->src[resampler->pos-1];
00129                         resampler->overshot = resampler->pos - resampler->end;
00130                 }
00131 
00132                 if (resampler->overshot < 0) {
00133                         resampler->overshot = 0;
00134                         return 0;
00135                 }
00136 
00137                 if (!resampler->pickup) {
00138                         resampler->dir = 0;
00139                         return 1;
00140                 }
00141                 (*resampler->pickup)(resampler, resampler->pickup_data);
00142                 if (resampler->dir == 0) return 1;
00143                 ASSERT(resampler->dir == -1 || resampler->dir == 1);
00144         }
00145 }
00146 
00147 
00148 
00149 /* Executes the content 'iterator' times.
00150  * Clobbers the 'iterator' variable.
00151  * The loop is unrolled by four.
00152  */
00153 #define LOOP4(iterator, CONTENT) \
00154 { \
00155         if ((iterator) & 2) { \
00156                 CONTENT; \
00157                 CONTENT; \
00158         } \
00159         if ((iterator) & 1) { \
00160                 CONTENT; \
00161         } \
00162         (iterator) >>= 2; \
00163         while (iterator) { \
00164                 CONTENT; \
00165                 CONTENT; \
00166                 CONTENT; \
00167                 CONTENT; \
00168                 (iterator)--; \
00169         } \
00170 }
00171 
00172 
00173 
00174 long dumb_resample(DUMB_RESAMPLER *resampler, sample_t *dst, long dst_size, float volume, float delta)
00175 {
00176         int dt;
00177         int vol;
00178         long done;
00179         long todo;
00180         int quality;
00181 
00182         if (!resampler || resampler->dir == 0) return 0;
00183         ASSERT(resampler->dir == -1 || resampler->dir == 1);
00184 
00185         done = 0;
00186         dt = (int)(delta * 65536.0 + 0.5);
00187         vol = (int)floor(volume * 65536.0 + 0.5);
00188 
00189         if (vol == 0) dst = NULL;
00190 
00191         quality = dumb_resampling_quality;
00192         if (quality > resampler->max_quality) quality = resampler->max_quality;
00193         else if (quality < resampler->min_quality) quality = resampler->min_quality;
00194 
00195         while (done < dst_size) {
00196                 if (process_pickup(resampler)) return done;
00197 
00198                 if ((resampler->dir ^ dt) < 0)
00199                         dt = -dt;
00200 
00201                 if (resampler->dir < 0)
00202                         todo = (long)((((LONG_LONG)(resampler->pos - resampler->start) << 16) + resampler->subpos - dt) / -dt);
00203                 else
00204                         todo = (long)((((LONG_LONG)(resampler->end - resampler->pos) << 16) - resampler->subpos - 1 + dt) / dt);
00205 
00206                 if (todo < 0)
00207                         todo = 0;
00208                 else if (todo > dst_size - done)
00209                         todo = dst_size - done;
00210 
00211                 done += todo;
00212 
00213                 {
00214                         sample_t *src = resampler->src;
00215                         long pos = resampler->pos;
00216                         int subpos = resampler->subpos;
00217                         long diff = pos;
00218                         long overshot;
00219                         if (resampler->dir < 0) {
00220                                 if (!dst) {
00221                                         /* Silence or simulation */
00222                                         LONG_LONG new_subpos = subpos + dt * todo;
00223                                         pos += (long)(new_subpos >> 16);
00224                                         subpos = (long)new_subpos & 65535;
00225                                 } else if (quality <= DUMB_RQ_ALIASING) {
00226                                         /* Aliasing, backwards */
00227                                         sample_t xbuf[2];
00228                                         sample_t *x = &xbuf[0];
00229                                         sample_t *xstart;
00230                                         xbuf[0] = resampler->x[1];
00231                                         xbuf[1] = resampler->x[2];
00232                                         while (todo && x < &xbuf[2]) {
00233                                                 HEAVYASSERT(pos >= resampler->start);
00234                                                 *dst++ += MULSC(x[0], vol);
00235                                                 subpos += dt;
00236                                                 pos += subpos >> 16;
00237                                                 x -= subpos >> 16;
00238                                                 subpos &= 65535;
00239                                                 todo--;
00240                                         }
00241                                         x = xstart = &src[pos];
00242                                         LOOP4(todo,
00243                                                 *dst++ += MULSC(x[2], vol);
00244                                                 subpos += dt;
00245                                                 x += subpos >> 16;
00246                                                 subpos &= 65535;
00247                                         );
00248                                         pos += x - xstart;
00249                                 } else if (quality <= DUMB_RQ_LINEAR) {
00250                                         /* Linear interpolation, backwards */
00251                                         sample_t xbuf[3];
00252                                         sample_t *x = &xbuf[1];
00253                                         xbuf[0] = resampler->x[1];
00254                                         xbuf[1] = resampler->x[2];
00255                                         xbuf[2] = src[pos];
00256                                         while (todo && x < &xbuf[3]) {
00257                                                 HEAVYASSERT(pos >= resampler->start);
00258                                                 *dst++ += MULSC(x[0] + MULSC(x[-1] - x[0], subpos), vol);
00259                                                 subpos += dt;
00260                                                 pos += subpos >> 16;
00261                                                 x -= subpos >> 16;
00262                                                 subpos &= 65535;
00263                                                 todo--;
00264                                         }
00265                                         x = &src[pos];
00266                                         LOOP4(todo,
00267                                                 HEAVYASSERT(pos >= resampler->start);
00268                                                 *dst++ += MULSC(x[1] + MULSC(x[2] - x[1], subpos), vol);
00269                                                 subpos += dt;
00270                                                 pos += subpos >> 16;
00271                                                 x += subpos >> 16;
00272                                                 subpos &= 65535;
00273                                         );
00274                                 } else {
00275                                         /* Cubic interpolation, backwards */
00276                                         sample_t xbuf[6];
00277                                         sample_t *x = &xbuf[3];
00278                                         sample_t *lastx = NULL;
00279                                         int a = 0, b = 0, c = 0;
00280                                         xbuf[0] = resampler->x[0];
00281                                         xbuf[1] = resampler->x[1];
00282                                         xbuf[2] = resampler->x[2];
00283                                         xbuf[3] = src[pos];
00284                                         if (pos-1 >= resampler->start) xbuf[4] = src[pos-1];
00285                                         if (pos-2 >= resampler->start) xbuf[5] = src[pos-2];
00286                                         while (todo && x < &xbuf[6]) {
00287                                                 HEAVYASSERT(pos >= resampler->start);
00288                                                 if (lastx != x) {
00289                                                         lastx = x;
00290                                                         a = (((x[-1] - x[-2]) << 1) + (x[-1] - x[-2]) + (x[-3] - x[0])) >> 1;
00291                                                         b = (x[-2] << 1) + x[0] - ((5 * x[-1] + x[-3]) >> 1);
00292                                                         c = (x[-2] - x[0]) >> 1;
00293                                                 }
00294                                                 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-1], vol);
00295                                                 subpos += dt;
00296                                                 pos += subpos >> 16;
00297                                                 x -= subpos >> 16;
00298                                                 subpos &= 65535;
00299                                                 todo--;
00300                                         }
00301                                         x = &src[pos];
00302                                         lastx = NULL;
00303                                         LOOP4(todo,
00304                                                 HEAVYASSERT(pos >= resampler->start);
00305                                                 if (lastx != x) {
00306                                                         lastx = x;
00307                                                         a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1;
00308                                                         b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1);
00309                                                         c = (x[2] - x[0]) >> 1;
00310                                                 }
00311                                                 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[1], vol);
00312                                                 subpos += dt;
00313                                                 pos += subpos >> 16;
00314                                                 x += subpos >> 16;
00315                                                 subpos &= 65535;
00316                                         );
00317                                 }
00318                                 diff = diff - pos;
00319                                 overshot = resampler->start - pos - 1;
00320                                 if (diff >= 3) {
00321                                         resampler->x[0] = overshot >= 3 ? 0 : src[pos+3];
00322                                         resampler->x[1] = overshot >= 2 ? 0 : src[pos+2];
00323                                         resampler->x[2] = overshot >= 1 ? 0 : src[pos+1];
00324                                 } else if (diff >= 2) {
00325                                         resampler->x[0] = resampler->x[2];
00326                                         resampler->x[1] = overshot >= 2 ? 0 : src[pos+2];
00327                                         resampler->x[2] = overshot >= 1 ? 0 : src[pos+1];
00328                                 } else if (diff >= 1) {
00329                                         resampler->x[0] = resampler->x[1];
00330                                         resampler->x[1] = resampler->x[2];
00331                                         resampler->x[2] = overshot >= 1 ? 0 : src[pos+1];
00332                                 }
00333                         } else {
00334                                 if (!dst) {
00335                                         /* Silence or simulation */
00336                                         LONG_LONG new_subpos = subpos + dt * todo;
00337                                         pos += (long)(new_subpos >> 16);
00338                                         subpos = (long)new_subpos & 65535;
00339                                 } else if (dumb_resampling_quality <= DUMB_RQ_ALIASING) {
00340                                         /* Aliasing, forwards */
00341                                         sample_t xbuf[2];
00342                                         sample_t *x = &xbuf[0];
00343                                         sample_t *xstart;
00344                                         xbuf[0] = resampler->x[1];
00345                                         xbuf[1] = resampler->x[2];
00346                                         while (todo && x < &xbuf[2]) {
00347                                                 HEAVYASSERT(pos < resampler->end);
00348                                                 *dst++ += MULSC(x[0], vol);
00349                                                 subpos += dt;
00350                                                 pos += subpos >> 16;
00351                                                 x += subpos >> 16;
00352                                                 subpos &= 65535;
00353                                                 todo--;
00354                                         }
00355                                         x = xstart = &src[pos];
00356                                         LOOP4(todo,
00357                                                 *dst++ += MULSC(x[-2], vol);
00358                                                 subpos += dt;
00359                                                 x += subpos >> 16;
00360                                                 subpos &= 65535;
00361                                         );
00362                                         pos += x - xstart;
00363                                 } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
00364                                         /* Linear interpolation, forwards */
00365                                         sample_t xbuf[3];
00366                                         sample_t *x = &xbuf[1];
00367                                         xbuf[0] = resampler->x[1];
00368                                         xbuf[1] = resampler->x[2];
00369                                         xbuf[2] = src[pos];
00370                                         while (todo && x < &xbuf[3]) {
00371                                                 HEAVYASSERT(pos < resampler->end);
00372                                                 *dst++ += MULSC(x[-1] + MULSC(x[0] - x[-1], subpos), vol);
00373                                                 subpos += dt;
00374                                                 pos += subpos >> 16;
00375                                                 x += subpos >> 16;
00376                                                 subpos &= 65535;
00377                                                 todo--;
00378                                         }
00379                                         x = &src[pos];
00380                                         LOOP4(todo,
00381                                                 HEAVYASSERT(pos < resampler->end);
00382                                                 *dst++ += MULSC(x[-2] + MULSC(x[-1] - x[-2], subpos), vol);
00383                                                 subpos += dt;
00384                                                 pos += subpos >> 16;
00385                                                 x += subpos >> 16;
00386                                                 subpos &= 65535;
00387                                         );
00388                                 } else {
00389                                         /* Cubic interpolation, forwards */
00390                                         sample_t xbuf[6];
00391                                         sample_t *x = &xbuf[3];
00392                                         sample_t *lastx = NULL;
00393                                         int a = 0, b = 0, c = 0;
00394                                         xbuf[0] = resampler->x[0];
00395                                         xbuf[1] = resampler->x[1];
00396                                         xbuf[2] = resampler->x[2];
00397                                         xbuf[3] = src[pos];
00398                                         if (pos+1 < resampler->end) xbuf[4] = src[pos+1];
00399                                         if (pos+2 < resampler->end) xbuf[5] = src[pos+2];
00400                                         while (todo && x < &xbuf[6]) {
00401                                                 HEAVYASSERT(pos < resampler->end);
00402                                                 if (lastx != x) {
00403                                                         lastx = x;
00404                                                         a = (((x[-2] - x[-1]) << 1) + (x[-2] - x[-1]) + (x[0] - x[-3])) >> 1;
00405                                                         b = (x[-1] << 1) + x[-3] - ((5 * x[-2] + x[0]) >> 1);
00406                                                         c = (x[-1] - x[-3]) >> 1;
00407                                                 }
00408                                                 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-2], vol);
00409                                                 subpos += dt;
00410                                                 pos += subpos >> 16;
00411                                                 x += subpos >> 16;
00412                                                 subpos &= 65535;
00413                                                 todo--;
00414                                         }
00415                                         x = &src[pos];
00416                                         lastx = NULL;
00417                                         LOOP4(todo,
00418                                                 HEAVYASSERT(pos < resampler->end);
00419                                                 if (lastx != x) {
00420                                                         lastx = x;
00421                                                         a = (((x[-2] - x[-1]) << 1) + (x[-2] - x[-1]) + (x[0] - x[-3])) >> 1;
00422                                                         b = (x[-1] << 1) + x[-3] - ((5 * x[-2] + x[0]) >> 1);
00423                                                         c = (x[-1] - x[-3]) >> 1;
00424                                                 }
00425                                                 *dst++ += MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[-2], vol);
00426                                                 subpos += dt;
00427                                                 pos += subpos >> 16;
00428                                                 x += subpos >> 16;
00429                                                 subpos &= 65535;
00430                                         );
00431                                 }
00432                                 diff = pos - diff;
00433                                 overshot = pos - resampler->end;
00434                                 if (diff >= 3) {
00435                                         resampler->x[0] = overshot >= 3 ? 0 : src[pos-3];
00436                                         resampler->x[1] = overshot >= 2 ? 0 : src[pos-2];
00437                                         resampler->x[2] = overshot >= 1 ? 0 : src[pos-1];
00438                                 } else if (diff >= 2) {
00439                                         resampler->x[0] = resampler->x[2];
00440                                         resampler->x[1] = overshot >= 2 ? 0 : src[pos-2];
00441                                         resampler->x[2] = overshot >= 1 ? 0 : src[pos-1];
00442                                 } else if (diff >= 1) {
00443                                         resampler->x[0] = resampler->x[1];
00444                                         resampler->x[1] = resampler->x[2];
00445                                         resampler->x[2] = overshot >= 1 ? 0 : src[pos-1];
00446                                 }
00447                         }
00448                         resampler->pos = pos;
00449                         resampler->subpos = subpos;
00450                 }
00451         }
00452 
00453         return done;
00454 }
00455 
00456 
00457 
00458 sample_t dumb_resample_get_current_sample(DUMB_RESAMPLER *resampler, float volume)
00459 {
00460         int vol;
00461         sample_t *src;
00462         long pos;
00463         int subpos;
00464         int quality;
00465 
00466         if (!resampler || resampler->dir == 0) return 0;
00467         ASSERT(resampler->dir == -1 || resampler->dir == 1);
00468 
00469         if (process_pickup(resampler)) return 0;
00470 
00471         vol = (int)floor(volume * 65536.0 + 0.5);
00472         if (vol == 0) return 0;
00473 
00474         quality = dumb_resampling_quality;
00475         if (quality > resampler->max_quality) quality = resampler->max_quality;
00476         else if (quality < resampler->min_quality) quality = resampler->min_quality;
00477 
00478         src = resampler->src;
00479         pos = resampler->pos;
00480         subpos = resampler->subpos;
00481 
00482         if (resampler->dir < 0) {
00483                 HEAVYASSERT(pos >= resampler->start);
00484                 if (dumb_resampling_quality <= 0) {
00485                         /* Aliasing, backwards */
00486                         return MULSC(src[pos], vol);
00487                 } else if (quality <= DUMB_RQ_LINEAR) {
00488                         /* Linear interpolation, backwards */
00489                         return MULSC(resampler->x[2] + MULSC(resampler->x[1] - resampler->x[2], subpos), vol);
00490                 } else {
00491                         /* Cubic interpolation, backwards */
00492                         sample_t *x = resampler->x;
00493                         int a, b, c;
00494                         a = (((x[2] - x[1]) << 1) + (x[2] - x[1]) + (x[0] - src[pos])) >> 1;
00495                         b = (x[1] << 1) + src[pos] - ((5 * x[2] + x[0]) >> 1);
00496                         c = (x[1] - src[pos]) >> 1;
00497                         return MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[2], vol);
00498                 }
00499         } else {
00500                 HEAVYASSERT(pos < resampler->end);
00501                 if (dumb_resampling_quality <= 0) {
00502                         /* Aliasing */
00503                         return MULSC(src[pos], vol);
00504                 } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
00505                         /* Linear interpolation, forwards */
00506                         return MULSC(resampler->x[1] + MULSC(resampler->x[2] - resampler->x[1], subpos), vol);
00507                 } else {
00508                         /* Cubic interpolation, forwards */
00509                         sample_t *x = resampler->x;
00510                         int a, b, c;
00511                         a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (src[pos] - x[0])) >> 1;
00512                         b = (x[2] << 1) + x[0] - ((5 * x[1] + src[pos]) >> 1);
00513                         c = (x[2] - x[0]) >> 1;
00514                         return MULSC(MULSC(MULSC(MULSC(a, subpos) + b, subpos) + c, subpos) + x[1], vol);
00515                 }
00516         }
00517 }
00518 
00519 
00520 
00521 void dumb_end_resampler(DUMB_RESAMPLER *resampler)
00522 {
00523         if (resampler)
00524                 free(resampler);
00525 }
00526 
00527 
00528 
00529 #if 0
00530 /* The following macro is used to overcome the fact that most C
00531  * compilers (including gcc and MSVC) can't correctly multiply signed
00532  * integers outside the range -32768 to 32767. i86 assembler versions
00533  * don't need to use this method, since the processor does in fact
00534  * have instructions to multiply large numbers correctly - which
00535  * means using assembly language could make a significant difference
00536  * to the speed.
00537  *
00538  * The basic method is as follows. We halve the subposition (how far
00539  * we are between samples), so it never exceeds 32767. We also halve
00540  * the delta, which is the amount to be added to the subposition each
00541  * time. Then we unroll the loop twofold, so that we can add the lost
00542  * one every other time if necessary (since the halving may have
00543  * resulted in rounding down).
00544  *
00545  * This method doesn't incur any cumulative inaccuracies. There is a
00546  * very slight loss of quality, which I challenge anyone to notice -
00547  * but the position will advance at *exactly* the same rate as it
00548  * would if we didn't use this method. This also means the pitch is
00549  * exactly the same, which may even make a difference to trained
00550  * musicians when resampling down a lot :)
00551  *
00552  * Each time this macro is invoked, DO_RESAMPLE(inc) must be defined
00553  * to calculate the samples by the appropriate equation (linear,
00554  * cubic, etc.). See the individual cases for examples of how this is
00555  * done.
00556  */
00557 #define MAKE_RESAMPLER()                                                        \
00558 {                                                                                                       \
00559         if (dt & 1) {                                                                   \
00560                 long todo2;                                                                     \
00561                                                                                                         \
00562                 dt >>= 1;                                                                       \
00563                                                                                                         \
00564                 if (src_subpos & 1) {                                           \
00565                         src_subpos >>= 1;                                               \
00566                         DO_RESAMPLE(1);                                                 \
00567                         todo--;                                                                 \
00568                 } else                                                                          \
00569                         src_subpos >>= 1;                                               \
00570                                                                                                         \
00571                 todo2 = todo >> 1;                                                      \
00572                                                                                                         \
00573                 while (todo2) {                                                         \
00574                         DO_RESAMPLE(0);                                                 \
00575                         DO_RESAMPLE(1);                                                 \
00576                         todo2--;                                                                \
00577                 }                                                                                       \
00578                                                                                                         \
00579                 if (todo & 1) {                                                         \
00580                         DO_RESAMPLE(0);                                                 \
00581                         src_subpos = (src_subpos << 1) | 1;             \
00582                 } else                                                                          \
00583                         src_subpos <<= 1;                                               \
00584                                                                                                         \
00585                 todo = 0;                                                                       \
00586                 dt = (dt << 1) | 1;                                                     \
00587         } else {                                                                                \
00588                 long subposbit = src_subpos & 1;                        \
00589                 dt >>= 1;                                                                       \
00590                 src_subpos >>= 1;                                                       \
00591                                                                                                         \
00592                 if (todo & 1) {                                                         \
00593                         DO_RESAMPLE(0);                                                 \
00594                 }                                                                                       \
00595                                                                                                         \
00596                 todo >>= 1;                                                                     \
00597                                                                                                         \
00598                 while (todo) {                                                          \
00599                         DO_RESAMPLE(0);                                                 \
00600                         DO_RESAMPLE(0);                                                 \
00601                         todo--;                                                                 \
00602                 }                                                                                       \
00603                                                                                                         \
00604                 src_subpos = (src_subpos << 1) | subposbit; \
00605                 dt <<= 1;                                                                       \
00606         }                                                                                               \
00607 }
00608 
00609 
00610 
00611 sample_t dumb_resample_get_current_sample(
00612         sample_t *src, long *_src_pos, int *_src_subpos,
00613         long src_start, long src_end,
00614         float volume, int *_dir,
00615         DUMB_RESAMPLE_PICKUP pickup, void *pickup_data
00616 )
00617 {
00618         long src_pos = *_src_pos;
00619         int src_subpos = *_src_subpos;
00620         int dir = _dir ? *_dir : 1;
00621 
00622         sample_t value = 0;
00623 
00624         if (dir == 0)
00625                 return 0;
00626 
00627         ASSERT(dir == 1 || dir == -1);
00628 
00629         if (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)) {
00630 
00631                 /* If there's no pick-up function, we stop. */
00632                 if (!pickup) {
00633                         dir = 0;
00634                         goto end;
00635                 }
00636 
00637                 /* Process the pick-up. It may need invoking more than once. */
00638                 do {
00639                         dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data);
00640 
00641                         if (dir == 0)
00642                                 goto end;
00643 
00644                         ASSERT(dir == 1 || dir == -1);
00645                 } while (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end));
00646         }
00647 
00648         HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end));
00649 
00650         if (dumb_resampling_quality == 0) {
00651                 /* Aliasing (coarse) */
00652                 int volume_fact = (int)(volume * 16384.0);
00653                 value = (src[src_pos] * volume_fact) >> 14;
00654         } else if (dumb_resampling_quality <= 2) {
00655                 /* Linear interpolation */
00656                 int volume_fact = (int)(volume * 16384.0);
00657                 int subpos = src_subpos >> 1;
00658                 value = ((src[src_pos] + ((((src[src_pos + 1] - src[src_pos]) >> 1) * subpos) >> 14)) * volume_fact) >> 14;
00659         } else if (dumb_resampling_quality == 3) {
00660                 /* Quadratic interpolation */
00661                 int volume_fact = (int)(volume * 16384.0);
00662                 int a, b;
00663                 sample_t *x;
00664                 int subpos = src_subpos >> 1;
00665                 x = &src[src_pos];
00666                 a = ((x[0] + x[2]) >> 1) - x[1];
00667                 b = ((x[2] - x[0]) >> 1) - (a << 1);
00668                 value = (((((((a * subpos) >> 15) + b) * subpos) >> 15) + x[0]) * volume_fact) >> 14;
00669         } else {
00670                 /* Cubic interpolation */
00671                 int volume_fact = (int)(volume * 16384.0);
00672                 int a, b, c;
00673                 sample_t *x;
00674                 int subpos = src_subpos >> 1;
00675                 x = &src[src_pos];
00676                 a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1;
00677                 b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1);
00678                 c = (x[2] - x[0]) >> 1;
00679                 value = (((int)(((LONG_LONG)((int)(((LONG_LONG)((int)(((LONG_LONG)a * subpos) >> 15) + b) * subpos) >> 15) + c) * subpos) >> 15) + x[1]) * volume_fact) >> 14;
00680         }
00681 
00682         end:
00683 
00684         *_src_pos = src_pos;
00685         *_src_subpos = src_subpos;
00686         if (_dir) *_dir = dir;
00687 
00688         return value;
00689 }
00690 
00691 
00692 
00693 long dumb_resample(
00694         sample_t *src, long *_src_pos, int *_src_subpos,
00695         long src_start, long src_end,
00696         sample_t *dst, long dst_size,
00697         float volume, float delta, int *_dir,
00698         DUMB_RESAMPLE_PICKUP pickup, void *pickup_data
00699 )
00700 {
00701         int dt = (int)(delta * 65536.0 + 0.5);
00702         long s = 0; /* Current position in the destination buffer */
00703 
00704         long src_pos = *_src_pos;
00705         int src_subpos = *_src_subpos;
00706         int dir = _dir ? *_dir : 1;
00707 
00708         int linear_average;
00709 
00710         if (dir == 0)
00711                 return 0;
00712 
00713         ASSERT(dir == 1 || dir == -1);
00714 
00715         linear_average = dst && dumb_resampling_quality >= 2 && dt > 65536;
00716 
00717         if (dir < 0) dt = -dt;
00718 
00719         if (linear_average)
00720                 volume /= delta;
00721 
00722         while (s < dst_size) {
00723 
00724                 long todo;
00725 
00726                 /* Process pick-ups first, just in case. */
00727 
00728                 if (linear_average) {
00729 
00730                         /* For linear average, the pick-up point could split a sum into
00731                          * two parts. We handle this by putting the pick-up code inside
00732                          * the summing loop. Note that this code is only executed when we
00733                          * know that a pick-up is necessary somewhere during this sum
00734                          * (although it is always executed once for the first sample).
00735                          * We use a separate loop further down when we know we won't have
00736                          * to do a pick-up, so the condition does not need testing inside
00737                          * the loop.
00738                          */
00739 
00740                         float sum;
00741                         long i;
00742                         int advance;
00743                         int x[3];
00744 
00745                         advance = src_subpos + dt;
00746 
00747                         /* Make these negative. Then they stay within the necessary
00748                          * range for integer multiplication, -32768 to 32767 ;)
00749                          */
00750                         x[0] = ~(src_subpos >> 1); /* = -1 - (src_subpos >> 1) */
00751                         x[2] = x[0] ^ 0x7FFF; /* = -32768 + (src_subpos >> 1) */
00752 
00753                         sum = (float)(-((src[src_pos] * (x+1)[dir]) >> 15));
00754 
00755                         i = src_pos + (advance >> 16);
00756                         src_pos += dir;
00757                         src_subpos = (dir >> 1) & 65535; /* changes 1,-1 to 0,65535 */
00758 
00759                         advance &= 65535;
00760 
00761                         /* i is the index of the first sample NOT to sum fully,
00762                          * regardless of the direction of resampling.
00763                          */
00764 
00765                         while (dir < 0 ? (i < src_start) : (i >= src_end)) {
00766                                 if (dir < 0) {
00767                                         while (src_pos >= src_start)
00768                                                 sum += src[src_pos--];
00769                                 } else {
00770                                         while (src_pos < src_end)
00771                                                 sum += src[src_pos++];
00772                                 }
00773 
00774                                 i -= src_pos;
00775                                 /* i is now the number of samples left to sum fully, except
00776                                  * it's negative if we're going backwards.
00777                                  */
00778 
00779                                 if (!pickup) {
00780                                         dir = 0;
00781                                         goto endsum;
00782                                 }
00783 
00784                                 dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data);
00785 
00786                                 if (dir == 0)
00787                                         goto endsum;
00788 
00789                                 ASSERT(dir == 1 || dir == -1);
00790 
00791                                 if ((dir ^ dt) < 0) {
00792                                         dt = -dt;
00793                                         advance ^= 65535;
00794                                         i = -i;
00795                                 }
00796 
00797                                 i += src_pos;
00798                                 /* There, i is back to normal. */
00799                         }
00800 
00801                         for (; src_pos != i; src_pos += dir)
00802                                 sum += src[src_pos];
00803 
00804                         src_subpos = advance;
00805 
00806                         x[2] = src_subpos >> 1;
00807                         x[0] = x[2] ^ 0x7FFF; /* = 32767 - (src_subpos >> 1) */
00808 
00809                         sum += (src[src_pos] * (x+1)[dir]) >> 15;
00810 
00811                         endsum:
00812 
00813                         sum *= volume;
00814                         dst[s] += (int)sum;
00815 
00816                         s++;
00817 
00818                         if (dir == 0)
00819                                 break;
00820 
00821                 } else if (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end)) {
00822 
00823                         /* If there's no pick-up function, we stop. */
00824                         if (!pickup) {
00825                                 dir = 0;
00826                                 break;
00827                         }
00828 
00829                         /* Process the pick-up. It may need invoking more than once. */
00830                         do {
00831                                 dir = (*pickup)(src, &src_pos, &src_subpos, &src_start, &src_end, dir, pickup_data);
00832 
00833                                 if (dir == 0)
00834                                         goto end;
00835 
00836                                 ASSERT(dir == 1 || dir == -1);
00837                         } while (dir < 0 ? (src_pos < src_start) : (src_pos >= src_end));
00838 
00839                         /* Update sign of dt to match that of dir. */
00840                         if ((dir ^ dt) < 0)
00841                                 dt = -dt;
00842                 }
00843 
00844                 /* Work out how many contiguous samples we can now render. */
00845                 if (dir < 0)
00846                         todo = (long)((((LONG_LONG)(src_pos - src_start) << 16) + src_subpos) / -dt);
00847                 else
00848                         todo = (long)((((LONG_LONG)(src_end - src_pos) << 16) - src_subpos - 1) / dt);
00849 
00850                 /* The above equations work out how many complete dt-sized
00851                  * intervals there are between the current position and the loop
00852                  * point (provided there is a little fractional extra). The linear
00853                  * average function needs complete intervals - but the other
00854                  * resamplers only read a sample from the beginning of each interval,
00855                  * so they can process one extra sample in their main loops (so we
00856                  * increment todo in a moment).
00857                  *
00858                  * The linear average function makes up the extra sample using the
00859                  * specialised pick-up code above.
00860                  *
00861                  * Note that our above pick-up process should have absolutely ensured
00862                  * that the result of this function will be nonnegative.
00863                  */
00864 
00865                 ASSERT(todo >= 0);
00866 
00867                 if (!linear_average)
00868                         todo++;
00869 
00870                 /* Of course we don't want to overrun the output buffer! */
00871                 if (todo > dst_size - s)
00872                         todo = dst_size - s;
00873 
00874                 if (!dst) {
00875 
00876                         LONG_LONG t = src_subpos + (LONG_LONG)dt * todo;
00877                         src_pos += (long)(t >> 16);
00878                         src_subpos = (int)t & 0xFFFFl;
00879 
00880                         s += todo;
00881 
00882                 } else if (linear_average) {
00883 
00884                         float sum;
00885                         long i;
00886                         int advance;
00887                         int x[3];
00888 
00889                         while (todo) {
00890 
00891                                 advance = src_subpos + dt;
00892 
00893                                 /* Make these negative. Then they stay within the necessary
00894                                  * range for integer multiplication, -32768 to 32767 ;)
00895                                  */
00896                                 x[0] = ~(src_subpos >> 1); /* = -1 - (src_subpos >> 1) */
00897                                 x[2] = x[0] ^ 0x7FFF; /* = -32768 + (src_subpos >> 1) */
00898 
00899                                 sum = (float)(-((src[src_pos] * (x+1)[dir]) >> 15));
00900 
00901                                 i = src_pos + (advance >> 16);
00902                                 src_pos += dir;
00903                                 src_subpos = (dir >> 1) & 65535; /* changes 1,-1 to 0,65535 */
00904 
00905                                 advance &= 65535;
00906 
00907                                 /* i is the index of the first sample NOT to sum fully,
00908                                  * regardless of the direction of resampling.
00909                                  */
00910 
00911                                 HEAVYASSERT(dir < 0 ? (i >= src_start) : (i < src_end));
00912 
00913                                 for (; src_pos != i; src_pos += dir)
00914                                         sum += src[src_pos];
00915 
00916                                 src_subpos = advance;
00917 
00918                                 x[2] = src_subpos >> 1;
00919                                 x[0] = x[2] ^ 0x7FFF; /* = 32767 - (src_subpos >> 1) */
00920 
00921                                 sum += (src[src_pos] * (x+1)[dir]) >> 15;
00922 
00923                                 sum *= volume;
00924                                 dst[s] += (int)sum;
00925 
00926                                 s++;
00927                                 todo--;
00928                         }
00929 
00930                 } else if (dumb_resampling_quality == 0 || (dumb_resampling_quality == 1 && delta >= 1.0)) {
00931 
00932                         /* Aliasing (coarse) */
00933                         int volume_fact = (int)(volume * 16384.0);
00934 
00935                         do {
00936                                 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end));
00937                                 dst[s] += ((src[src_pos] * volume_fact) >> 14);
00938                                 src_subpos += dt;
00939                                 src_pos += src_subpos >> 16;
00940                                 src_subpos &= 0xFFFFl;
00941                                 s++;
00942                         } while (--todo);
00943 
00944                 } else if (dumb_resampling_quality <= 2) {
00945 
00946                         /* Linear interpolation */
00947                         int volume_fact = (int)(volume * 16384.0);
00948 
00949                         #define DO_RESAMPLE(inc)                 \
00950                         {                                                                \
00951                                 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
00952                                                                                          \
00953                                 dst[s] += (((src[src_pos] + ((((src[src_pos + 1] - src[src_pos]) >> 1) * src_subpos) >> 14)) * volume_fact) >> 14); \
00954                                                                                          \
00955                                 src_subpos += dt + inc;          \
00956                                 src_pos += src_subpos >> 15; \
00957                                 src_subpos &= 0x7FFFl;           \
00958                                 s++;                                             \
00959                         }
00960 
00961                         MAKE_RESAMPLER();
00962 
00963                         #undef DO_RESAMPLE
00964 
00965                 } else if (dumb_resampling_quality == 3) {
00966 
00967                         /* Quadratic interpolation */
00968 
00969                         int volume_fact = (int)(volume * 16384.0);
00970                         int a = 0, b = 0;
00971                         sample_t *x = NULL;
00972                         int last_src_pos = -1;
00973 
00974                         /* AIM: no integer multiplicands must transcend the range -32768 to 32767.
00975                          * This limitation is imposed by most compilers, including gcc and MSVC.
00976                          *
00977                          * a = 0.5 * (s0 + s2) - s1
00978                          * b = -1.5 * s0 + 2 * s1 - 0.5 * s2
00979                          * c = s0
00980                          *
00981                          * s = (a * t + b) * t + c
00982                          *
00983                          * In fixed-point:
00984                          *
00985                          * a = ((s0 + s2) >> 1) - s1
00986                          * b = ((-3 * s0 - s2) >> 1) + (s1 << 1)
00987                          *
00988                          * s = (((((a * t) >> 16) + b) * t) >> 16) + s0
00989                          *
00990                          * With t halved (since t can reach 65535):
00991                          *
00992                          * s = (((((a * t) >> 15) + b) * t) >> 15) + s0
00993                          *
00994                          * a currently reaches 65536
00995                          * b currently reaches 131072
00996                          *
00997                          * So we must use aon2
00998                          *
00999                          * s = (((((aon2 * t) >> 14) + b) * t) >> 15) + s0
01000                          *
01001                          * ((aon2 * t) >> 14) + b is 5 times too big
01002                          * so we must divide by 8
01003                          *
01004                          * s = (((((aon2 * t) >> 17) + bon8) * t) >> 12) + s0
01005                          *
01006                          * aon2 = ((s0 + s2) >> 2) - (s1 >> 1)
01007                          * bon8 = ((-3 * s0 - s2) >> 4) + (s1 >> 2)
01008                          * or:
01009                          * bon8 = ((s2 - s0) >> 4) - (aon2 >> 1)
01010                          */
01011 
01012                         /* Unh4x0r3d version:
01013                         #define DO_RESAMPLE(inc)                                                \
01014                         {                                                                                               \
01015                                 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
01016                                                                                                                         \
01017                                 if (src_pos != last_src_pos) {                          \
01018                                         last_src_pos = src_pos;                                 \
01019                                         x = &src[src_pos];                                              \
01020                                         a = ((x[0] + x[2]) >> 2) - (x[1] >> 1); \
01021                                         b = ((x[2] - x[0]) >> 4) - (a >> 1);    \
01022                                 }                                                                                       \
01023                                                                                                                         \
01024                                 dst[s] += ((((((((a * src_subpos) >> 17) + b) * src_subpos) >> 12) + x[0]) * volume_fact) >> 14); \
01025                                                                                                                         \
01026                                 src_subpos += dt + inc;                                         \
01027                                 src_pos += src_subpos >> 15;                            \
01028                                 src_subpos &= 0x7FFFl;                                          \
01029                                 s++;                                                                            \
01030                         }
01031                         */
01032 
01033                         /* H4x0r3d version: */
01034                         #define DO_RESAMPLE(inc)                                                \
01035                         {                                                                                               \
01036                                 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
01037                                                                                                                         \
01038                                 if (src_pos != last_src_pos) {                          \
01039                                         last_src_pos = src_pos;                                 \
01040                                         x = &src[src_pos];                                              \
01041                                         a = ((x[0] + x[2]) >> 1) - x[1];                \
01042                                         b = ((x[2] - x[0]) >> 1) - (a << 1);    \
01043                                 }                                                                                       \
01044                                                                                                                         \
01045                                 dst[s] += ((((((((a * src_subpos) >> 15) + b) * src_subpos) >> 15) + x[0]) * volume_fact) >> 14); \
01046                                                                                                                         \
01047                                 src_subpos += dt + inc;                                         \
01048                                 src_pos += src_subpos >> 15;                            \
01049                                 src_subpos &= 0x7FFFl;                                          \
01050                                 s++;                                                                            \
01051                         }
01052 
01053                         MAKE_RESAMPLER();
01054 
01055                         #undef DO_RESAMPLE
01056 
01057                 } else {
01058 
01059                         /* Cubic interpolation */
01060 
01061                         int volume_fact = (int)(volume * 16384.0);
01062                         int a = 0, b = 0, c = 0;
01063                         sample_t *x = NULL;
01064                         int last_src_pos = -1;
01065 
01066                         /* AIM: never multiply integers outside the range -32768 to 32767.
01067                          *
01068                          * a = 1.5f * (x[1] - x[2]) + (x[3] - x[0]) * 0.5f;
01069                          * b = 2.0f * x[2] + x[0] - 2.5f * x[1] - x[3] * 0.5f;
01070                          * c = (x[2] - x[0]) * 0.5f;
01071                          *
01072                          * s = ((a * t + b) * t + c) * t + x[1];
01073                          *
01074                          * Fixed-point version:
01075                          *
01076                          * a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1;
01077                          * b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1);
01078                          * c = (x[2] - x[0]) >> 1;
01079                          *
01080                          * s = ((((((((a * t) >> 15) + b) * t) >> 15) + c) * t) >> 15) + x[1];
01081                          *   (with t already halved, maximum 32767)
01082                          *
01083                          * a is in (((1+1)*2)+(1+1)+(1+1))/2 = 8 times the required range
01084                          * b is in (1*2)+1+((5*1+1)/2) = 6 times
01085                          * c is in the required range
01086                          *
01087                          * We must use aon8
01088                          *
01089                          * s = ((((((((aon8 * t) >> 12) + b) * t) >> 15) + c) * t) >> 15) + x[1];
01090                          *
01091                          * But ((aon8 * t) >> 12) is in 2^(15+15-12) = 2^18 = 8 times
01092                          * b is in 6 times
01093                          * so we divide both ((aon8 * t) >> 12) and b by 16
01094                          *
01095                          * s = ((((((((aon8 * t) >> 16) + bon16) * t) >> 11) + c) * t) >> 15) + x[1];
01096                          *
01097                          * ((... + bon16) * t) >> 11 is 16 times too big
01098                          * c is in the correct range
01099                          * we must divide both by 32
01100                          *
01101                          * s = ((((((((aon8 * t) >> 16) + bon16) * t) >> 16) + con32) * t) >> 10) + x[1];
01102                          *
01103                          * aon8  = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 4;
01104                          * bon16 = ((x[2] << 2) + (x[0] << 1) - (5 * x[1] + x[3])) >> 5;
01105                          * con32 = (x[2] - x[0]) >> 6;
01106                          *
01107                          * A lot of accuracy is lost here. It is quite likely that some
01108                          * of the above would cancel anyway, so the scaling down wouldn't
01109                          * have to be so severe. However, I'm not in the mood to work it
01110                          * out now :P
01111                          *
01112                          * It may also be worth investigating whether doing this stuff
01113                          * in floats would be faster.
01114                          */
01115 
01116                         /* Unh4x0r3d version:
01117                         #define DO_RESAMPLE(inc)                   \
01118                         {                                                                  \
01119                                 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
01120                                                                                            \
01121                                 if (src_pos != last_src_pos) { \
01122                                         last_src_pos = src_pos;    \
01123                                         x = &src[src_pos];                 \
01124                                         a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 4; \
01125                                         b = ((x[2] << 2) + (x[0] << 1) - (5 * x[1] + x[3])) >> 5; \
01126                                         c = (x[2] - x[0]) >> 6;    \
01127                                 }                                                          \
01128                                                                                            \
01129                                 dst[s] += ((((((((((a * src_subpos) >> 16) + b) * src_subpos) >> 16) + c) * src_subpos) >> 10) + x[1]) * volume_fact) >> 14; \
01130                                                                                            \
01131                                 src_subpos += dt + inc;            \
01132                                 src_pos += src_subpos >> 15;   \
01133                                 src_subpos &= 0x7FFFl;             \
01134                                 s++;                                               \
01135                         }
01136                         */
01137 
01138                         /* H4x0r3d version: */
01139                         #define DO_RESAMPLE(inc)                   \
01140                         {                                                                  \
01141                                 HEAVYASSERT(dir < 0 ? (src_pos >= src_start) : (src_pos < src_end)); \
01142                                                                                            \
01143                                 if (src_pos != last_src_pos) { \
01144                                         last_src_pos = src_pos;    \
01145                                         x = &src[src_pos];                 \
01146                                         a = (((x[1] - x[2]) << 1) + (x[1] - x[2]) + (x[3] - x[0])) >> 1; \
01147                                         b = (x[2] << 1) + x[0] - ((5 * x[1] + x[3]) >> 1); \
01148                                         c = (x[2] - x[0]) >> 1;    \
01149                                 }                                                          \
01150                                                                                            \
01151                                 dst[s] += (((int)(((LONG_LONG)((int)(((LONG_LONG)((int)(((LONG_LONG)a * src_subpos) >> 15) + b) * src_subpos) >> 15) + c) * src_subpos) >> 15) + x[1]) * volume_fact) >> 14; \
01152                                                                                            \
01153                                 src_subpos += dt + inc;            \
01154                                 src_pos += src_subpos >> 15;   \
01155                                 src_subpos &= 0x7FFFl;             \
01156                                 s++;                                               \
01157                         }
01158 
01159                         MAKE_RESAMPLER();
01160 
01161                         #undef DO_RESAMPLE
01162 
01163                 }
01164 
01165         }
01166 
01167         end:
01168 
01169         ASSERT(s <= dst_size);
01170 
01171         *_src_pos = src_pos;
01172         *_src_subpos = src_subpos;
01173         if (_dir) *_dir = dir;
01174 
01175         return s;
01176 }
01177 #endif
01178 
01179 }

Generated on Mon Feb 13 23:07:46 2006 for audiere by  doxygen 1.4.6