Add a lookup table for wavetable octaves
This commit is contained in:
parent
a4f43cabd0
commit
4acb4cd7f7
3 changed files with 50 additions and 0 deletions
|
|
@ -200,6 +200,39 @@ unsigned WavetableRange::getOctaveForFrequency(float f)
|
|||
return clamp<int>(oct, 0, countOctaves - 1);
|
||||
}
|
||||
|
||||
static const auto octaveForFrequencyTable = []()
|
||||
{
|
||||
static constexpr unsigned N = 1024;
|
||||
std::array<float, N> table;
|
||||
|
||||
constexpr double fmin = 1 / WavetableRange::frequencyScaleFactor;
|
||||
constexpr double fmax = (1 << (WavetableRange::countOctaves - 1)) / WavetableRange::frequencyScaleFactor;
|
||||
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
double f = fmin + (i * (1.0 / (N - 1))) * (fmax - fmin);
|
||||
table[i] = std::log2(f * WavetableRange::frequencyScaleFactor);
|
||||
}
|
||||
|
||||
return table;
|
||||
}();
|
||||
|
||||
float WavetableRange::getFractionalOctaveForFrequency(float f)
|
||||
{
|
||||
static constexpr unsigned N = octaveForFrequencyTable.size();
|
||||
|
||||
constexpr double fmin = 1 / WavetableRange::frequencyScaleFactor;
|
||||
constexpr double fmax = (1 << (WavetableRange::countOctaves - 1)) / WavetableRange::frequencyScaleFactor;
|
||||
|
||||
float pos = (f - fmin) * ((N - 1) / static_cast<float>(fmax - fmin));
|
||||
int index1 = static_cast<int>(pos);
|
||||
float frac = pos - index1;
|
||||
index1 = clamp<int>(index1, 0, N - 1);
|
||||
int index2 = std::min<int>(index1 + 1, N - 1);
|
||||
|
||||
return (1.0f - frac) * octaveForFrequencyTable[index1] +
|
||||
frac * octaveForFrequencyTable[index2];
|
||||
}
|
||||
|
||||
WavetableRange WavetableRange::getRangeForOctave(int o)
|
||||
{
|
||||
WavetableRange range;
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ public:
|
|||
static constexpr float frequencyScaleFactor = 0.05;
|
||||
|
||||
static unsigned getOctaveForFrequency(float f);
|
||||
static float getFractionalOctaveForFrequency(float f);
|
||||
static WavetableRange getRangeForOctave(int o);
|
||||
static WavetableRange getRangeForFrequency(float f);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "sfizz/MathHelpers.h"
|
||||
#include "catch2/catch.hpp"
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
TEST_CASE("[Wavetables] Frequency ranges")
|
||||
{
|
||||
|
|
@ -38,3 +39,18 @@ TEST_CASE("[Wavetables] Frequency ranges")
|
|||
REQUIRE(min_oct == 0);
|
||||
REQUIRE(max_oct == sfz::WavetableRange::countOctaves - 1);
|
||||
}
|
||||
|
||||
TEST_CASE("[Wavetables] Octave number lookup")
|
||||
{
|
||||
for (int note = 0; note < 128; ++note) {
|
||||
double f = midiNoteFrequency(note);
|
||||
|
||||
float ref = std::log2(f * sfz::WavetableRange::frequencyScaleFactor);
|
||||
float oct = sfz::WavetableRange::getFractionalOctaveForFrequency(f);
|
||||
|
||||
ref = clamp<float>(ref, 0, sfz::WavetableRange::countOctaves - 1);
|
||||
oct = clamp<float>(oct, 0, sfz::WavetableRange::countOctaves - 1);
|
||||
|
||||
REQUIRE(oct == Approx(ref).margin(0.03f));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue