これは私が思いついたもので、ニルスのアイデアに触発されました。他の人に役立つ場合に備えて、ここに貼り付けます。最後のサンプルからの位相の変化をカーネルサイズ(またはカットオフ)として使用して、のこぎり波を分析的にボックスフィルター処理するだけです。それはかなりうまく機能し、非常に高い音にいくつかの可聴エイリアシングがありますが、通常の使用法では素晴らしい音になります。
エイリアシングをさらに減らすには、カーネルサイズを少し大きくして、たとえば2 * phaseChangeにすることもできますが、最高周波数が少し失われます。
また、SPを参照して同様のトピックを探したときに見つけたもう1つの優れたDSPリソースは次のとおりです。C++のSynthesis ToolKit(STK)。これは、便利なDSPツールがたくさんあるクラスライブラリです。帯域制限された波形ジェネレーターを使用する準備もできています。彼らが使用する方法は、私が最初の投稿で説明したようにsincを統合することです(私よりもうまくいくと思いますが...)。
float getSaw(float phaseChange)
{
static float phase = 0.0f;
phase = fmod(phase + phaseChange, 1.0f);
return getBoxFilteredSaw(phase, phaseChange);
}
float getPulse(float phaseChange, float pulseWidth)
{
static float phase = 0.0f;
phase = fmod(phase + phaseChange, 1.0f);
return getBoxFilteredSaw(phase, phaseChange) - getBoxFilteredSaw(fmod(phase + pulseWidth, 1.0f), phaseChange);
}
float getBoxFilteredSaw(float phase, float kernelSize)
{
float a, b;
// Check if kernel is longer that one cycle
if (kernelSize >= 1.0f) {
return 0.0f;
}
// Remap phase and kernelSize from [0.0, 1.0] to [-1.0, 1.0]
kernelSize *= 2.0f;
phase = phase * 2.0f - 1.0f;
if (phase + kernelSize > 1.0f)
{
// Kernel wraps around edge of [-1.0, 1.0]
a = phase;
b = phase + kernelSize - 2.0f;
}
else
{
// Kernel fits nicely in [-1.0, 1.0]
a = phase;
b = phase + kernelSize;
}
// Integrate and divide with kernelSize
return (b * b - a * a) / (2.0f * kernelSize);
}