Search code examples
c++audiovst

Simple VST Synth Changes Pitch at Random Intervals


I'm learning how to use the Steinberg VST 2.4 SDK (or rather, the 2.x portion that comes with the 3.6.0 version). I've created a simple synthesizer designed to play a sine wave at a constant frequency during its lifetime. Here is the code for this synth:

static const float TAU = 3.14159f * 2;

AudioEffect* createEffectInstance(audioMasterCallback audioMaster) {
    return new VSTTest(audioMaster);
}

VSTTest::VSTTest(audioMasterCallback audioMaster) : AudioEffectX(audioMaster, 0, NUM_PARAMS), //NUM_PARAMS is 0
                                                    fDeltaTime(1.0f / getSampleRate()), //time per sample (1.0 / 44100, presumably)
                                                    fFrequency(100.0f), //frequency of the wave (100 Hz)
                                                    fAmplitude(0.5f), //amplitude of the wave
                                                    fPos(0.0f) { //position of the wave in the x direction
    setNumInputs(0);
    setNumOutputs(2);
    canProcessReplacing();
    isSynth();
}

VSTTest::~VSTTest(void) {

}

void VSTTest::processReplacing(float** input, float** output, VstInt32 numFrames) {
    for (VstInt32 i = 0; i < numFrames; i++) {
        output[0][i] = fAmplitude * sin(fPos);
        output[1][i] = fAmplitude * sin(fPos);

        fPos += fFrequency * TAU * fDeltaTime;

        if (fPos >= TAU) {
            fPos = fmod(fPos, TAU);
        }
    }
}

void VSTTest::setSampleRate(float fSampleRate) {
    fDeltaTime = 1.0f / fSampleRate;
}

The problem is that when the VST is loaded as a channel in FL Studio, I can hear (and see) it changing pitch a couple of times over about 20 seconds until it settles on a final pitch that isn't even correct (deviates by about 10 Hz). Why is this happening?


Solution

  • Well this isn't exactly a complete answer, but this was solved by calculating the delta time in resume().

    void VSTTest::resume(void) {
        fDeltaTime = 1.0 / getSampleRate();
    }
    

    I'm not sure why this needs to be done or how it solves the problem, but it does. Also, I should note that fDeltaTime should not be initialized in the constructor since there's no guarantee getSampleRate() is correct at that time.