[PD] Creating a basic oscillator from first principles?

Andy Farnell padawan12 at obiwannabe.co.uk
Sat Feb 7 20:07:00 CET 2009

Here's some notes and an example patch on exactly this subject
hope it helps.


The first principles of generative DSP can be broken into three concepts
which follow easily from one another.

The first and most fundamental is that of the accumulator. This just means
something like

x = x + 1

Or more correctly x[t_n] = x[t_n-1] + k

It just makes a line. The line increases without bound. From high school
maths you will know the line equation y = mx + c, the slope m determines 
how fast the line rises from an origin c on the y axis for a given interval
on the x axis. In DSP we make the x axis be time, t, and the discrete time
values n and n-1 represent contiguous samples along the time line.

In a simple sense of programming the accumulator/incrementor/integrator can 
be considered an endless loop, a do-while(1) or for(;;;) loop, in which a variable
is incremented by a small amount on each step. In a more advanced interpretation
the accumulator/incrementor can be thought of as a filter, an IIR filter in which
the current output depends on the last output plus input k, so it integrates k 
over time. Thus by changing k we can change the slope (slew or phase
increment) of the line. 

Shown in part one of the example patch is a couple of ways of doing this. The 
first uses [vline~] to make a line that will rise steadily over a long period
of time. The second is more arcane, it uses a [biquad~] object as an integrator.

This isn't much use until we combine it with the second fundamental concept, the
idea of wrapping. Wrapping creates a discontinuous periodic function by making
any input value x greater than N become 0 < x < N, wrapping the output back
into the range between zero and N. If x is a float then it's the fractional part
of x, or x - floor(x), like the modulo operator is to integers. In Pure Data
it is defined for the range 0 to 1.0. What we get by combining an accumulator with 
a wrap is called a phasor, a line that cycles up from 0.0 to 1.0 over and over.
The frequency of the phasor is determined by the slope of the line, by the phase
increment k.

In practice, in code, we combine the integrator and wrap into a single unit
so that the line does not increase without bound. If it does then the oscillator
will work for a while, but then the line will exceed the representation range
of the CPU.

A wrapped line is shown in the second part of the patch along with an example
of how it is like the built-in [phasor~] object.

The final part of the picture is a new periodic function that sets the waveform
of our oscillator. It is defined over the domain 0.0 to 1.0 so the phasor drives
the input nicely, but it normally has a bipolar range defined between -1.0 and 1.0
to give a symmetrical waveform without a DC component. This can be in the form of
a lookup table, for which the domain is mapped to the table size, or a trigonometric
function like cos(x) for which the domain is mapped to 2 time PI. In other words the
periodic function takes a phasor that cycles up to 1.0 and maps it onto a waveform
that cycles backwards and forwards around zero. 

In the last part of the example patch we see a wrapped line and periodic function
behave as an oscillator alongside the built-in [osc~] object which does more or
less the same thing.


On Sat, 7 Feb 2009 17:31:48 +0000
Geoff <geoffspuredata at googlemail.com> wrote:

> Hi
> I am very new to PD and DSP concepts.
> So this will be hopelessly, awfully, basic :)
> I have just started chapter 3 of 'The theory and technique of  
> electronic music'
> which is excellent
> However it raises a million questions in my head...... one of which  
> is how do I create an oscillator myself?
> Its really bugging me everytime I create an example from the book. I  
> feel I need to understand the fundamentals of how the basic objects  
> are created too.
> It seems too easy for me to just use the phasor object provided,
> So I thought I would struggle through it and try to work it out.
> This is how I am thinking about it.
> If I want to create a sawtooth oscillator then this is just a ramp  
> function i.e. a number that increases by 1 each time.
> therefore if I use a simple float that, that adds 1 each time and a  
> modulus % object to cap it, then I will have my repeating ramp wave :)
> However I am triggering it by the metro object which is way too slow,  
> how can I send a bang to the float object say every sample? or alot  
> quicker than one millisecond?
> My thinking is if I could speed up the bangs to a sample level I  
> would then have more scope to then actually tune it, and create the  
> shape I want. However I am sure to do this well would require working  
> at a higher sample rate, but I am not really sure how to proceed.
> Below is my appalling attempt :) I use the number box to change pitch.
> Any guidance appreciated
> Cheers
> Geoff
> #N canvas 325 62 681 388 10;
> #X obj 119 69 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
> -1;
> #X obj 121 96 f;
> #X obj 181 116 + 1;
> #X obj 115 17 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
> -1;
> #X obj 127 238 dac~;
> #X obj 118 46 metro 1;
> #X floatatom 187 163 5 0 0 0 - - -;
> #X obj 115 160 %;
> #X obj 114 199 /;
> #X connect 0 0 1 0;
> #X connect 1 0 2 0;
> #X connect 1 0 7 0;
> #X connect 2 0 1 1;
> #X connect 3 0 5 0;
> #X connect 5 0 0 0;
> #X connect 6 0 7 1;
> #X connect 6 0 8 1;
> #X connect 7 0 8 0;
> #X connect 8 0 4 0; 

Use the source
-------------- next part --------------
A non-text attachment was scrubbed...
Name: oscil-basics.pd
Type: application/octet-stream
Size: 22397 bytes
Desc: not available
URL: <http://lists.puredata.info/pipermail/pd-list/attachments/20090207/c1633242/attachment.obj>

More information about the Pd-list mailing list