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