Skip to content

Redundant per-sample setFrequency calls with unnecessary division #15

@user1303836

Description

@user1303836

Problem

oscillator.setFrequency() is called every sample in both pitch-tracking and manual modes (source/PluginProcessor.cpp:137,143). Each call triggers updateIncrement() which performs a floating-point division (freq / sr) (source/dsp/Oscillator.cpp:12-16,52).

In pitch-tracking mode, the pitch detector only updates its result every ~4096-8192 input samples, so the frequency is identical for thousands of consecutive samples. In manual mode, the frequency is constant for the entire block. This wastes ~48K-88K divisions/sec.

Additionally, in manual mode, oscillator.setWaveform() is also called every sample (PluginProcessor.cpp:142) despite the waveform being constant for the block.

Corroborated by: 6/8 audit agents (dsp-algorithm, pitch-detection, param-state, vst3-practices, ring-mod-research, perf-optimizer)

Suggested Fix

Quick fix -- cache last frequency in setFrequency():

void Oscillator::setFrequency(float hz) {
    if (hz != freq) {
        freq = hz;
        updateIncrement();
    }
}

Better fix -- restructure processBlock:

  • Manual mode: move setFrequency and setWaveform outside the per-sample loop
  • Pitch-tracking mode: only update frequency when the pitch detector produces a new result (flag-based)

Impact

  • Performance: Eliminates ~99.9% of redundant divisions (~720K-960K cycles/sec saved)
  • Severity: Medium -- easy fix with measurable impact

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions