我正在使用 NAudio 在 C# 中编写一个合成器。我试图让它在频率之间平滑滑动。但是我有一种感觉,我对所涉及的数学不了解。在切换到正确的下一个音高之前,它会以高音疯狂地滑动。
从一个音高滑到另一个音高的数学正确方法是什么?
代码如下:
public override int Read(float[] buffer, int offset, int sampleCount) { int sampleRate = WaveFormat.SampleRate;
for (int n = 0; n < sampleCount; n++)
{
if (nextFrequencyQueue.Count > 0)
{
nextFrequency = nextFrequencyQueue.Dequeue();
}
if (nextFrequency > 0 && Frequency != nextFrequency)
{
if (Frequency == 0) //special case for first note
{
Frequency = nextFrequency;
}
else //slide up or down to next frequency
{
if (Frequency < nextFrequency)
{
Frequency = Clamp(Frequency + frequencyStep, nextFrequency, Frequency);
}
if (Frequency > nextFrequency)
{
Frequency = Clamp(Frequency - frequencyStep, Frequency, nextFrequency);
}
}
}
buffer[n + offset] = (float)(Amplitude * Math.Sin(2 * Math.PI * time * Frequency));
try
{
time += (double)1 / (double)sampleRate;
}
catch
{
time = 0;
}
}
return sampleCount;
}
最佳答案
您使用绝对时间来确定波函数,因此当您稍微改变频率时,下一个样本就是您以新频率开始运行时的样本。
我不知道已建立的最佳方法,但一个可能足够好的简单方法是计算相位 (φ = t mod 1/fold) 并调整 t 以保持相位在新的频率下 (t = φ/fnew).
更平滑的方法是保留一阶导数。这更困难,因为与波本身不同,一阶导数的振幅随频率变化,这意味着仅保留相位是不够的。无论如何,考虑到您平滑地改变频率,这种增加的复杂性几乎肯定是矫枉过正。
关于c# - 合成器从一个频率滑到另一个频率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14035906/