00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <math.h>
00046 #include "dumb_resample.h"
00047
00048 namespace audiere {
00049
00050
00051
00052
00053
00054 #ifdef HEAVYDEBUG
00055 #define HEAVYASSERT(cond) ASSERT(cond)
00056 #else
00057 #define HEAVYASSERT(cond)
00058 #endif
00059
00060
00061
00062
00063
00064 #define MULSC(a, b) ((int)((LONG_LONG)((a) << 4) * ((b) << 12) >> 32))
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
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
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
00150
00151
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
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
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
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
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
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
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
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
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
00486 return MULSC(src[pos], vol);
00487 } else if (quality <= DUMB_RQ_LINEAR) {
00488
00489 return MULSC(resampler->x[2] + MULSC(resampler->x[1] - resampler->x[2], subpos), vol);
00490 } else {
00491
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
00503 return MULSC(src[pos], vol);
00504 } else if (dumb_resampling_quality <= DUMB_RQ_LINEAR) {
00505
00506 return MULSC(resampler->x[1] + MULSC(resampler->x[2] - resampler->x[1], subpos), vol);
00507 } else {
00508
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
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
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
00632 if (!pickup) {
00633 dir = 0;
00634 goto end;
00635 }
00636
00637
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
00652 int volume_fact = (int)(volume * 16384.0);
00653 value = (src[src_pos] * volume_fact) >> 14;
00654 } else if (dumb_resampling_quality <= 2) {
00655
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
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
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;
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
00727
00728 if (linear_average) {
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 float sum;
00741 long i;
00742 int advance;
00743 int x[3];
00744
00745 advance = src_subpos + dt;
00746
00747
00748
00749
00750 x[0] = ~(src_subpos >> 1);
00751 x[2] = x[0] ^ 0x7FFF;
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;
00758
00759 advance &= 65535;
00760
00761
00762
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
00776
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
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;
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
00824 if (!pickup) {
00825 dir = 0;
00826 break;
00827 }
00828
00829
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
00840 if ((dir ^ dt) < 0)
00841 dt = -dt;
00842 }
00843
00844
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
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 ASSERT(todo >= 0);
00866
00867 if (!linear_average)
00868 todo++;
00869
00870
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
00894
00895
00896 x[0] = ~(src_subpos >> 1);
00897 x[2] = x[0] ^ 0x7FFF;
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;
00904
00905 advance &= 65535;
00906
00907
00908
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;
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
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
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
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
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
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
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
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
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 }