Two beginner "what object should I use?" questions.
@alexandros said:
Am I missing something, or the patch below isn't correct?
[phasor~ 1] | [threshold 0.5 10 0.5 10] | [o]This does output a bang whenever [phasor~] resets.
Nice, provided this operates as suggested (haven't tested), this does precisely what I'm looking for.
I literally started with PD last week, so I just haven't encountered the threshold module to consider (I used Max/MSP back in the Nato.0+55+3d days, supercollider in the early 2000s, and patch modulars extensively since the Nord Modular days, but ignored PD for the most part under an impression it lacked refinement).
My aim is quite simple, embarrassingly so: I'm learning how to play back samples loaded into arrays, and wanted to test my bpm calculations after changing the phasor's speed. As a test I wanted to run a metro at the quarter note time of the new BPM, triggering a kick sample, and confirm the hits are falling where I expect them to,... but then I ran into the issue of getting my metro to start precisely in time with the looping sample (which is just freely looping endlessly via a phasor). Since the phasor~ lacked a phase output, I was stumped, and figured getting the array index = 0 = bang would be a simpler approach.
Per the randomF, the multiplicative scaling by 0.1 works, but then limits my range to 0-1. The use of a second random added to these values would fix this easily, but didn't seem as efficient as finding something that might already exist. Good to hear else has a "rand.f" (or whatever is typed above). I have this external already installed, but haven't exhaustively worked through what is included.
Thanks again, one and all.
p.s. Per the playback of arrays, I have learned a method of chopping samples with a dedicated start button using direct indexing of the slice's start in sample size values (fed as arguments into a vline module set to read from tabread4), but haven't learned how to do so when indexing via a phasor~, I suspect I'll get there in the next day or so.
The vline approach feels superior, but I'm not so sure it lends itself to rate control as easily as phasor~. Indexing via phase seems simpler too since it'll always be 0-1.
snapshotting and restoring the state of a [phasor~] exactly
@jameslo I think all your assumptions are correct.
I'm just using it as an oscillator/LFO. Are you suggesting that there's a way to build an oscillator with [rpole~] that is as frequency-accurate as [phasor~] but without the single vs double precision issue?
No, as far as I understood:
Phasor~ is frequency-accurate, while compromising on the absolute y-value: Jitter in amplitude as little trade-off (which multiplied can become big).
On the contrary to a rpole~ramp, which is accurate in amplitude and accurately reproduces 'one-shots' sample-by-sample, but therefor must jitter in frequency when oscillating.
And I assumed wrong, maybe the correct amplitude would be most important for your application.
(The term phase of a ramp can be seen as amplitude or time.)
So I mentioned rpole~ solution.
the best it can do (without having to predict the future) is to return the last sample of the previous audio block.
Yes, you are right. Not a bug.
But it is not [phasor~] being slow (that is what I have been reading in your first post), it is [snapshot~] being one sample late.
Anyway, this thread is helpful for me, as I am slowly working on a state-saving-thing, and have not been aware of the 1-sample difference. Thank you.
snapshotting and restoring the state of a [phasor~] exactly
@lacuna said:
Don't know about phasor's right inlet, but I guess for more precision on the outside of objects we'd have to use 'Pd double precision'.
Yes, I confirmed that my test patch runs without issue under Pd64. Unfortunately, my real patch doesn't 
Also remember @ddw_music different approach than [phasor~]:
I think that "different approach" is a different issue--I'm not multipying its output to index into a large table. I'm just using it as an oscillator/LFO. Are you suggesting that there's a way to build an oscillator with [rpole~] that is as frequency-accurate as [phasor~] but without the single vs double precision issue?
On one sample late: It is [snapshot~] who is early, not [phasor~]:
...
I would call this a bug of [snapshot~] !%§$*(
I don't understand your conclusion about the timing of [snapshot~]. Here's how I would analyze your demonstration patch: the top bang is processed in-between audio blocks. Therefore, [tabplay~] and [fexpr~] run in the following audio block. [snapshot~] is different though, because it's a bridge between control rate and audio rate--like bang, it also runs between audio blocks. Therefore, the best it can do (without having to predict the future) is to return the last sample of the previous audio block. So it's not surprising for [fexpr~] to have to reach back into the previous audio block to get the same value as [snapshot~]. If [snapshot~] were to return the first sample of the following audio block, it couldn't pass that value to control rate code until that audio block's processing is complete. Do you see my point?
Also, I'm not saying [phasor~] is early, I'm just saying its right inlet isn't a mechanism for restoring its state. It's just for what the documentation says it's for: to reset its phase to a given value.
snapshotting and restoring the state of a [phasor~] exactly
Suppose you want to capture the state of a [phasor~] in order to return to it later, i.e. you want it to output the exact same sequence of samples as it did from the moment you captured its state. As a first attempt, you might [snapshot~] the [phasor~]'s output and then send that value to the [phasor~]'s right inlet sometime later to restore it. Of course you also want to capture the state of its frequency inlet (and record it if it's changing). But there are two subtleties to consider. Firstly, the value you write to the right inlet is the next value that the [phasor~] will output, but when you [snapshot~]ed it, the next value it output was a little greater, greater by the amount of the last frequency divided by the current sample rate. So really, this greater value (call it "snap++") is the one you should be writing to the right inlet.
The second subtlety has to do with the limits of Pd's single precision floats. Internally, [phasor~] is accumulating into a double precision float, so in a way, the right inlet overwrites the state of the phasor with something that can only approximate its state. The only solution I could find is to immediately write snap++ to the right inlet of the running [phasor~], so that the current and all future runs output the exact same sequence of samples. This might not be acceptable in your application if you are reliant on [phasor~]'s double precision accumulation because you'd be disrupting it in exchange for repeatability.
Here's a test patch that demonstrates the issue:
phasor snapshot restore test.pd

Looking for advice on using phasor~ to randomize tabread4~ playback
@nicnut said:
There is a number box labeled "transpose." The first step is to put a value in there, 1 being the original pitch, .5 is an octave down, 2 is an octave up, etc.
Here, you'd need to calculate the phasor frequency corresponding to normal playback speed, which is 1 / dur, where dur is the soundfile duration in seconds. Soundfile duration = soundfile size in samples / soundfile sample rate, so the phasor~ frequency can be expressed as soundfile sample rate / soundfile size in samples. Then you multiply this by a transpose factor, ok.
But I don't see you accounting for the soundfile's size or sample rate, so you have no guarantee of actually hitting normal playback speed.
After that you can change the frequency of the phasor in the other number box labled "change phasor frequency without changing pitch."
If you change the phasor frequency here, you will also change the transposition.
This way, I can make the phasor frequency, say .5 and the transposition 2,
Making the eventual playback speed 1 (assuming it was 1 to begin with), undoing the transposition.
which I don't think I can do using line~ with tabread4~.
The bad news is, you can't do this with phasor either.
hjh
looking for velvet noise generator
Ok, I changed the algorithm a bit and now I think I nailed it and solved it for frequencies up to Nyquist and above! I'm just randomly choosing any sample in the period, from first to last and I don't have if there are consecutive samples, like the last sample from the previous period and first sample from the current one.
for(int j = 0; j < x->x_nchans; j++){
for(int i = 0, n = x->x_n; i < n; i++){
double hz = in1[j*n + i];
double step = hz * x->x_sr_rec; // phase step
step = step > 1 ? 1 : step < 0 ? 0 : step; // clip step
t_float imp = 0;
t_float r = x->x_rand[j]; // - step;
if(phase[j] >= r && ((lastphase[j] < r) || (x->x_1st[j])))
imp = velvet_random(x) > 0.5 ? 1 : -1;
out[j*n + i] = imp;
x->x_1st[j] = 0;
if(phase[j] >= 1.){
x->x_1st[j] = 1;
x->x_rand[j] = velvet_random(x);
while(phase[j] >= 1.)
phase[j] -= 1; // wrap phase
}
lastphase[j] = phase[j];
phase[j] += step;
}
}```
looking for velvet noise generator
As I was imagining, as a C code, this is all hassle free, very simple, and never misses a period. And the code is pretty simple. And Multichannel capable 

So far this is what I have....
// Porres 2024
#include "m_pd.h"
#include <stdlib.h>
#include "random.h"
#define MAXLEN 1024
typedef struct _velvet{
t_object x_obj;
double *x_phase;
double *x_lastphase;
t_random_state x_rstate;
int x_id;
t_float *x_rand;
int x_nchans;
t_float x_hz;
t_int x_n;
t_int x_ch2;
t_int x_ch3;
t_inlet *x_inlet_reg;
t_inlet *x_inlet_bias;
t_outlet *x_outlet;
double x_sr_rec;
}t_velvet;
static t_class *velvet_class;
static void velvet_seed(t_velvet *x, t_symbol *s, int ac, t_atom *av){
random_init(&x->x_rstate, get_seed(s, ac, av, x->x_id));
}
static t_int *velvet_perform(t_int *w){
t_velvet *x = (t_velvet *)(w[1]);
t_float *in1 = (t_float *)(w[2]);
// t_float *in2 = (t_float *)(w[3]); // bias placeholder
// t_float *in3 = (t_float *)(w[4]); // regularity placeholder
t_float *out = (t_float *)(w[5]);
double phase = x->x_phase;
double lastphase = x->x_lastphase;
for(int j = 0; j < x->x_nchans; j++){
for(int i = 0, n = x->x_n; i < n; i++){
double hz = in1[jn + i];
double step = hz * x->x_sr_rec; // phase step
step = step > 1 ? 1 : step < 0 ? 0 : step; // clipped phase_step
out[jn + i] = ((phase[j] + x->x_rand[j]) >= 1.) && ((lastphase[j] + x->x_rand[j]) < 1.);
if(phase[j] >= 1.){
uint32_t *s1 = &x->x_rstate.s1;
uint32_t *s2 = &x->x_rstate.s2;
uint32_t *s3 = &x->x_rstate.s3;
x->x_rand[j] = (t_float)(random_frand(s1, s2, s3)) * 0.5 + 0.5;
post("phase = %f", phase[j]);
post("random = %f", x->x_rand[j]);
phase[j] -= 1; // wrapped phase
}
lastphase[j] = phase[j];
phase[j] += step;
}
}
x->x_phase = phase;
x->x_lastphase = lastphase;
return(w+6);
}
static void velvet_dsp(t_velvet *x, t_signal **sp){
x->x_n = sp[0]->s_n, x->x_sr_rec = 1.0 / (double)sp[0]->s_sr;
int chs = sp[0]->s_nchans;
x->x_ch2 = sp[1]->s_nchans, x->x_ch3 = sp[2]->s_nchans;
if(x->x_nchans != chs){
x->x_lastphase = (double *)resizebytes(x->x_lastphase,
x->x_nchans * sizeof(double), chs * sizeof(double));
x->x_phase = (double *)resizebytes(x->x_phase,
x->x_nchans * sizeof(double), chs * sizeof(double));
x->x_rand = (t_float )resizebytes(x->x_rand,
x->x_nchans * sizeof(t_float), chs * sizeof(t_float));
x->x_nchans = chs;
}
signal_setmultiout(&sp[3], x->x_nchans);
if((x->x_ch2 > 1 && x->x_ch2 != x->x_nchans)
|| (x->x_ch3 > 1 && x->x_ch3 != x->x_nchans)){
dsp_add_zero(sp[3]->s_vec, x->x_nchansx->x_n);
pd_error(x, "[velvet~]: channel sizes mismatch");
return;
}
dsp_add(velvet_perform, 5, x, sp[0]->s_vec,
sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec);
}
static void *velvet_free(t_velvet *x){
inlet_free(x->x_inlet_bias);
inlet_free(x->x_inlet_reg);
outlet_free(x->x_outlet);
freebytes(x->x_phase, x->x_nchans * sizeof(*x->x_phase));
freebytes(x->x_lastphase, x->x_nchans * sizeof(*x->x_lastphase));
freebytes(x->x_rand, x->x_nchans * sizeof(*x->x_rand));
return(void *)x;
}
static void *velvet_new(t_symbol *s, int ac, t_atom *av){
s = NULL;
t_velvet *x = (t_velvet *)pd_new(velvet_class);
x->x_id = random_get_id();
x->x_phase = (double *)getbytes(sizeof(*x->x_phase));
x->x_lastphase = (double *)getbytes(sizeof(*x->x_lastphase));
x->x_rand = (t_float *)getbytes(sizeof(*x->x_rand));
x->x_hz = x->x_phase[0] = x->x_lastphase[0] = x->x_rand[0] = 0;
velvet_seed(x, s, 0, NULL);
if(ac){
while(av->a_type == A_SYMBOL){
if(ac >= 2 && atom_getsymbol(av) == gensym("-seed")){
t_atom at[1];
SETFLOAT(at, atom_getfloat(av+1));
ac-=2, av+=2;
velvet_seed(x, s, 1, at);
}
else
goto errstate;
}
if(ac && av->a_type == A_FLOAT){
x->x_hz = av->a_w.w_float;
ac--, av++;
}
}
x->x_inlet_bias = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
pd_float((t_pd *)x->x_inlet_bias, 0);
x->x_inlet_reg = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal);
pd_float((t_pd *)x->x_inlet_reg, x->x_phase[0]);
x->x_outlet = outlet_new(&x->x_obj, &s_signal);
return(x);
errstate:
post("[velvet~]: improper args");
return(NULL);
}
void velvet_tilde_setup(void){
velvet_class = class_new(gensym("velvet~"), (t_newmethod)velvet_new, (t_method)velvet_free,
sizeof(t_velvet), CLASS_MULTICHANNEL, A_GIMME, 0);
CLASS_MAINSIGNALIN(velvet_class, t_velvet, x_hz);
class_addmethod(velvet_class, (t_method)velvet_dsp, gensym("dsp"), A_CANT, 0);
class_addmethod(velvet_class, (t_method)velvet_seed, gensym("seed"), A_GIMME, 0);
}
looking for velvet noise generator
@seb-harmonik.ar said:
I do think @manuels original idea of having a sample-increment offset still works without missing periods?
Why don't you think it works with non-integer period lengths?a phasor~ is always guaranteed to have its last sample be within the last sample increment regardless of whether an integer-period or not, and
[wrap~]will pretty much perfectly wrap the phasor~'s phase..
With non-integer period lengths you have effectively a changing number of samples per period. That in itself I don't think would be a problem, but adding a random value and wrapping the result can give you sample-increments that are either smaller or bigger than the calculated value.
Maybe an extreme example can help to clarify: Consider a period length of 2.5 samples. The sample increment is in this case 0.4. If you have a period with the sample values 0.3 and 0.7, add 0.8 as a random value and wrap, what you get is 0.1 and 0.5, so the last sample doesn't get above 1 when you add the calculated sample-increment of 0.4. Am I missing something?
@ben.wes Did you do the testing with non-integer fractions of your sampling frequency? You mentioned 3kHz at 48kHz SR as an example, which shouldn't make problems ....
simple polyphonic synth - clone the central phasor or not?
@manuels That's clever, thanks! I especially like how you get the slope of the input phasor (compensating for that downward jump every cycle) and how you construct the output phasor. But I think there are two issues with it. Firstly, a sync will reset the phase of the output phasor at an arbitrary point unless the output phasor frequency is an exact multiple of the input frequency. Secondly, without sync, I think the output phasor may drift WRT the input phasor due to floating point roundoff error. Agree?
Backing out to look at the big picture again, i.e. Brendan's question, this means that it couldn't be used to make either a "hardsync" synthesizer (disclaimer: I don't really know what that is) or a "phasor~-synchronized system", assuming that both require a precise phase relationship between the input and output phasors and that the output phasor doesn't contain discontinuities. What do you think?
Tabplay~ -tabread~
I have build a six shot sampler with tabplay~ objects since these have the benefit of sample accurate adjusting the start adress ( helpfull when recording too late )
But since these are one shot ( adjustable end adress too ) and non transposable , I wonder if there's a method to adjsut the start adress of tabread~ objects .
Assume the tabread is 88200 samples long , but recording only begun after 17500 samples .
I can use the same method as tabread , use as fader 0-1 multiplied by lenght of file into line ~ and into tabread to get to the first audible sample peaks to determine start adress
So I get a tabread of 176400 samples , with 90000 samples of silence at the beginning , subtracting these from the sample length is 86400
SO the Line should start at 86400 instantly , then the second phase are the resulting samples and time correction .of 1959 MS
OK got it
This should be it
90000 0 0 ,17640 1959 0 ,0 0 1959
