为给定频率生成可循环的正弦波周期

信息处理 海浪 信号合成 振荡器
2022-02-08 05:44:35

我对 DSP 有点陌生,所以对我来说很陌生。我正在研究一个简单的波表振荡器。我要做的是为每个音符(频率)生成一个波形周期,并将其存储在一个数组中以供以后播放。我知道我可以生成一个频率,将其存储并实时重新采样到其他频率,但我正在寻找性能并且我仍在学习,所以我现在尽量保持简单。

在我的第一次尝试中,我能够在每个频率上生成一个正弦波周期,但是当我播放存储的波形时,频率偏离了 0.5 - 0.10 赫兹或更多,并且在循环重复时有明显的咔哒声. 我知道这是因为波形的开始和结束没有在 0 上对齐。我一直在努力解决这个问题。

下面是我用来生成和存储正弦波的最新 C# 代码。这将产生更多的周期,但似乎解决了我在生成一个周期时得到的赫兹方差。剩下的唯一问题是循环返回时的点击。我可能会完全错误地解决这个问题,所以任何建议都将不胜感激。

double frequency = 440.0; //A4
double sampleRate = 44100;
double numSamples = sampleRate / frequency;
double phase = frequency / sampleRate;

int j = 0;
for (double i = 0.0; i < numSamples; i += phase)
{
    double sample = Math.Sin(i * 2 * Math.PI);

    sineWaveTable[j] = sample;

    j++;
}

我不确定是否甚至可以为每个音符生成一个正弦波周期并让它在 0 开始和停止。如果没有,我是否坚持必须使用重新采样来获得其他所需的音符?

1个回答

您的点击来自两个来源。波表和硬件。

如果你想创建一个简单的小乐器,通过回放波表来产生音调,那么没有办法固定“回放窗口”的大小来重现音调而无需点击。

组成半音阶的频率遵循几何级数,以 12 步实现频率加倍。每个音调的频率是通过将前一个音调乘以 1.05 来产生的。该因素由以下公式计算得出:让我们采用及其在处的八度音程。每个音调都是,所以但是我们知道因此,AF=440HzAO=880HzAn+1=AnrAO=AFr12AO=AF2r12=2r1.059463094359

因此,您可以将整齐地放入波表中,但现在需要个样本才能整齐地放入。不仅那里没有整数,而且即使您可以在整洁的窗口中重现音调,您也会遇到节奏问题,乐曲中每个音符的持续时间,因为短。AF,AOAF1.0594AFAF

解决此问题的“经典”方法是设置单个正弦波的高分辨率波表,然后以“不同速度”读回,并带有插值。因此,速度读回(实际上没有插值),但速度读回,当“针”必须落在已知样本。AFr0=1AFr11.0594

但!,这与你的输出流无关换句话说,您必须设置(或采用)一个流系统,其中样本不断被推送到声卡,并且您具有“全局”时间感。

曾几何时,您通过设置三个指向三个缓冲区的指针(在 C、C++ 中)来做到这一点。我们称它们为您将声卡设置为在中播放,在此过程中,您的主要代码正在处理缓冲区当声卡调用其回调以表示录制结束时,您将“循环切换”缓冲区,以便它们现在指向并重新设置声音卡来做同样的工作,而你现在正在处理,现在是你新录制的H,D,LHLDLD,DH,HsilenceDH. 这些缓冲区有一个长度,例如 1000 个样本,然后任务变成了找到一个平衡缓冲区长度和响应性的最佳点。

但是正如你所看到的,在这个系统中,样本被连续不断地推送到声卡中。bufferLength样本,您并不真正关心正在播放的内容是否适合缓冲区。您所做的就是迭代您的模型(例如波表),生成样本缓冲区,冻结模型,播放该缓冲区并从顶部再次移动。

现在,显然,上述内容也包括来自音频源的实时输入。如果你所做的只是一个很小的合成器,你可以有两个缓冲区并在它们之间切换,在播放另一个的同时处理一个。

但是,即使您使用市场上一些现成的廉价声卡执行此操作,您仍然可以获得点击,尽管您已经非常努力地完美对齐块之间的零这是因为所谓的延迟

换句话说,只是因为你的程序调用了一些操作系统应用程序编程接口函数,上面写着“现在记录!” (或“立即播放!),这并不意味着此命令将通过驱动程序传播,最终音频硬件和录音将开始NOW。录音(和播放)将开始一些NOW!+latency单位时间后和现成的声卡,这曾经是一个可怕的时间。太可怕了,你可以听到通话之间的沉默。

所以,那里的解决方案是转移到像ASIO这样的东西,它最终将整个工作流程打包成一个完整的解决方案,从软件调用到硬件。

例如,一个 8 轨外部声卡可以在 256 个样本的缓冲区上进行 48kHz 立体声播放/录制(绝对没有咔嗒声)。这意味着,声音在持续大约 5 毫秒的块中进行处理。当它们分开超过 40 毫秒时,人耳开始分辨声音,所以这 5 毫秒是非常安全的。这意味着我们可以将电子乐器插入声卡并对其进行实时处理,就像它通过效果盒一样,表演者不会注意到他们演奏的内容和听到的内容之间的任何差异。

如果你试图让H,D,L256 的大小并尝试用现成的(相对流行的)声卡做同样的事情,首先你会 g/et//an/awf/ul/am//ount/of/cli/k/s //(每 5 毫秒一个)其次,驱动程序和操作系统会被大量的函数调用所淹没,很快您就会遇到 Seg Faults、蓝屏、系统冻结、repreprepreprepreprepreppreprepreprepreprepreprepreprepreprepreprepreprepreprepreprepeated waves out of synsynsynsynsynsynsynsynsynsynreprepresync 和其他有趣的副作用。

因此,最重要的是,继续在合成器的 DSP 方面工作,但如果您真的想摆脱咔嗒声,请确保您的声音硬件也能胜任这项任务。

希望这可以帮助。