Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::signal::osc::VaOscillator Class Reference

Virtual-analog oscillator over the static shapes. More...

#include <va.hpp>

Public Member Functions

void set_shape (VaShape shape) noexcept
VaShape shape () const noexcept
void set_pulse_width (double width) noexcept
 Fraction of the period the square spends high, clamped to [0, 1].
double pulse_width () const noexcept
void reset (double phase=0.0) noexcept
 Set the phase and drop any pending correction.
double phase () const noexcept
 Current phase, in [0, 1).
double next (double increment) noexcept
 Generate one sample and advance by increment cycles.
double next_synced (double increment, double sync_frac, double sync_phase=0.0) noexcept
 Generate one sample, advancing by increment but forcing the phase to sync_phase at sub-sample position sync_frac — a hard sync.

Detailed Description

Virtual-analog oscillator over the static shapes.

Member Function Documentation

◆ next()

double pulp::signal::osc::VaOscillator::next ( double increment)
inlinenoexcept

Generate one sample and advance by increment cycles.

The returned sample is the shape at the phase on entry, so the advance spans from this sample to the next one, and a discontinuity inside that span owes its before term to this sample and its after term to the next. That is the whole reason the increment is read here rather than held: the span this call corrects is defined by the increment this call was given.

◆ next_synced()

double pulp::signal::osc::VaOscillator::next_synced ( double increment,
double sync_frac,
double sync_phase = 0.0 )
inlinenoexcept

Generate one sample, advancing by increment but forcing the phase to sync_phase at sub-sample position sync_frac — a hard sync.

Call this only on the samples where a sync actually fires. It emits a sync event unconditionally, including a zero-magnitude one when the target equals the phase it replaces, so calling it every sample would report a sync every sample. The zero-magnitude case costs nothing (the corrector skips a zero step) but the intent would be wrong.

The reset is a value step of ARBITRARY magnitude, unlike a wrap's known 1 -> 0. That magnitude is read off the event's endpoints rather than assumed, which is the same path a wrap takes — see correct_events.

◆ phase()

double pulp::signal::osc::VaOscillator::phase ( ) const
inlinenoexcept

Current phase, in [0, 1).

◆ pulse_width()

double pulp::signal::osc::VaOscillator::pulse_width ( ) const
inlinenoexcept

◆ reset()

void pulp::signal::osc::VaOscillator::reset ( double phase = 0.0)
inlinenoexcept

Set the phase and drop any pending correction.

◆ set_pulse_width()

void pulp::signal::osc::VaOscillator::set_pulse_width ( double width)
inlinenoexcept

Fraction of the period the square spends high, clamped to [0, 1].

A width of exactly 0 or 1 leaves no edge and the square degenerates to DC, which is the honest limit of the shape rather than an error.

Widths narrower than one sample cannot be represented: the pulse's two edges land inside one sample period, their corrections overlap, and the result is a bounded but inaccurate pulse. That is polyBLEP's limit, not a bug to fix here — the output stays finite and bounded, which is what test_osc_va.cpp pins.

◆ set_shape()

void pulp::signal::osc::VaOscillator::set_shape ( VaShape shape)
inlinenoexcept

◆ shape()

VaShape pulp::signal::osc::VaOscillator::shape ( ) const
inlinenoexcept

The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/signal/include/pulp/signal/osc/va.hpp