Extra samples in the wavetables, to help interpolations
This commit is contained in:
parent
62ba2113c7
commit
c57ab54c24
2 changed files with 42 additions and 7 deletions
|
|
@ -143,17 +143,18 @@ WavetableRange WavetableRange::getRangeForFrequency(float f)
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
constexpr unsigned WavetableMulti::_tableExtra;
|
||||||
|
|
||||||
WavetableMulti WavetableMulti::createForHarmonicProfile(
|
WavetableMulti WavetableMulti::createForHarmonicProfile(
|
||||||
const HarmonicProfile& hp, unsigned tableSize, double refSampleRate)
|
const HarmonicProfile& hp, unsigned tableSize, double refSampleRate)
|
||||||
{
|
{
|
||||||
WavetableMulti wm;
|
WavetableMulti wm;
|
||||||
constexpr unsigned multiSize = wm.multiSize();
|
constexpr unsigned multiSize = WavetableMulti::multiSize();
|
||||||
|
|
||||||
// amplitude to match ARIA's default generator output
|
// amplitude to match ARIA's default generator output
|
||||||
constexpr double amplitude = 0.25;
|
constexpr double amplitude = 0.25;
|
||||||
|
|
||||||
wm._tableSize = tableSize;
|
wm.allocateStorage(tableSize);
|
||||||
wm._multiData.reset(new float[tableSize * multiSize]);
|
|
||||||
|
|
||||||
for (unsigned m = 0; m < multiSize; ++m) {
|
for (unsigned m = 0; m < multiSize; ++m) {
|
||||||
WavetableRange range = WavetableRange::getRangeForOctave(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).
|
// 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;
|
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);
|
absl::Span<float> table(ptr, tableSize);
|
||||||
|
|
||||||
hp.generate(table, amplitude, cutoff);
|
hp.generate(table, amplitude, cutoff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wm.fillExtra();
|
||||||
|
|
||||||
return wm;
|
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
|
} // namespace sfz
|
||||||
|
|
|
||||||
|
|
@ -86,9 +86,7 @@ public:
|
||||||
// get the N-th table in the multisample
|
// get the N-th table in the multisample
|
||||||
absl::Span<const float> getTable(unsigned index) const
|
absl::Span<const float> getTable(unsigned index) const
|
||||||
{
|
{
|
||||||
unsigned size = _tableSize;
|
return { getTablePointer(index), _tableSize };
|
||||||
const float* ptr = &_multiData[index * _tableSize];
|
|
||||||
return { ptr, size };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the table which is adequate for a given playback frequency
|
// 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);
|
const HarmonicProfile& hp, unsigned tableSize, double refSampleRate = 44100.0);
|
||||||
|
|
||||||
private:
|
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
|
// length of each individual table of the multisample
|
||||||
unsigned _tableSize = 0;
|
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.
|
// internal storage, having `multiSize` rows and `tableSize` columns.
|
||||||
std::unique_ptr<float[]> _multiData;
|
std::unique_ptr<float[]> _multiData;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue