Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 简单VST合成器以随机间隔改变音高_C++_Audio_Vst - Fatal编程技术网

C++ 简单VST合成器以随机间隔改变音高

C++ 简单VST合成器以随机间隔改变音高,c++,audio,vst,C++,Audio,Vst,我正在学习如何使用Steinberg VST 2.4 SDK,或者更确切地说,3.6.0版本附带的2.x部分。我发明了一个简单的合成器,可以在其使用寿命内以恒定频率播放正弦波。以下是此合成器的代码: static const float TAU = 3.14159f * 2; AudioEffect* createEffectInstance(audioMasterCallback audioMaster) { return new VSTTest(audioMaster); } V

我正在学习如何使用Steinberg VST 2.4 SDK,或者更确切地说,3.6.0版本附带的2.x部分。我发明了一个简单的合成器,可以在其使用寿命内以恒定频率播放正弦波。以下是此合成器的代码:

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;
}

问题是,当VST作为FL Studio中的一个频道加载时,我可以听到和看到它在大约20秒内改变音高几次,直到最终音高稳定下来,甚至偏离约10 Hz。为什么会发生这种情况?

您正在向FPO添加一个巨大的数字,它应该增加1。您正在寻找的公式是:

sinf(2.0 * M_PI * fPos++ * fFrequency / fSampleRate);

这并不是一个完整的答案,但这是通过计算简历中的增量时间来解决的

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

我不确定为什么需要这样做,或者它是如何解决问题的,但确实如此。另外,我应该注意,fdelatime不应该在构造函数中初始化,因为当时无法保证getSampleRate是正确的。

这个算法不是很好,因为改变音高时会发生单击。你应该使用一个代表波的相位的浮点数,而不是计数样本。这样,当频率增加时,您会考虑上一个频率的相位,以便波不会在X/Y方向上突然从一个位置跳到另一个位置。这就是fPos的用途。我知道这里的频率应该是常数,但不管怎样,这并不能真正解释频率的变化-我用一个运行时常数来增加FPO。算法不会导致点击,或者至少不会,原始代码在这里:这是我很久以前写的一个synth,它也使用音高修改,修改音高时不会点击。这里有一个关于这个的问题。我忘了它到底在哪里了——谷歌没有发现任何东西。但是,想象一下,在一个样本中,你从100赫兹跳到107赫兹。这样做会给你一个X值,就好像整个时间的频率都是107赫兹——相位可能会向前跳一整π,这肯定会引起一些点击。也就是说,如果fPos为100,则会从~1.42的相位跳到~1.54,而不是从~1.42平滑跳到~1.44(如果考虑到前一个相位)。