#N canvas 346 38 960 867 12;
#X declare -stdpath ./;
#X obj 505 536 metro 100;
#X obj 238 463 phasor~;
#X obj 505 566 snapshot~;
#X obj 37 628 output~;
#X obj 38 452 phasor~;
#X floatatom 38 320 5 -100 1000 0 - - - 0;
#X obj 37 509 tabread4~ \$0-tab;
#X msg 368 320 0.5;
#X msg 404 320 0.01;
#X obj 505 449 loadbang;
#X msg 505 475 1;
#X obj 418 656 +;
#X obj 238 721 tabread4~ \$0-tab;
#X obj 476 656 f;
#X obj 386 633 t f f;
#X obj 238 757 output~;
#X floatatom 487 690 8 0 0 0 - - - 0;
#X obj 418 691 t f b;
#X obj 450 720 f;
#X obj 418 720 -;
#X floatatom 568 625 8 0 0 0 - - - 0;
#X obj 400 747 -;
#X obj 505 511 tgl 18 0 empty empty empty 17 7 0 10 #dfdfdf #000000 #000000 0 1;
#X obj 238 489 -~ 0.5;
#X obj 400 836 + 0.5;
#X obj 37 481 *~ 1e+06;
#X floatatom 400 777 8 0 0 0 - - - 0;
#X obj 618 545 samplerate~;
#X obj 586 544 /;
#X obj 586 519 t f b;
#X obj 568 599 +;
#X obj 400 808 / 10000;
#X obj 238 514 *~ 10000;
#X obj 586 570 * 10000;
#X obj 571 176 samplerate~;
#X obj 571 200 / 2;
#X obj 560 251 tabwrite~ \$0-tab;
#X obj 571 224 osc~;
#X obj 560 131 bng 19 250 50 0 empty empty empty 17 7 0 10 #dfdfdf #000000 #000000;
#X obj 38 424 / 1e+06;
#X text 549 689 new onset is phase plus old onset;
#X obj 404 348 * 1e+06;
#X text 631 627 extrapolated phase of next sample;
#X text 482 721 new onset minus old onset;
#X text 470 755 back up phasor output by amount the onset advanced;
#X text 468 768 (approximately zero but not exactly because of;
#X text 470 782 truncation error!);
#X obj 404 374 t b f;
#X text 463 348 convert to samples;
#X text 448 375 set both last-onset and previous-onset;
#X text 448 398 ... and also reset phasor.;
#X text 465 808 convert phase back to range 0-1, f 17;
#X obj 238 426 / 10000;
#X text 45 400 cycles/sec;
#X text 45 388 convert to;
#X text 296 426 cycles/sec;
#X text 240 402 convert to;
#X text 67 692 BAD;
#X text 273 819 GOOD;
#X msg 386 406 0;
#X text 634 510 extrapolate snapshot of phase by one sample to sync with next block, f 34;
#X obj 737 22 declare -stdpath ./;
#X msg 669 169 \; pd dsp 1 \, fast-forward 22680;
#X text 539 62 *** The table is now 1 million points and takes about 23 seconds to fill \, we also use the 'fast-forward' message to fill it., f 47;
#X text 24 50 Here is how to use the [tabread~]'s "onset" input to allow clean varispeed playback from a long table. At left \, a [phasor~] is naively rescaled to the size of the table. At right \, the [phasor~] gets only a 10000-point range about a moving "onset". Ten times per second \, we poll the [phasor~]'s phase \, sum its value into the onset \, and back up the phase of the [phasor~] correspondingly., f 69;
#X text 24 140 The tricky bits are \, first \, that we need to poll the [phasor~]'s phase one sample into the future (so we add the per-sample increment into the [snapshot~] result). Second \, we can't just reset the [phasor~] to a fixed point - instead \, we measure how much the onset has actually increased (which has truncation error from summing in the phase snapshot) \, and subtract that increase from the phase \, giving a value that differs from zero by the truncation error but reflects the true phase we should reset to for continuity., f 69;
#X text 24 259 The metronome rate is arbitrary but should be fast enough that the [phasor~] never has time to wrap., f 69;
#X text 447 319 <-- reset phase. 0.5 causes trouble for the "bad" way.;
#X text 86 319 <-- playback speed \, samples/sec;
#X text 578 456 Each 100 msec \, poll phase of [phasor~] in order to change onset to reflect it, f 38;
#X text 104 451 naive way: just run a phasor into [tabread4~], f 16;
#X text 105 551 convert phase to range +/- 5000 -->, f 18;
#X obj 34 14 cnv 5 5 25 empty empty Variable\ Speed\ Playback\ from\ Long\ Tables 15 13 0 16 #dfdfdf #202020 0;
#X obj 702 251 array define \$0-tab 1e+06;
#X connect 0 0 2 0;
#X connect 1 0 23 0;
#X connect 2 0 30 0;
#X connect 4 0 25 0;
#X connect 5 0 39 0;
#X connect 5 0 52 0;
#X connect 6 0 3 0;
#X connect 7 0 4 1;
#X connect 7 0 41 0;
#X connect 8 0 4 1;
#X connect 8 0 41 0;
#X connect 9 0 10 0;
#X connect 10 0 22 0;
#X connect 11 0 13 0;
#X connect 11 0 17 0;
#X connect 11 0 12 1;
#X connect 11 0 16 0;
#X connect 12 0 15 0;
#X connect 13 0 11 1;
#X connect 14 0 21 0;
#X connect 14 1 11 0;
#X connect 17 0 18 1;
#X connect 17 0 19 0;
#X connect 17 1 18 0;
#X connect 18 0 19 1;
#X connect 19 0 21 1;
#X connect 21 0 26 0;
#X connect 22 0 0 0;
#X connect 23 0 32 0;
#X connect 24 0 1 1;
#X connect 25 0 6 0;
#X connect 26 0 31 0;
#X connect 27 0 28 1;
#X connect 28 0 33 0;
#X connect 29 0 28 0;
#X connect 29 1 27 0;
#X connect 30 0 14 0;
#X connect 30 0 20 0;
#X connect 31 0 24 0;
#X connect 32 0 2 0;
#X connect 32 0 12 0;
#X connect 33 0 30 1;
#X connect 34 0 35 0;
#X connect 35 0 37 0;
#X connect 37 0 36 0;
#X connect 38 0 34 0;
#X connect 38 0 36 0;
#X connect 38 0 62 0;
#X connect 39 0 4 0;
#X connect 41 0 47 0;
#X connect 47 0 59 0;
#X connect 47 1 18 1;
#X connect 47 1 11 1;
#X connect 52 0 1 0;
#X connect 52 0 29 0;
#X connect 59 0 14 0;
