Phasor

Phasor

Overview

The phasor (not to be confused with the phaser audio effect) is a name used to describe a classic signal generator that produces a periodic ramp signal normalized to be in range 0-1, set to move at a specified frequency. Phasors are typically used in the context of table-lookup oscillators such as oscf.

The term "phasor" comes from the engineering and physics world, used to describe the complex value of a sinusoid (phase, and amplitude). While not a complex value, the phasor in this computer music context could be the phase component of the phasor.

The adoption of the phasor term in the computer music world can be traced back to one of the oldest opcodes in Csound, but the author believes it may go back even further to the MUSICN family of computer music languages. It is noteworthy that the word phasor is six letters, which was the character limit for opcodes in both MUSICN languages and the older versions of Csound. In this context, it is a really nice name to describe this.

Tangled Files

Tangles to phasor.h and phasor.c.

If SK_PHASOR_PRIV is defined, it exposes the struct sk_phasor, otherwise it is opaque.

<<phasor.h>>=
#ifndef SK_PHASOR_H
#define SK_PHASOR_H

#ifndef SKFLT
#define SKFLT float
#endif

<<typedefs>>
<<funcdefs>>
#ifdef SK_PHASOR_PRIV
<<structs>>
#endif
#endif

<<phasor.c>>=
#define SK_PHASOR_PRIV
#include "phasor.h"
<<funcs>>

Struct and initialization

The state of phasor is wrapped in a struct called sk_phasor, and initialized with sk_phasor_init. You'll need the sampling rate, and initial phase.

<<typedefs>>=
typedef struct sk_phasor sk_phasor;

In sk_phasor, freq stores the frequency, phs stores the previous phasor value, and onedsr is the inverse value of the sampling rate, which is used in order to shave off a traditionally more expensive divide operation.

<<structs>>=
struct sk_phasor {
    SKFLT freq;
    SKFLT phs;
    SKFLT onedsr;
};

<<funcdefs>>=
void sk_phasor_init(sk_phasor *ph, int sr, SKFLT iphs);

<<funcs>>=
void sk_phasor_init(sk_phasor *ph, int sr, SKFLT iphs)
{
    ph->phs = iphs;
    ph->onedsr = 1.0 / sr;
    sk_phasor_freq(ph, 440);
}

Setting the Frequency

The frequency of the phasor can be set with sk_phasor_freq.

<<funcdefs>>=
void sk_phasor_freq(sk_phasor *ph, SKFLT freq);

<<funcs>>=
void sk_phasor_freq(sk_phasor *ph, SKFLT freq)
{
    ph->freq = freq;
}

Computation

A single sample of audio is computed with sk_phasor_tick.

<<funcdefs>>=
SKFLT sk_phasor_tick(sk_phasor *ph);

The output of the phasor is the current internal phase state before being incremented.

The behavior of the phasor is to increment its internal phase by an increment amount, determined by freq*onedsr. It is then wrapped to be in range 0 and 1. Instead of using something fmod for the wrapping, conditionals and arithmetic are used. In addition to being simpler, this is often a faster approach.

<<funcs>>=
SKFLT sk_phasor_tick(sk_phasor *ph)
{
    SKFLT phs;
    SKFLT incr;
    SKFLT out;

    phs = ph->phs;
    incr = ph->freq * ph->onedsr;

    out = phs;

    phs += incr;

    if (phs >= 1.0) {
        phs -= 1.0;
    } else if (phs < 0.0) {
        phs += 1.0;
    }

    ph->phs = phs;

    return out;
}

Resetting The Phase

The phase of the phasor can be reset with a particular value in sk_phasor_reset. If the the value is less than 0, it will use a default value of 0.

<<funcdefs>>=
void sk_phasor_reset(sk_phasor *phs, SKFLT val);

<<funcs>>=
void sk_phasor_reset(sk_phasor *phs, SKFLT val)
{
    if (val >= 0) phs->phs = val;
    else phs->phs = 0;
}