A sine, and a saw
The smallest thing that makes a sound, and the smallest thing that makes an interesting one.
Anyone starting here.
An oscillator does not need incoming audio. It needs a clock and a memory of where it is in its cycle. Every frame it moves a little farther around that cycle and turns its position into a sample.
This example uses a parabolic approximation to a sine. It is a rounded wave made from a ramp, so it contains more harmonics than a mathematical sine. We will use that distinction to hear how a waveform's shape changes its tone.
Controls#
| Parameter | Default | Range | What you hear |
|---|---|---|---|
freq | 220 Hz | 20–8,000 Hz | The number of cycles per second; doubling it raises the pitch one octave. |
level | 0.6 | 0–1 | Output amplitude: 0 is silent and 1 is full level. |
There is no input stream. out is the generated mono signal.
The complete patch#
processor Sine
{
param float freq = 220.0f [20.0f, 8000.0f] smooth 10.0f;
param float level = 0.6f [0.0f, 1.0f] smooth 20.0f;
output stream float out;
float phase = 0.0f;
void main()
{
loop
{
let step = freq / processor.frequency;
let p = phase + step;
phase = p > 1.0f ? p - 1.0f : p;
let t = phase * 2.0f - 1.0f;
let a = t > 0.0f ? t : -t;
out <- 4.0f * t * (1.0f - a) * level;
advance();
}
}
}Follow one frame#
freq / processor.frequencyconverts cycles per second to cycles per frame. At 220 Hz and 48 kHz the step is about 0.00458.phaseadvances and wraps back into one cycle. Because it is processor state, the next frame starts where this one finished.phase * 2.0f - 1.0fconverts a 0…1 phase into a -1…1 ramp, calledt.4.0f * t * (1.0f - abs(t))bends that ramp into the rounded waveform. The patch spells out the absolute value with a conditional.- Multiplication by
levelcontrols amplitude before the sample is written.
The single-subtraction wrap assumes the phase step is less than one cycle. That holds for these frequency settings at common audio sample rates.
Try three waveforms#
Replace the output expression with sin(6.2831853f * phase) * level for a
true sine, or t * level for a saw. The phase machinery stays the same; only
the mapping from position to amplitude changes.
Listen at 220 Hz, then increase the frequency. The saw is brighter because of its harmonics. It is also not band-limited: harmonics above half the sample rate fold back as aliasing. This is a useful learning oscillator, not an alias-free oscillator design.
If it is silent: check that phase is state outside main(). A local
phase reset to zero on each frame never travels around a cycle.
Next: put the saw through the filter.