What does gen phasor do? (trying to convert to C++)

elanhickler's icon

The question is basically: What would a C++ equivalent be to phasor? I know it takes in a frequency and outputs a 0 to 1 sawtooth waveform, but I don't know how it does that without a phase or time reference.

Evan's icon

I don't know any C++, so I'll just speak to what its doing in gen, as I understand it.
You can use a counter, or accumulator to simulate a phasor in gen, by taking into account sample rate, and wrapping the count at the appropriate value basd on the frequency value.

Here's a very crude gen~ phasor with nothing but arithmetic in codebox:

History count(0);
frequency = in1;
length = samplerate/frequency;
count = count + 1;
out1 = (count % length)/length;

elanhickler's icon

That's all good, but what I don't get is how you can have more than one call to phasor in the same gen code box.

does each phasor magically have a unique set of all of those variables? frequency,length,count?

so if I did this:
my_frequency_1 = 40;
my_frequency_2 = 1000;

phasor_val_1 = phasor(my_frequency_1); // this is a phasor
phasor_val_2 = phasor(my_frequency_2); // this is another instance of phasor
phasor_val_1 != phasor_val_2 // resolves to true?

so each call to phasor is magically a unique instance?

Evan's icon

Yeah it won't resolve to true unless th phasors start at the same time and have identical frequencies. I'm no expert, but I don't think its magic.

phasor(x){
    History count(0);
    length = samplerate/x;
    count = count + 1;
    return (count % length)/length;
}
out1 = phasor(in1);
out2 = phasor(in2);

That will give you two different phasors. I don't know enough about the low level memory allocation stuff going on, to comment on exactly how or why this works.

elanhickler's icon

Ok, so I am overthinking this. Phasor is just a function, not an object, not an instance of some oscillator class.

Roman Thilenius's icon

it is like a counter object. and, as you know, is aware of the current samplingrate, so there are the two variables you need. :) (the count is always the same...)

elanhickler's icon

I am not overthinking this. After implementing the suggested code by Evan, I got results that differ from Max/MSP/Gen.

In Max/MSP/Gen, each call to phasor is indeed a unique oscillator. With Evan's code, changing frequency also changes phase, because there is no memory of phase in Evan's code. In Max/MSP/Gen, increasing frequency simply makes the phasor run faster rather than jerk around like Evan's code (jerking is result of changing phase).

Floating Point's icon

I guess you'd need to keep track of phase separate to freq, with a phase variable expressed as a float between 0 and 1, so if freq is changed, you reset the count according to the current phase fraction

elanhickler's icon

I created this C++ class:

class Phasor
{
public:
    double getSample()
    {
        double ret = phase/PI_z_2;
        phase = fmod(phase+phase_inc, TAU); //increment phase
        return ret;
    }
    void setSampleRate(double v) { sampleRate = v; calculateIncrement(); }
    void setFrequency(double v) { frequency = v; calculateIncrement(); }
    void calculateIncrement() { phase_inc = TAU * frequency / sampleRate; }
    void Reset() { phase = 0.0; }
protected:
    double sampleRate = 44100.0;
    double frequency = 1.0;
    double phase = 0.0;
    double phase_inc = 0.0;
    const double TAU = 2*PI;
};

Floating Point's icon

looks eloquent, when frequency changes you alter the increment (phase_inc), while keeping the current accumulation (phase), and your phase is between zero and 2pi which is perhaps more useful than between 0 and 1

Evan's icon

Was away for the weekend - sorry I missed the developments. I didn't include any phase handling, because I didn't want to take all the fun ;).

Although it seems you've already got it sorted rather well. my two ideas for handling phase would be to (1)only update at the end of a cycle ( less flexible, but more syncable), or (2) sample the phase when the frequency changes, and then reset the count with the new frequency, while adding an offset equal to the previous phase.

I didn't even think of altering the increment....

elanhickler's icon

Wait... WTF... my phasor is not 0 to 1?!?! I didn't think about that!.. that could explain why none of my gen-to-C++ has been working.