Extra samples in the wavetables, to help interpolations

This commit is contained in:
Jean Pierre Cimalando 2020-02-14 01:20:05 +01:00 committed by Paul Fd
parent 62ba2113c7
commit c57ab54c24
2 changed files with 42 additions and 7 deletions

View file

@ -143,17 +143,18 @@ WavetableRange WavetableRange::getRangeForFrequency(float f)
}
//------------------------------------------------------------------------------
constexpr unsigned WavetableMulti::_tableExtra;
WavetableMulti WavetableMulti::createForHarmonicProfile(
const HarmonicProfile& hp, unsigned tableSize, double refSampleRate)
{
WavetableMulti wm;
constexpr unsigned multiSize = wm.multiSize();
constexpr unsigned multiSize = WavetableMulti::multiSize();
// amplitude to match ARIA's default generator output
constexpr double amplitude = 0.25;
wm._tableSize = tableSize;
wm._multiData.reset(new float[tableSize * multiSize]);
wm.allocateStorage(tableSize);
for (unsigned m = 0; m < multiSize; ++m) {
WavetableRange range = WavetableRange::getRangeForOctave(m);
@ -165,13 +166,34 @@ WavetableMulti WavetableMulti::createForHarmonicProfile(
// Therefore it's desired to cut harmonics at C=0.5*Fs/Fs'=0.5*Fs/(F*N).
double cutoff = (0.5 * refSampleRate / tableSize) / freq;
float* ptr = &wm._multiData[m * tableSize];
float* ptr = const_cast<float*>(wm.getTablePointer(m));
absl::Span<float> table(ptr, tableSize);
hp.generate(table, amplitude, cutoff);
}
wm.fillExtra();
return wm;
}
void WavetableMulti::allocateStorage(unsigned tableSize)
{
_multiData.reset(new float[(tableSize + _tableExtra) * multiSize()]());
_tableSize = tableSize;
}
void WavetableMulti::fillExtra()
{
unsigned tableSize = _tableSize;
constexpr unsigned tableExtra = _tableExtra;
constexpr unsigned multiSize = WavetableMulti::multiSize();
for (unsigned m = 0; m < multiSize; ++m) {
float* ptr = const_cast<float*>(getTablePointer(m));
for (unsigned i = 0; i < tableExtra; ++i)
ptr[tableSize + i] = ptr[i % tableSize];
}
}
} // namespace sfz

View file

@ -86,9 +86,7 @@ public:
// get the N-th table in the multisample
absl::Span<const float> getTable(unsigned index) const
{
unsigned size = _tableSize;
const float* ptr = &_multiData[index * _tableSize];
return { ptr, size };
return { getTablePointer(index), _tableSize };
}
// get the table which is adequate for a given playback frequency
@ -104,9 +102,24 @@ public:
const HarmonicProfile& hp, unsigned tableSize, double refSampleRate = 44100.0);
private:
// get a pointer to the beginning of the N-th table
const float* getTablePointer(unsigned index) const
{
return &_multiData[index * (_tableSize + _tableExtra)];
}
// allocate the internal data for tables of the given size
void allocateStorage(unsigned tableSize);
// fill extra data at table ends with repetitions of the first samples
void fillExtra();
// length of each individual table of the multisample
unsigned _tableSize = 0;
// number X of extra elements, for safe interpolations up to X-th order.
static constexpr unsigned _tableExtra = 4;
// internal storage, having `multiSize` rows and `tableSize` columns.
std::unique_ptr<float[]> _multiData;
};