Osc
An oscillator in [-1, 1], one channel per channel of `pitch`.
out
- Type name
audio:Osc- Plane
audio- Tags
generator- Language
rust- Tier
native- Bundle
audio- Source
node-bundles/audio/Osc.rs- Availability
- available
Slots
| Slot | Direction | Type | |
|---|---|---|---|
out | output | AUDIO |
Parameters
osc
| Name | Type | Default | Range | Doc |
|---|---|---|---|---|
pitch | float | 0.75 | -10 … 10 | volts per octave, 0 at C4 (0.75 is A4); an audio reference is one voice per channel |
waveform | string | sine | sine | triangle | sawtooth | square | the shape one cycle traces, from the roundest to the brightest |
Source
The current source of this node, as it stands in the goofi repository at node-bundles/audio/Osc.rs.
use goofi_audio_sdk::goofi_core::SlotType;
use goofi_audio_sdk::{hz_of, AudioNode, Block, Manifest, OutputDecl, ParamDecl, ParamSpec, Tag, BLOCK, MAX_CHANNELS};
goofi_audio_sdk::params! {
PITCH = ParamDecl {
group: "osc",
name: "pitch",
spec: ParamSpec::Float { default: 0.75, min: -10.0, max: 10.0 },
expression: None,
doc: Some("volts per octave, 0 at C4 (0.75 is A4); an audio reference is one voice per channel"),
},
WAVEFORM = ParamDecl {
group: "osc",
name: "waveform",
spec: ParamSpec::Str {
default: "sine",
options: &["sine", "triangle", "sawtooth", "square"],
refresh: false,
},
expression: None,
doc: Some("the shape one cycle traces, from the roundest to the brightest"),
},
}
static OUTS: &[OutputDecl] = &[OutputDecl { name: "out", kind: SlotType::Audio }];
static MANIFEST: Manifest = Manifest {
tags: &[Tag::Generator],
doc: "An oscillator in [-1, 1], one channel per channel of `pitch`.",
inputs: &[],
outputs: OUTS,
params: PARAMS,
};
#[derive(Default)]
struct Osc {
phase: [f32; MAX_CHANNELS as usize],
step: f32,
}
impl AudioNode for Osc {
fn prepare(&mut self, rate: f64) {
self.step = 1.0 / rate as f32;
}
fn process(&mut self, b: &mut Block<'_>) {
let pitch = &b.params[P::PITCH];
let waveform = b.params[P::WAVEFORM].chan(0)[0] as u8;
let out = &mut b.outs[0];
for c in 0..out.channels() as usize {
let p = pitch.chan(c);
let phase = &mut self.phase[c];
let samples = out.chan_mut(c);
for i in 0..BLOCK {
samples[i] = match waveform {
1 => 1.0 - 4.0 * (*phase - 0.5).abs(),
2 => 2.0 * *phase - 1.0,
3 => if *phase < 0.5 { 1.0 } else { -1.0 },
_ => (std::f32::consts::TAU * *phase).sin(),
};
*phase = (*phase + hz_of(p[i]) * self.step).fract();
}
}
}
}
goofi_audio_sdk::export!(Osc, MANIFEST);This reference describes goofi 3.1.0(537cd394), generated from a running instance on 2026-09-06.