Add the opcode sample_quality and default value to 2
This commit is contained in:
parent
51502eaed3
commit
4ff54b3158
6 changed files with 72 additions and 20 deletions
|
|
@ -246,7 +246,7 @@ public:
|
|||
* @param channelIndex the channel
|
||||
* @return absl::Span<const Type>
|
||||
*/
|
||||
absl::Span<const Type> getConstSpan(size_t channelIndex)
|
||||
absl::Span<const Type> getConstSpan(size_t channelIndex) const
|
||||
{
|
||||
ASSERT(channelIndex < numChannels);
|
||||
if (channelIndex < numChannels)
|
||||
|
|
@ -382,7 +382,7 @@ public:
|
|||
*
|
||||
* @returns size_type the number of frames in the AudioSpan
|
||||
*/
|
||||
size_type getNumFrames()
|
||||
size_type getNumFrames() const
|
||||
{
|
||||
return numFrames;
|
||||
}
|
||||
|
|
@ -392,7 +392,7 @@ public:
|
|||
*
|
||||
* @returns size_type the number of channels in the AudioSpan
|
||||
*/
|
||||
size_t getNumChannels()
|
||||
size_t getNumChannels() const
|
||||
{
|
||||
return numChannels;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -221,6 +221,9 @@ namespace Default
|
|||
constexpr Range<float> egOnCCPercentRange { -100.0, 100.0 };
|
||||
|
||||
// ***** SFZ v2 ********
|
||||
constexpr int sampleQuality { 2 };
|
||||
constexpr Range<int> sampleQualityRange { 1, 10 }; // sample_quality
|
||||
|
||||
constexpr bool checkSustain { true }; // sustain_sw
|
||||
constexpr bool checkSostenuto { true }; // sostenuto_sw
|
||||
constexpr Range<int> octaveOffsetRange { -10, 10 }; // octave_offset
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
|
|||
sampleId = FileId(std::move(filename), sampleId.isReverse());
|
||||
}
|
||||
break;
|
||||
case hash("sample_quality"):
|
||||
{
|
||||
setValueFromOpcode(opcode, sampleQuality, Default::sampleQualityRange);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case hash("direction"):
|
||||
sampleId = sampleId.reversed(opcode.value == "reverse");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ struct Region {
|
|||
|
||||
// Sound source: sample playback
|
||||
FileId sampleId {}; // Sample
|
||||
int sampleQuality { Default::sampleQuality };
|
||||
float delay { Default::delay }; // delay
|
||||
float delayRandom { Default::delayRandom }; // delay_random
|
||||
int64_t offset { Default::offset }; // offset
|
||||
|
|
|
|||
|
|
@ -506,23 +506,25 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
auto ind = indices->data();
|
||||
auto coeff = coeffs->data();
|
||||
auto leftSource = source.getConstSpan(0);
|
||||
auto left = buffer.getChannel(0);
|
||||
if (source.getNumChannels() == 1) {
|
||||
while (ind < indices->end()) {
|
||||
*left = interpolate<kInterpolatorBspline3>(&leftSource[*ind], *coeff);
|
||||
incrementAll(ind, left, coeff);
|
||||
}
|
||||
} else {
|
||||
auto right = buffer.getChannel(1);
|
||||
auto rightSource = source.getConstSpan(1);
|
||||
while (ind < indices->end()) {
|
||||
*left = interpolate<kInterpolatorBspline3>(&leftSource[*ind], *coeff);
|
||||
*right = interpolate<kInterpolatorBspline3>(&rightSource[*ind], *coeff);
|
||||
incrementAll(ind, left, right, coeff);
|
||||
}
|
||||
const int quality = region->sampleQuality;
|
||||
|
||||
switch (quality) {
|
||||
default:
|
||||
if (quality > 2)
|
||||
goto high; // TODO sinc, not implemented
|
||||
// fall through
|
||||
case 1:
|
||||
fillInterpolated<kInterpolatorLinear>(source, buffer, *indices, *coeffs);
|
||||
break;
|
||||
case 2: high:
|
||||
#if 1
|
||||
// B-spline response has faster decay of aliasing, but not zero-crossings at integer positions
|
||||
fillInterpolated<kInterpolatorBspline3>(source, buffer, *indices, *coeffs);
|
||||
#else
|
||||
// Hermite polynomial
|
||||
fillInterpolated<kInterpolatorHermite3>(source, buffer, *indices, *coeffs);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
sourcePosition = indices->back();
|
||||
|
|
@ -536,6 +538,31 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
|
|||
#endif
|
||||
}
|
||||
|
||||
template <sfz::InterpolatorModel M>
|
||||
void sfz::Voice::fillInterpolated(
|
||||
const sfz::AudioSpan<const float>& source, sfz::AudioSpan<float>& dest,
|
||||
absl::Span<const int> indices, absl::Span<const float> coeffs)
|
||||
{
|
||||
auto ind = indices.data();
|
||||
auto coeff = coeffs.data();
|
||||
auto leftSource = source.getConstSpan(0);
|
||||
auto left = dest.getChannel(0);
|
||||
if (source.getNumChannels() == 1) {
|
||||
while (ind < indices.end()) {
|
||||
*left = sfz::interpolate<M>(&leftSource[*ind], *coeff);
|
||||
incrementAll(ind, left, coeff);
|
||||
}
|
||||
} else {
|
||||
auto right = dest.getChannel(1);
|
||||
auto rightSource = source.getConstSpan(1);
|
||||
while (ind < indices.end()) {
|
||||
*left = sfz::interpolate<M>(&leftSource[*ind], *coeff);
|
||||
*right = sfz::interpolate<M>(&rightSource[*ind], *coeff);
|
||||
incrementAll(ind, left, right, coeff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sfz::Voice::fillWithGenerator(AudioSpan<float> buffer) noexcept
|
||||
{
|
||||
const auto leftSpan = buffer.getSpan(0);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <random>
|
||||
|
||||
namespace sfz {
|
||||
enum InterpolatorModel : int;
|
||||
/**
|
||||
* @brief The SFZ voice are the polyphony holders. They get activated by the synth
|
||||
* and tasked to play a given region until the end, stopping on note-offs, off-groups
|
||||
|
|
@ -242,6 +243,20 @@ private:
|
|||
* @param buffer
|
||||
*/
|
||||
void fillWithGenerator(AudioSpan<float> buffer) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Fill a destination with an interpolated source.
|
||||
*
|
||||
* @param source the source sample
|
||||
* @param dest the destination buffer
|
||||
* @param indices the integral parts of the source positions
|
||||
* @param coeffs the fractional parts of the source positions
|
||||
*/
|
||||
template <sfz::InterpolatorModel M>
|
||||
static void fillInterpolated(
|
||||
const sfz::AudioSpan<const float>& source, sfz::AudioSpan<float>& dest,
|
||||
absl::Span<const int> indices, absl::Span<const float> coeffs);
|
||||
|
||||
void amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept;
|
||||
void ampStageMono(AudioSpan<float> buffer) noexcept;
|
||||
void ampStageStereo(AudioSpan<float> buffer) noexcept;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue