Merge pull request #338 from jpcima/mm+lfo

LFO
This commit is contained in:
JP Cimalando 2020-08-13 13:40:07 +02:00 committed by GitHub
commit 09341723c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 2997 additions and 1 deletions

4
dpf.mk
View file

@ -1,3 +1,4 @@
# #
# A build file to help using sfizz with the DISTRHO Plugin Framework (DPF) # A build file to help using sfizz with the DISTRHO Plugin Framework (DPF)
# ------------------------------------------------------------------------ # ------------------------------------------------------------------------
@ -65,6 +66,7 @@ SFIZZ_SOURCES = \
src/sfizz/modulations/ModKeyHash.cpp \ src/sfizz/modulations/ModKeyHash.cpp \
src/sfizz/modulations/ModMatrix.cpp \ src/sfizz/modulations/ModMatrix.cpp \
src/sfizz/modulations/sources/Controller.cpp \ src/sfizz/modulations/sources/Controller.cpp \
src/sfizz/modulations/sources/LFO.cpp \
src/sfizz/effects/Compressor.cpp \ src/sfizz/effects/Compressor.cpp \
src/sfizz/effects/Disto.cpp \ src/sfizz/effects/Disto.cpp \
src/sfizz/effects/Eq.cpp \ src/sfizz/effects/Eq.cpp \
@ -91,6 +93,8 @@ SFIZZ_SOURCES = \
src/sfizz/FilterPool.cpp \ src/sfizz/FilterPool.cpp \
src/sfizz/FloatEnvelopes.cpp \ src/sfizz/FloatEnvelopes.cpp \
src/sfizz/Logger.cpp \ src/sfizz/Logger.cpp \
src/sfizz/LFO.cpp \
src/sfizz/LFODescription.cpp \
src/sfizz/MidiState.cpp \ src/sfizz/MidiState.cpp \
src/sfizz/OpcodeCleanup.cpp \ src/sfizz/OpcodeCleanup.cpp \
src/sfizz/Opcode.cpp \ src/sfizz/Opcode.cpp \

View file

@ -35,6 +35,7 @@ set (SFIZZ_HEADERS
sfizz/modulations/ModMatrix.h sfizz/modulations/ModMatrix.h
sfizz/modulations/ModGenerator.h sfizz/modulations/ModGenerator.h
sfizz/modulations/sources/Controller.h sfizz/modulations/sources/Controller.h
sfizz/modulations/sources/LFO.h
sfizz/effects/impl/ResonantArray.h sfizz/effects/impl/ResonantArray.h
sfizz/effects/impl/ResonantArrayAVX.h sfizz/effects/impl/ResonantArrayAVX.h
sfizz/effects/impl/ResonantArraySSE.h sfizz/effects/impl/ResonantArraySSE.h
@ -70,6 +71,8 @@ set (SFIZZ_HEADERS
sfizz/Interpolators.h sfizz/Interpolators.h
sfizz/Interpolators.hpp sfizz/Interpolators.hpp
sfizz/Logger.h sfizz/Logger.h
sfizz/LFO.h
sfizz/LFODescription.h
sfizz/MathHelpers.h sfizz/MathHelpers.h
sfizz/MidiState.h sfizz/MidiState.h
sfizz/ModifierHelpers.h sfizz/ModifierHelpers.h
@ -133,11 +136,14 @@ set (SFIZZ_SOURCES
sfizz/RTSemaphore.cpp sfizz/RTSemaphore.cpp
sfizz/Panning.cpp sfizz/Panning.cpp
sfizz/Effects.cpp sfizz/Effects.cpp
sfizz/LFO.cpp
sfizz/LFODescription.cpp
sfizz/modulations/ModId.cpp sfizz/modulations/ModId.cpp
sfizz/modulations/ModKey.cpp sfizz/modulations/ModKey.cpp
sfizz/modulations/ModKeyHash.cpp sfizz/modulations/ModKeyHash.cpp
sfizz/modulations/ModMatrix.cpp sfizz/modulations/ModMatrix.cpp
sfizz/modulations/sources/Controller.cpp sfizz/modulations/sources/Controller.cpp
sfizz/modulations/sources/LFO.cpp
sfizz/effects/Nothing.cpp sfizz/effects/Nothing.cpp
sfizz/effects/Filter.cpp sfizz/effects/Filter.cpp
sfizz/effects/Eq.cpp sfizz/effects/Eq.cpp

View file

@ -64,6 +64,8 @@ namespace config {
constexpr unsigned int defaultAlignment { 16 }; constexpr unsigned int defaultAlignment { 16 };
constexpr int filtersInPool { maxVoices * 2 }; constexpr int filtersInPool { maxVoices * 2 };
constexpr int excessFileFrames { 8 }; constexpr int excessFileFrames { 8 };
constexpr int maxLFOSubs { 8 };
constexpr int maxLFOSteps { 128 };
/** /**
* @brief The threshold for age stealing. * @brief The threshold for age stealing.
* In percentage of the voice's max age. * In percentage of the voice's max age.

View file

@ -209,6 +209,22 @@ namespace Default
constexpr int bendStep { 1 }; constexpr int bendStep { 1 };
constexpr uint8_t bendSmooth { 0 }; constexpr uint8_t bendSmooth { 0 };
// Modulation: LFO
constexpr int numLFOs { 4 };
constexpr int numLFOSubs { 2 };
constexpr int numLFOSteps { 8 };
constexpr Range<float> lfoFreqRange { 0.0, 100.0 };
constexpr Range<float> lfoPhaseRange { 0.0, 360.0 };
constexpr Range<float> lfoDelayRange { 0.0, 30.0 };
constexpr Range<float> lfoFadeRange { 0.0, 30.0 };
constexpr Range<unsigned> lfoCountRange { 0, 1000 };
constexpr Range<unsigned> lfoStepsRange { 0, static_cast<unsigned>(config::maxLFOSteps) };
constexpr Range<float> lfoStepXRange { -100.0, 100.0 };
constexpr Range<int> lfoWaveRange { 0, 15 };
constexpr Range<float> lfoOffsetRange { -1.0, 1.0 };
constexpr Range<float> lfoRatioRange { 0.0, 100.0 };
constexpr Range<float> lfoScaleRange { 0.0, 1.0 };
// Envelope generators // Envelope generators
constexpr float attack { 0 }; constexpr float attack { 0 };
constexpr float decay { 0 }; constexpr float decay { 0 };

308
src/sfizz/LFO.cpp Normal file
View file

@ -0,0 +1,308 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "LFO.h"
#include "LFODescription.h"
#include "MathHelpers.h"
#include "SIMDHelpers.h"
#include "Config.h"
#include <array>
#include <algorithm>
#include <cmath>
namespace sfz {
struct LFO::Impl {
float sampleRate_ = 0;
// control
const LFODescription* desc_ = nullptr;
// state
size_t delayFramesLeft_ = 0;
float fadePosition_ = 0;
std::array<float, config::maxLFOSubs> subPhases_ {{}};
std::array<float, config::maxLFOSubs> sampleHoldMem_ {{}};
};
LFO::LFO()
: impl_(new Impl)
{
impl_->sampleRate_ = config::defaultSampleRate;
impl_->desc_ = &LFODescription::getDefault();
}
LFO::~LFO()
{
}
void LFO::setSampleRate(double sampleRate)
{
impl_->sampleRate_ = sampleRate;
}
void LFO::configure(const LFODescription* desc)
{
impl_->desc_ = desc ? desc : &LFODescription::getDefault();
}
void LFO::start()
{
Impl& impl = *impl_;
const LFODescription& desc = *impl.desc_;
const float sampleRate = impl.sampleRate_;
impl.subPhases_.fill(desc.phase0);
impl.sampleHoldMem_.fill(0.0f);
const float delay = desc.delay;
impl.delayFramesLeft_ = (delay > 0) ? static_cast<size_t>(std::ceil(sampleRate * delay)) : 0u;
impl.fadePosition_ = (desc.fade > 0) ? 0.0f : 1.0f;
}
template <>
inline float LFO::eval<LFOWave::Triangle>(float phase)
{
float y = -4 * phase + 2;
y = (phase < 0.25f) ? (4 * phase) : y;
y = (phase > 0.75f) ? (4 * phase - 4) : y;
return y;
}
template <>
inline float LFO::eval<LFOWave::Sine>(float phase)
{
float x = phase + phase - 1;
return 4 * x * (1 - std::fabs(x));
}
template <>
inline float LFO::eval<LFOWave::Pulse75>(float phase)
{
return (phase < 0.75f) ? +1.0f : -1.0f;
}
template <>
inline float LFO::eval<LFOWave::Square>(float phase)
{
return (phase < 0.5f) ? +1.0f : -1.0f;
}
template <>
inline float LFO::eval<LFOWave::Pulse25>(float phase)
{
return (phase < 0.25f) ? +1.0f : -1.0f;
}
template <>
inline float LFO::eval<LFOWave::Pulse12_5>(float phase)
{
return (phase < 0.125f) ? +1.0f : -1.0f;
}
template <>
inline float LFO::eval<LFOWave::Ramp>(float phase)
{
return 2 * phase - 1;
}
template <>
inline float LFO::eval<LFOWave::Saw>(float phase)
{
return 1 - 2 * phase;
}
template <LFOWave W>
void LFO::processWave(unsigned nth, absl::Span<float> out)
{
Impl& impl = *impl_;
const LFODescription& desc = *impl.desc_;
const LFODescription::Sub& sub = desc.sub[nth];
const size_t numFrames = out.size();
const float samplePeriod = 1.0f / impl.sampleRate_;
const float baseFreq = desc.freq;
const float offset = sub.offset;
const float ratio = sub.ratio;
const float scale = sub.scale;
float phase = impl.subPhases_[nth];
for (size_t i = 0; i < numFrames; ++i) {
out[i] += offset + scale * eval<W>(phase);
// TODO(jpc) lfoN_count: number of repetitions
float incrPhase = ratio * samplePeriod * baseFreq;
phase += incrPhase;
int numWraps = (int)phase;
phase -= numWraps;
}
impl.subPhases_[nth] = phase;
}
template <LFOWave W>
void LFO::processSH(unsigned nth, absl::Span<float> out)
{
Impl& impl = *impl_;
const LFODescription& desc = *impl.desc_;
const LFODescription::Sub& sub = desc.sub[nth];
const size_t numFrames = out.size();
const float samplePeriod = 1.0f / impl.sampleRate_;
const float baseFreq = desc.freq;
const float offset = sub.offset;
const float ratio = sub.ratio;
const float scale = sub.scale;
float sampleHoldValue = impl.sampleHoldMem_[nth];
float phase = impl.subPhases_[nth];
for (size_t i = 0; i < numFrames; ++i) {
out[i] += offset + scale * sampleHoldValue;
// TODO(jpc) lfoN_count: number of repetitions
float incrPhase = ratio * samplePeriod * baseFreq;
// value updates twice every period
bool updateValue = (int)(phase * 2.0) != (int)((phase + incrPhase) * 2.0);
phase += incrPhase;
int numWraps = (int)phase;
phase -= numWraps;
if (updateValue) {
std::uniform_real_distribution<float> dist(-1.0f, +1.0f);
sampleHoldValue = dist(Random::randomGenerator);
}
}
impl.subPhases_[nth] = phase;
impl.sampleHoldMem_[nth] = sampleHoldValue;
}
void LFO::processSteps(absl::Span<float> out)
{
unsigned nth = 0;
Impl& impl = *impl_;
const LFODescription& desc = *impl.desc_;
const LFODescription::Sub& sub = desc.sub[nth];
const size_t numFrames = out.size();
const LFODescription::StepSequence& seq = *desc.seq;
const float* steps = seq.steps.data();
unsigned numSteps = seq.steps.size();
if (numSteps <= 0)
return;
const float samplePeriod = 1.0f / impl.sampleRate_;
const float baseFreq = desc.freq;
const float offset = sub.offset;
const float ratio = sub.ratio;
const float scale = sub.scale;
float phase = impl.subPhases_[nth];
for (size_t i = 0; i < numFrames; ++i) {
float step = steps[static_cast<int>(phase * numSteps)];
out[i] += offset + scale * step;
// TODO(jpc) lfoN_count: number of repetitions
float incrPhase = ratio * samplePeriod * baseFreq;
phase += incrPhase;
int numWraps = (int)phase;
phase -= numWraps;
}
impl.subPhases_[nth] = phase;
}
void LFO::process(absl::Span<float> out)
{
Impl& impl = *impl_;
const LFODescription& desc = *impl.desc_;
size_t numFrames = out.size();
fill(out, 0.0f);
size_t skipFrames = std::min(numFrames, impl.delayFramesLeft_);
if (skipFrames > 0) {
impl.delayFramesLeft_ -= skipFrames;
out.remove_prefix(skipFrames);
numFrames -= skipFrames;
}
unsigned subno = 0;
const unsigned countSubs = desc.sub.size();
if (countSubs < 1)
return;
if (desc.seq) {
processSteps(out);
++subno;
}
for (; subno < countSubs; ++subno) {
switch (desc.sub[subno].wave) {
case LFOWave::Triangle:
processWave<LFOWave::Triangle>(subno, out);
break;
case LFOWave::Sine:
processWave<LFOWave::Sine>(subno, out);
break;
case LFOWave::Pulse75:
processWave<LFOWave::Pulse75>(subno, out);
break;
case LFOWave::Square:
processWave<LFOWave::Square>(subno, out);
break;
case LFOWave::Pulse25:
processWave<LFOWave::Pulse25>(subno, out);
break;
case LFOWave::Pulse12_5:
processWave<LFOWave::Pulse12_5>(subno, out);
break;
case LFOWave::Ramp:
processWave<LFOWave::Ramp>(subno, out);
break;
case LFOWave::Saw:
processWave<LFOWave::Saw>(subno, out);
break;
case LFOWave::RandomSH:
processSH<LFOWave::RandomSH>(subno, out);
break;
}
}
processFadeIn(out);
}
void LFO::processFadeIn(absl::Span<float> out)
{
Impl& impl = *impl_;
const LFODescription& desc = *impl.desc_;
const float samplePeriod = 1.0f / impl.sampleRate_;
size_t numFrames = out.size();
float fadePosition = impl.fadePosition_;
if (fadePosition >= 1.0f)
return;
const float fadeTime = desc.fade;
const float fadeStep = samplePeriod / fadeTime;
for (size_t i = 0; i < numFrames && fadePosition < 1; ++i) {
out[i] *= fadePosition;
fadePosition = std::min(1.0f, fadePosition + fadeStep);
}
impl.fadePosition_ = fadePosition;
}
} // namespace sfz

117
src/sfizz/LFO.h Normal file
View file

@ -0,0 +1,117 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
#include <absl/types/span.h>
#include <memory>
namespace sfz {
enum class LFOWave : int;
struct LFODescription;
/*
* General
lfoN_freq: Base frequency - Allow modulations at A-rate
lfoN_phase: Initial phase
lfoN_delay: Delay
lfoN_fade: Time to fade-in
lfoN_count: Number of repetitions - not implemented in ARIA
lfoN_steps: Length of the step sequence - 1 to 128
lfoN_steps_onccX: ??? TODO(jpc) seen in Rapture
lfoN_stepX: Value of the Xth step of the sequence - -100% to +100%
lfoN_stepX_onccY: ??? TODO(jpc) check this. override/modulate step in sequence?
note: LFO evaluates between -1 to +1
note: make the step sequencer override the main wave when present.
subwaves are ARIA, step sequencer is Cakewalk, so do our own thing
which makes the most sense.
* Subwaveforms
X: - #1/omitted: the main wave
- #2-#8: a subwave
note: if there are gaps in subwaveforms, these subwaveforms which are gaps
will be initialized and processed.
example: lfo1_ratio4=1.0 // instantiate implicitly the subs #2 and #3
lfoN_wave[X]: Wave
lfoN_offset[X]: DC offset - Add to LFO output; not affected by scale.
lfoN_ratio[X]: Sub ratio - Frequency = (Ratio * Base Frequency)
lfoN_scale[X]: Sub scale - Amplitude of sub
*/
class LFO {
public:
LFO();
~LFO();
/**
Sets the sample rate.
*/
void setSampleRate(double sampleRate);
/**
Attach some control parameters to this LFO.
The control structure is owned by the caller.
*/
void configure(const LFODescription* desc);
/**
Start processing a LFO as a region is triggered.
Prepares the delay, phases, fade-in, etc..
*/
void start();
/**
Process a cycle of the oscillator.
TODO(jpc) frequency modulations
*/
void process(absl::Span<float> out);
private:
/**
Evaluate the wave at a given phase.
Phase must be in the range 0 to 1 excluded.
*/
template <LFOWave W>
static float eval(float phase);
/**
Process the nth subwaveform, adding to the buffer.
This definition is duplicated per each wave, a strategy to avoid a switch
on wave type inside the frame loop.
*/
template <LFOWave W>
void processWave(unsigned nth, absl::Span<float> out);
/**
Process a sample-and-hold subwaveform, adding to the buffer.
*/
template <LFOWave W>
void processSH(unsigned nth, absl::Span<float> out);
/**
Process the step sequencer, adding to the buffer.
*/
void processSteps(absl::Span<float> out);
/**
Process the fade in gain, and apply it to the buffer.
*/
void processFadeIn(absl::Span<float> out);
private:
struct Impl;
std::unique_ptr<Impl> impl_;
};
} // namespace sfz

View file

@ -0,0 +1,31 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "LFODescription.h"
namespace sfz {
LFODescription::LFODescription()
{
sub.resize(1);
}
LFODescription::~LFODescription()
{
}
const LFODescription& LFODescription::getDefault()
{
static LFODescription desc = []() -> LFODescription
{
LFODescription desc;
desc.sub.resize(1);
return desc;
}();
return desc;
}
} // namespace sfz

View file

@ -0,0 +1,48 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
#include <absl/types/optional.h>
#include <vector>
namespace sfz {
enum class LFOWave : int {
Triangle,
Sine,
Pulse75,
Square,
Pulse25,
Pulse12_5,
Ramp,
Saw,
// ARIA extra
RandomSH = 12,
};
struct LFODescription {
LFODescription();
~LFODescription();
static const LFODescription& getDefault();
float freq = 0; // lfoN_freq
float phase0 = 0; // lfoN_phase
float delay = 0; // lfoN_delay
float fade = 0; // lfoN_fade
unsigned count = 0; // lfoN_count
struct Sub {
LFOWave wave = LFOWave::Triangle; // lfoN_wave[X]
float offset = 0; // lfoN_offset[X]
float ratio = 1; // lfoN_ratio[X]
float scale = 1; // lfoN_scale[X]
};
struct StepSequence {
std::vector<float> steps {}; // lfoN_stepX - normalized to unity
};
absl::optional<StepSequence> seq;
std::vector<Sub> sub;
};
} // namespace sfz

View file

@ -823,6 +823,228 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
setValueFromOpcode(opcode, bendSmooth, Default::smoothCCRange); setValueFromOpcode(opcode, bendSmooth, Default::smoothCCRange);
break; break;
// Modulation: LFO
case hash("lfo&_freq"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
setValueFromOpcode(opcode, lfos[lfoNumber - 1].freq, Default::lfoFreqRange);
}
break;
case hash("lfo&_phase"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoPhaseRange)) {
float normalPhase = *value * (1.0 / 360.0);
normalPhase -= int(normalPhase);
normalPhase += (normalPhase < 0) ? 1 : 0;
lfos[lfoNumber - 1].phase0 = normalPhase;
}
}
break;
case hash("lfo&_delay"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
setValueFromOpcode(opcode, lfos[lfoNumber - 1].delay, Default::lfoDelayRange);
}
break;
case hash("lfo&_fade"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
setValueFromOpcode(opcode, lfos[lfoNumber - 1].fade, Default::lfoFadeRange);
}
break;
case hash("lfo&_count"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
setValueFromOpcode(opcode, lfos[lfoNumber - 1].count, Default::lfoCountRange);
}
break;
case hash("lfo&_steps"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoStepsRange)) {
if (!lfos[lfoNumber - 1].seq)
lfos[lfoNumber - 1].seq = LFODescription::StepSequence();
lfos[lfoNumber - 1].seq->steps.resize(*value);
}
}
break;
case hash("lfo&_step&"):
{
const auto lfoNumber = opcode.parameters.front();
const auto stepNumber = opcode.parameters[1];
if (lfoNumber == 0 || stepNumber == 0 || stepNumber > config::maxLFOSteps)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoStepXRange)) {
if (!lfos[lfoNumber - 1].seq)
lfos[lfoNumber - 1].seq = LFODescription::StepSequence();
if (!extendIfNecessary(lfos[lfoNumber - 1].seq->steps, stepNumber, Default::numLFOSteps))
return false;
lfos[lfoNumber - 1].seq->steps[stepNumber - 1] = *value * 0.01f;
}
}
break;
case hash("lfo&_wave&"): // also lfo&_wave
{
const auto lfoNumber = opcode.parameters.front();
const auto subNumber = opcode.parameters[1];
if (lfoNumber == 0 || subNumber == 0 || subNumber > config::maxLFOSubs)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoWaveRange)) {
if (!extendIfNecessary(lfos[lfoNumber - 1].sub, subNumber, Default::numLFOSubs))
return false;
lfos[lfoNumber - 1].sub[subNumber - 1].wave = static_cast<LFOWave>(*value);
}
}
break;
case hash("lfo&_offset&"): // also lfo&_offset
{
const auto lfoNumber = opcode.parameters.front();
const auto subNumber = opcode.parameters[1];
if (lfoNumber == 0 || subNumber == 0 || subNumber > config::maxLFOSubs)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoOffsetRange)) {
if (!extendIfNecessary(lfos[lfoNumber - 1].sub, subNumber, Default::numLFOSubs))
return false;
lfos[lfoNumber - 1].sub[subNumber - 1].offset = *value;
}
}
break;
case hash("lfo&_ratio&"): // also lfo&_ratio
{
const auto lfoNumber = opcode.parameters.front();
const auto subNumber = opcode.parameters[1];
if (lfoNumber == 0 || subNumber == 0 || subNumber > config::maxLFOSubs)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoRatioRange)) {
if (!extendIfNecessary(lfos[lfoNumber - 1].sub, subNumber, Default::numLFOSubs))
return false;
lfos[lfoNumber - 1].sub[subNumber - 1].ratio = *value;
}
}
break;
case hash("lfo&_scale&"): // also lfo&_scale
{
const auto lfoNumber = opcode.parameters.front();
const auto subNumber = opcode.parameters[1];
if (lfoNumber == 0 || subNumber == 0 || subNumber > config::maxLFOSubs)
return false;
if (!extendIfNecessary(lfos, lfoNumber, Default::numLFOs))
return false;
if (auto value = readOpcode(opcode.value, Default::lfoScaleRange)) {
if (!extendIfNecessary(lfos[lfoNumber - 1].sub, subNumber, Default::numLFOSubs))
return false;
lfos[lfoNumber - 1].sub[subNumber - 1].scale = *value;
}
}
break;
// Modulation: LFO (targets)
case hash("lfo&_amplitude"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (auto value = readOpcode(opcode.value, Default::amplitudeRange)) {
const ModKey source = ModKey::createNXYZ(ModId::LFO, id, lfoNumber - 1);
const ModKey target = ModKey::createNXYZ(ModId::Amplitude, id);
getOrCreateConnection(source, target).sourceDepth = *value;
}
}
break;
case hash("lfo&_pan"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (auto value = readOpcode(opcode.value, Default::panCCRange)) {
const ModKey source = ModKey::createNXYZ(ModId::LFO, id, lfoNumber - 1);
const ModKey target = ModKey::createNXYZ(ModId::Pan, id);
getOrCreateConnection(source, target).sourceDepth = *value;
}
}
break;
case hash("lfo&_width"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (auto value = readOpcode(opcode.value, Default::widthCCRange)) {
const ModKey source = ModKey::createNXYZ(ModId::LFO, id, lfoNumber - 1);
const ModKey target = ModKey::createNXYZ(ModId::Width, id);
getOrCreateConnection(source, target).sourceDepth = *value;
}
}
break;
case hash("lfo&_position"): // sfizz extension
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (auto value = readOpcode(opcode.value, Default::positionCCRange)) {
const ModKey source = ModKey::createNXYZ(ModId::LFO, id, lfoNumber - 1);
const ModKey target = ModKey::createNXYZ(ModId::Position, id);
getOrCreateConnection(source, target).sourceDepth = *value;
}
}
break;
case hash("lfo&_pitch"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (auto value = readOpcode(opcode.value, Default::tuneCCRange)) {
const ModKey source = ModKey::createNXYZ(ModId::LFO, id, lfoNumber - 1);
const ModKey target = ModKey::createNXYZ(ModId::Pitch, id);
getOrCreateConnection(source, target).sourceDepth = *value;
}
}
break;
case hash("lfo&_volume"):
{
const auto lfoNumber = opcode.parameters.front();
if (lfoNumber == 0)
return false;
if (auto value = readOpcode(opcode.value, Default::volumeCCRange)) {
const ModKey source = ModKey::createNXYZ(ModId::LFO, id, lfoNumber - 1);
const ModKey target = ModKey::createNXYZ(ModId::Volume, id);
getOrCreateConnection(source, target).sourceDepth = *value;
}
}
break;
// Amplitude Envelope // Amplitude Envelope
case hash("ampeg_attack"): case hash("ampeg_attack"):
setValueFromOpcode(opcode, amplitudeEG.attack, Default::egTimeRange); setValueFromOpcode(opcode, amplitudeEG.attack, Default::egTimeRange);
@ -1378,3 +1600,22 @@ float sfz::Region::getBendInCents(float bend) const noexcept
{ {
return bend > 0.0f ? bend * static_cast<float>(bendUp) : -bend * static_cast<float>(bendDown); return bend > 0.0f ? bend * static_cast<float>(bendUp) : -bend * static_cast<float>(bendDown);
} }
sfz::Region::Connection& sfz::Region::getOrCreateConnection(const ModKey& source, const ModKey& target)
{
auto pred = [&source, &target](const Connection& c)
{
return c.source == source && c.target == target;
};
auto it = std::find_if(connections.begin(), connections.end(), pred);
if (it != connections.end())
return *it;
sfz::Region::Connection c;
c.source = source;
c.target = target;
connections.push_back(c);
return connections.back();
}

View file

@ -12,6 +12,7 @@
#include "EGDescription.h" #include "EGDescription.h"
#include "EQDescription.h" #include "EQDescription.h"
#include "FilterDescription.h" #include "FilterDescription.h"
#include "LFODescription.h"
#include "Opcode.h" #include "Opcode.h"
#include "AudioBuffer.h" #include "AudioBuffer.h"
#include "MidiState.h" #include "MidiState.h"
@ -373,6 +374,9 @@ struct Region {
EGDescription pitchEG; EGDescription pitchEG;
EGDescription filterEG; EGDescription filterEG;
// LFOs
std::vector<LFODescription> lfos;
bool hasStereoSample { false }; bool hasStereoSample { false };
// Effects // Effects
@ -388,6 +392,7 @@ struct Region {
float sourceDepth = 1.0f; float sourceDepth = 1.0f;
}; };
std::vector<Connection> connections; std::vector<Connection> connections;
Connection& getOrCreateConnection(const ModKey& source, const ModKey& target);
// Parent // Parent
RegionSet* parent { nullptr }; RegionSet* parent { nullptr };

View file

@ -16,6 +16,7 @@
#include "modulations/ModKey.h" #include "modulations/ModKey.h"
#include "modulations/ModId.h" #include "modulations/ModId.h"
#include "modulations/sources/Controller.h" #include "modulations/sources/Controller.h"
#include "modulations/sources/LFO.h"
#include "pugixml.hpp" #include "pugixml.hpp"
#include "absl/algorithm/container.h" #include "absl/algorithm/container.h"
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
@ -42,6 +43,7 @@ sfz::Synth::Synth(int numVoices)
// modulation sources // modulation sources
genController.reset(new ControllerSource(resources)); genController.reset(new ControllerSource(resources));
genLFO.reset(new LFOSource(*this));
} }
sfz::Synth::~Synth() sfz::Synth::~Synth()
@ -461,6 +463,7 @@ void sfz::Synth::finalizeSfzLoad()
size_t maxFilters { 0 }; size_t maxFilters { 0 };
size_t maxEQs { 0 }; size_t maxEQs { 0 };
size_t maxLFOs { 0 };
while (currentRegionIndex < currentRegionCount) { while (currentRegionIndex < currentRegionCount) {
auto region = regions[currentRegionIndex].get(); auto region = regions[currentRegionIndex].get();
@ -571,6 +574,7 @@ void sfz::Synth::finalizeSfzLoad()
region->registerTempo(2.0f); region->registerTempo(2.0f);
maxFilters = max(maxFilters, region->filters.size()); maxFilters = max(maxFilters, region->filters.size());
maxEQs = max(maxEQs, region->equalizers.size()); maxEQs = max(maxEQs, region->equalizers.size());
maxLFOs = max(maxLFOs, region->lfos.size());
++currentRegionIndex; ++currentRegionIndex;
} }
@ -580,6 +584,7 @@ void sfz::Synth::finalizeSfzLoad()
settingsPerVoice.maxFilters = maxFilters; settingsPerVoice.maxFilters = maxFilters;
settingsPerVoice.maxEQs = maxEQs; settingsPerVoice.maxEQs = maxEQs;
settingsPerVoice.maxLFOs = maxLFOs;
applySettingsPerVoice(); applySettingsPerVoice();
@ -1437,6 +1442,7 @@ void sfz::Synth::applySettingsPerVoice()
for (auto& voice : voices) { for (auto& voice : voices) {
voice->setMaxFiltersPerVoice(settingsPerVoice.maxFilters); voice->setMaxFiltersPerVoice(settingsPerVoice.maxFilters);
voice->setMaxEQsPerVoice(settingsPerVoice.maxEQs); voice->setMaxEQsPerVoice(settingsPerVoice.maxEQs);
voice->setMaxLFOsPerVoice(settingsPerVoice.maxLFOs);
} }
} }
@ -1452,6 +1458,9 @@ void sfz::Synth::setupModMatrix()
case ModId::Controller: case ModId::Controller:
gen = genController.get(); gen = genController.get();
break; break;
case ModId::LFO:
gen = genLFO.get();
break;
default: default:
DBG("[sfizz] Have unknown type of source generator"); DBG("[sfizz] Have unknown type of source generator");
break; break;

View file

@ -27,6 +27,7 @@
namespace sfz { namespace sfz {
class ControllerSource; class ControllerSource;
class LFOSource;
/** /**
* @brief This class is the core of the sfizz library. In C++ it is the main point * @brief This class is the core of the sfizz library. In C++ it is the main point
@ -806,11 +807,13 @@ private:
// Modulation source generators // Modulation source generators
std::unique_ptr<ControllerSource> genController; std::unique_ptr<ControllerSource> genController;
std::unique_ptr<LFOSource> genLFO;
// Settings per voice // Settings per voice
struct SettingsPerVoice { struct SettingsPerVoice {
size_t maxFilters { 0 }; size_t maxFilters { 0 };
size_t maxEQs { 0 }; size_t maxEQs { 0 };
size_t maxLFOs { 0 };
}; };
SettingsPerVoice settingsPerVoice; SettingsPerVoice settingsPerVoice;

View file

@ -12,6 +12,7 @@
#include "SIMDHelpers.h" #include "SIMDHelpers.h"
#include "Panning.h" #include "Panning.h"
#include "SfzHelpers.h" #include "SfzHelpers.h"
#include "LFO.h"
#include "modulations/ModId.h" #include "modulations/ModId.h"
#include "modulations/ModKey.h" #include "modulations/ModKey.h"
#include "modulations/ModMatrix.h" #include "modulations/ModMatrix.h"
@ -34,6 +35,10 @@ sfz::Voice::Voice(int voiceNumber, sfz::Resources& resources)
filter.setGain(vaGain(config::filteredEnvelopeCutoff, sampleRate)); filter.setGain(vaGain(config::filteredEnvelopeCutoff, sampleRate));
} }
sfz::Voice::~Voice()
{
}
void sfz::Voice::startVoice(Region* region, int delay, int number, float value, sfz::Voice::TriggerType triggerType) noexcept void sfz::Voice::startVoice(Region* region, int delay, int number, float value, sfz::Voice::TriggerType triggerType) noexcept
{ {
ASSERT(value >= 0.0f && value <= 1.0f); ASSERT(value >= 0.0f && value <= 1.0f);
@ -246,6 +251,9 @@ void sfz::Voice::setSampleRate(float sampleRate) noexcept
for (WavetableOscillator& osc : waveOscillators) for (WavetableOscillator& osc : waveOscillators)
osc.init(sampleRate); osc.init(sampleRate);
for (auto& lfo : lfos)
lfo->setSampleRate(sampleRate);
} }
void sfz::Voice::setSamplesPerBlock(int samplesPerBlock) noexcept void sfz::Voice::setSamplesPerBlock(int samplesPerBlock) noexcept
@ -787,6 +795,17 @@ void sfz::Voice::setMaxEQsPerVoice(size_t numFilters)
equalizers.reserve(numFilters); equalizers.reserve(numFilters);
} }
void sfz::Voice::setMaxLFOsPerVoice(size_t numLFOs)
{
lfos.resize(numLFOs);
for (size_t i = 0; i < numLFOs; ++i) {
auto lfo = absl::make_unique<LFO>();
lfo->setSampleRate(sampleRate);
lfos[i] = std::move(lfo);
}
}
void sfz::Voice::setupOscillatorUnison() void sfz::Voice::setupOscillatorUnison()
{ {
int m = region->oscillatorMulti; int m = region->oscillatorMulti;

View file

@ -22,6 +22,7 @@
namespace sfz { namespace sfz {
enum InterpolatorModel : int; enum InterpolatorModel : int;
class LFO;
/** /**
* @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
@ -38,6 +39,9 @@ public:
* @param midiState * @param midiState
*/ */
Voice(int voiceNumber, Resources& resources); Voice(int voiceNumber, Resources& resources);
~Voice();
enum class TriggerType { enum class TriggerType {
NoteOn, NoteOn,
NoteOff, NoteOff,
@ -270,6 +274,12 @@ public:
* @return * @return
*/ */
const Region* getRegion() const noexcept { return region; } const Region* getRegion() const noexcept { return region; }
/**
* @brief Get the LFO designated by the given index
*
* @param index
*/
LFO* getLFO(size_t index) { return lfos[index].get(); }
/** /**
* @brief Set the max number of filters per voice * @brief Set the max number of filters per voice
* *
@ -279,9 +289,15 @@ public:
/** /**
* @brief Set the max number of EQs per voice * @brief Set the max number of EQs per voice
* *
* @param numFilters * @param numEQs
*/ */
void setMaxEQsPerVoice(size_t numEQs); void setMaxEQsPerVoice(size_t numEQs);
/**
* @brief Set the max number of LFOs per voice
*
* @param numLFOs
*/
void setMaxLFOsPerVoice(size_t numLFOs);
/** /**
* @brief Release the voice after a given delay * @brief Release the voice after a given delay
* *
@ -441,6 +457,7 @@ private:
std::vector<FilterHolderPtr> filters; std::vector<FilterHolderPtr> filters;
std::vector<EQHolderPtr> equalizers; std::vector<EQHolderPtr> equalizers;
std::vector<std::unique_ptr<LFO>> lfos;
ADSREnvelope<float> egEnvelope; ADSREnvelope<float> egEnvelope;
float bendStepFactor { centsFactor(1) }; float bendStepFactor { centsFactor(1) };

View file

@ -0,0 +1,67 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "LFO.h"
#include "../../LFO.h"
#include "../../Synth.h"
#include "../../Voice.h"
#include "../../SIMDHelpers.h"
#include "../../Config.h"
#include "../../Debug.h"
namespace sfz {
LFOSource::LFOSource(Synth &synth)
: synth_(&synth)
{
}
void LFOSource::init(const ModKey& sourceKey, NumericId<Voice> voiceId)
{
Synth& synth = *synth_;
unsigned lfoIndex = sourceKey.parameters().N;
Voice* voice = synth.getVoiceById(voiceId);
if (!voice) {
ASSERTFALSE;
return;
}
const Region* region = voice->getRegion();
if (lfoIndex >= region->lfos.size()) {
ASSERTFALSE;
return;
}
LFO* lfo = voice->getLFO(lfoIndex);
lfo->configure(&region->lfos[lfoIndex]);
lfo->start();
}
void LFOSource::generate(const ModKey& sourceKey, NumericId<Voice> voiceId, absl::Span<float> buffer)
{
Synth& synth = *synth_;
const unsigned lfoIndex = sourceKey.parameters().N;
Voice* voice = synth.getVoiceById(voiceId);
if (!voice) {
ASSERTFALSE;
fill(buffer, 0.0f);
return;
}
const Region* region = voice->getRegion();
if (lfoIndex >= region->lfos.size()) {
ASSERTFALSE;
fill(buffer, 0.0f);
return;
}
LFO* lfo = voice->getLFO(lfoIndex);
lfo->process(buffer);
}
} // namespace sfz

View file

@ -0,0 +1,23 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
#include "../ModGenerator.h"
namespace sfz {
class Synth;
class LFOSource : public ModGenerator {
public:
explicit LFOSource(Synth &synth);
void init(const ModKey& sourceKey, NumericId<Voice> voiceId) override;
void generate(const ModKey& sourceKey, NumericId<Voice> voiceId, absl::Span<float> buffer) override;
private:
Synth* synth_ = nullptr;
};
} // namespace sfz

View file

@ -39,6 +39,9 @@ set(SFIZZ_TEST_SOURCES
TuningT.cpp TuningT.cpp
ConcurrencyT.cpp ConcurrencyT.cpp
ModulationsT.cpp ModulationsT.cpp
LFOT.cpp
DataHelpers.h
DataHelpers.cpp
) )
add_executable(sfizz_tests ${SFIZZ_TEST_SOURCES}) add_executable(sfizz_tests ${SFIZZ_TEST_SOURCES})
@ -94,6 +97,9 @@ target_link_libraries(sfizz_plot_curve PRIVATE sfizz::sfizz)
add_executable(sfizz_plot_wavetables PlotWavetables.cpp) add_executable(sfizz_plot_wavetables PlotWavetables.cpp)
target_link_libraries(sfizz_plot_wavetables PRIVATE sfizz::sfizz) target_link_libraries(sfizz_plot_wavetables PRIVATE sfizz::sfizz)
add_executable(sfizz_plot_lfo PlotLFO.cpp)
target_link_libraries(sfizz_plot_lfo PRIVATE sfizz::sfizz)
add_executable(sfizz_file_instrument FileInstrument.cpp) add_executable(sfizz_file_instrument FileInstrument.cpp)
target_link_libraries(sfizz_file_instrument PRIVATE sfizz::sfizz) target_link_libraries(sfizz_file_instrument PRIVATE sfizz::sfizz)

89
tests/DataHelpers.cpp Normal file
View file

@ -0,0 +1,89 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "DataHelpers.h"
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <cstring>
void load_txt(DataPoints& dp, std::istream& in)
{
struct RawValue {
bool rowJump;
float value;
};
std::vector<RawValue> raw;
raw.reserve(1024);
// read raw value data
{
std::string line;
line.reserve(256);
while (std::getline(in, line)) {
size_t commentPos = line.find('#');
if (commentPos == line.npos)
line = line.substr(0, commentPos);
std::istringstream lineIn(line);
RawValue rv;
rv.rowJump = true;
while (lineIn >> rv.value) {
raw.push_back(rv);
rv.rowJump = false;
}
}
}
if (raw.empty()) {
dp.rows = 0;
dp.cols = 0;
dp.data.reset();
return;
}
// count rows and columns
size_t numRows = 0;
size_t numCols = 0;
{
size_t c = 0;
for (const RawValue& rv : raw) {
if (!rv.rowJump)
++c;
else {
numRows += c != 0;
c = 1;
}
numCols = std::max(numCols, c);
}
numRows += c != 0;
}
// fill the data
float* data = new float[numRows * numCols];
dp.rows = numRows;
dp.cols = numCols;
dp.data.reset(data);
for (size_t i = 0, j = 0; i < numRows * numCols; ) {
size_t c = 1;
data[i++] = raw[j++].value;
for (; j < raw.size() && !raw[j].rowJump; ++c)
data[i++] = raw[j++].value;
for ( ; c < numCols; ++c)
data[i++] = 0.0f;
}
}
bool load_txt_file(DataPoints& dp, const fs::path& path)
{
fs::ifstream in(path);
load_txt(dp, in);
return !in.bad();
}

29
tests/DataHelpers.h Normal file
View file

@ -0,0 +1,29 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#pragma once
#include <ghc/fs_std.hpp>
#include <iosfwd>
#include <memory>
#include <cstddef>
struct DataPoints {
size_t rows = 0;
size_t cols = 0;
std::unique_ptr<float[]> data;
const float& operator()(size_t r, size_t c) const noexcept
{
return data[r * cols + c];
}
float& operator()(size_t r, size_t c) noexcept
{
return data[r * cols + c];
}
};
void load_txt(DataPoints& dp, std::istream& in);
bool load_txt_file(DataPoints& dp, const fs::path& path);

117
tests/LFOT.cpp Normal file
View file

@ -0,0 +1,117 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
#include "DataHelpers.h"
#include "sfizz/Synth.h"
#include "sfizz/LFO.h"
#include "catch2/catch.hpp"
static bool computeLFO(DataPoints& dp, const fs::path& sfzPath, double sampleRate, size_t numFrames)
{
sfz::Synth synth;
if (!synth.loadSfzFile(sfzPath))
return false;
if (synth.getNumRegions() != 1)
return false;
const std::vector<sfz::LFODescription>& desc = synth.getRegionView(0)->lfos;
size_t numLfos = desc.size();
std::vector<sfz::LFO> lfos(numLfos);
for (size_t l = 0; l < numLfos; ++l) {
lfos[l].setSampleRate(sampleRate);
lfos[l].configure(&desc[l]);
}
std::vector<float> outputMemory(numLfos * numFrames);
for (size_t l = 0; l < numLfos; ++l) {
lfos[l].start();
}
std::vector<absl::Span<float>> lfoOutputs(numLfos);
for (size_t l = 0; l < numLfos; ++l) {
lfoOutputs[l] = absl::MakeSpan(&outputMemory[l * numFrames], numFrames);
lfos[l].process(lfoOutputs[l]);
}
dp.rows = numFrames;
dp.cols = numLfos + 1;
dp.data.reset(new float[dp.rows * dp.cols]);
for (size_t i = 0; i < numFrames; ++i) {
dp(i, 0) = i / sampleRate;
for (size_t l = 0; l < numLfos; ++l)
dp(i, 1 + l) = lfoOutputs[l][i];
}
return true;
}
double meanSquareError(const float* a, const float* b, size_t count, size_t step)
{
double sum = 0;
for (size_t i = 0; i < count; ++i) {
double diff = a[i * step] - b[i * step];
sum += diff * diff;
}
return sum / count;
}
static constexpr double mseThreshold = 1e-3;
TEST_CASE("[LFO] Waves")
{
DataPoints ref;
REQUIRE(load_txt_file(ref, "tests/lfo/lfo_waves_reference.dat"));
DataPoints cur;
REQUIRE(computeLFO(cur, "tests/lfo/lfo_waves.sfz", 100.0, ref.rows));
REQUIRE(ref.rows == cur.rows);
REQUIRE(ref.cols == cur.cols);
for (size_t l = 1; l < cur.cols; ++l) {
double mse = meanSquareError(&ref.data[l], &cur.data[l], ref.rows, ref.cols);
REQUIRE(mse < mseThreshold);
}
}
TEST_CASE("[LFO] Subwave")
{
DataPoints ref;
REQUIRE(load_txt_file(ref, "tests/lfo/lfo_subwave_reference.dat"));
DataPoints cur;
REQUIRE(computeLFO(cur, "tests/lfo/lfo_subwave.sfz", 100.0, ref.rows));
REQUIRE(ref.rows == cur.rows);
REQUIRE(ref.cols == cur.cols);
for (size_t l = 1; l < cur.cols; ++l) {
double mse = meanSquareError(&ref.data[l], &cur.data[l], ref.rows, ref.cols);
REQUIRE(mse < mseThreshold);
}
}
TEST_CASE("[LFO] Fade and delay")
{
DataPoints ref;
REQUIRE(load_txt_file(ref, "tests/lfo/lfo_fade_and_delay_reference.dat"));
DataPoints cur;
REQUIRE(computeLFO(cur, "tests/lfo/lfo_fade_and_delay.sfz", 100.0, ref.rows));
REQUIRE(ref.rows == cur.rows);
REQUIRE(ref.cols == cur.cols);
for (size_t l = 1; l < cur.cols; ++l) {
double mse = meanSquareError(&ref.data[l], &cur.data[l], ref.rows, ref.cols);
REQUIRE(mse < mseThreshold);
}
}

200
tests/PlotLFO.cpp Normal file
View file

@ -0,0 +1,200 @@
// SPDX-License-Identifier: BSD-2-Clause
// This code is part of the sfizz library and is licensed under a BSD 2-clause
// license. You should have receive a LICENSE.md file along with the code.
// If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz
/**
This program generates the data file of a LFO output recorded for a fixed
duration. The file contains columns for each LFO in the SFZ region.
The columns are: Time, Lfo1, ... LfoN
One can use Gnuplot to display this data.
Example:
sfizz_plot_lfo file.sfz > lfo.dat
gnuplot
plot "lfo.dat" using 1:2 with lines
*/
#include "sfizz/Synth.h"
#include "sfizz/LFO.h"
#include "sfizz/LFODescription.h"
#include "sfizz/MathHelpers.h"
#include "cxxopts.hpp"
#include <absl/types/span.h>
#include <vector>
#include <iostream>
#include <cmath>
#ifdef _WIN32
#define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
#endif
#include <sndfile.hh>
//==============================================================================
static double sampleRate = 1000.0; // sample rate used to compute
static double duration = 5.0; // length in seconds
static std::string outputFilename;
static bool saveFlac = false;
static std::vector<sfz::LFODescription> lfoDescriptionFromSfzFile(const fs::path &sfzPath, bool &success)
{
sfz::Synth synth;
if (!synth.loadSfzFile(sfzPath)) {
std::cerr << "Cannot load the SFZ file.\n";
success = false;
return {};
}
if (synth.getNumRegions() != 1) {
std::cerr << "The SFZ file must contain exactly one region.\n";
success = false;
return {};
}
success = true;
return synth.getRegionView(0)->lfos;
}
/**
Program which loads LFO configuration and generates plot data for the given duration.
*/
int main(int argc, char* argv[])
{
cxxopts::Options options("sfizz_plot_lfo", "Compute LFO and generate plot data");
options.add_options()
("s,samplerate", "Sample rate", cxxopts::value(sampleRate))
("d,duration", "Duration", cxxopts::value(duration))
("o,output", "Output file", cxxopts::value(outputFilename))
("F,flac", "Save output as FLAC", cxxopts::value(saveFlac))
("h,help", "Print usage")
;
options.positional_help("sfz-file");
fs::path sfzPath;
try {
cxxopts::ParseResult result = options.parse(argc, argv);
options.parse_positional({ "sfz-file" });
if (result.count("help")) {
std::cout << options.help() << std::endl;
return 0;
}
if (argc != 2) {
std::cerr << "Please indicate the SFZ file to process.\n";
return 1;
}
sfzPath = argv[1];
}
catch (cxxopts::OptionException& ex) {
std::cerr << ex.what() << "\n";
return 1;
}
bool success = false;
const std::vector<sfz::LFODescription> desc = lfoDescriptionFromSfzFile(sfzPath, success);
if (!success){
std::cerr << "Could not extract LFO descriptions from SFZ file.\n";
return 1;
}
if (sampleRate <= 0) {
std::cerr << "The sample rate provided is invalid.\n";
return 1;
}
size_t numLfos = desc.size();
std::vector<sfz::LFO> lfos(numLfos);
for (size_t l = 0; l < numLfos; ++l) {
lfos[l].setSampleRate(sampleRate);
lfos[l].configure(&desc[l]);
}
size_t numFrames = (size_t)std::ceil(sampleRate * duration);
std::vector<float> outputMemory(numLfos * numFrames);
for (size_t l = 0; l < numLfos; ++l) {
lfos[l].start();
}
std::vector<absl::Span<float>> lfoOutputs(numLfos);
for (size_t l = 0; l < numLfos; ++l) {
lfoOutputs[l] = absl::MakeSpan(&outputMemory[l * numFrames], numFrames);
lfos[l].process(lfoOutputs[l]);
}
if (saveFlac) {
if (outputFilename.empty()) {
std::cerr << "Please indicate the audio file to save.\n";
return 1;
}
fs::path outputPath = fs::u8path(outputFilename);
SndfileHandle snd(
#ifndef _WIN32
outputPath.c_str(),
#else
outputPath.wstring().c_str(),
#endif
SFM_WRITE, SF_FORMAT_FLAC|SF_FORMAT_PCM_16, numLfos, sampleRate);
std::unique_ptr<float[]> frame(new float[numLfos]);
size_t numClips = 0;
for (size_t i = 0; i < numFrames; ++i) {
for (size_t l = 0; l < numLfos; ++l) {
float orig = lfoOutputs[l][i];
float clamped = clamp(orig, -1.0f, 1.0f);
numClips += clamped != orig;
frame[l] = clamped;
}
snd.writef(frame.get(), 1);
}
snd.writeSync();
if (snd.error()) {
std::error_code ec;
fs::remove(outputPath, ec);
std::cerr << "Could not save audio to the output file.\n";
return 1;
}
if (numClips > 0)
std::cerr << "Warning: the audio output has been clipped on " << numClips << " frames.\n";
}
else {
std::ostream* os = &std::cout;
fs::ofstream of;
fs::path outputPath;
if (!outputFilename.empty()) {
outputPath = fs::u8path(outputFilename);
of.open(outputPath);
os = &of;
}
for (size_t i = 0; i < numFrames; ++i) {
*os << (i / sampleRate);
for (size_t l = 0; l < numLfos; ++l)
*os << ' ' << lfoOutputs[l][i];
*os << '\n';
}
if (os == &of) {
of.flush();
if (!of) {
std::error_code ec;
fs::remove(outputPath, ec);
std::cerr << "Could not save data to the output file.\n";
return 1;
}
}
}
return 0;
}

27
tests/lfo/compare_lfo.py Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env python3
# coding: utf-8
import numpy as np
from argparse import ArgumentParser
import os
parser = ArgumentParser(usage="Compare 2 files as outputted by sfizz_plot_lfo")
parser.add_argument("file", help="The file to test")
parser.add_argument("reference", help="The reference file")
parser.add_argument("--threshold", type=float, default=0.001, help="Mean squared error threshold")
args = parser.parse_args()
assert os.path.exists(args.file), "The file to test does not exist"
assert os.path.exists(args.reference), "The reference file does not exist"
reference_data = np.loadtxt(args.reference)
data = np.loadtxt(args.file)
assert reference_data.shape == data.shape, "The shapes of the data and reference are different"
mean_squared_error = np.mean((data - reference_data) ** 2)
print("MSE difference:", mean_squared_error)
if (mean_squared_error > args.threshold):
exit(-1)

View file

@ -0,0 +1,7 @@
<region>
sample=*sine
//
lfo1_freq=1
lfo1_wave=3
lfo1_delay=0.5
lfo1_fade=1

View file

@ -0,0 +1,500 @@
0 0
0.01 0
0.02 0
0.03 0
0.04 0
0.05 0
0.06 0
0.07 0
0.08 0
0.09 0
0.1 0
0.11 0
0.12 0
0.13 0
0.14 0
0.15 0
0.16 0
0.17 0
0.18 0
0.19 0
0.2 0
0.21 0
0.22 0
0.23 0
0.24 0
0.25 0
0.26 0
0.27 0
0.28 0
0.29 0
0.3 0
0.31 0
0.32 0
0.33 0
0.34 0
0.35 0
0.36 0
0.37 0
0.38 0
0.39 0
0.4 0
0.41 0
0.42 0
0.43 0
0.44 0
0.45 0
0.46 0
0.47 0
0.48 0
0.49 0
0.5 0
0.51 0.01
0.52 0.02
0.53 0.03
0.54 0.04
0.55 0.05
0.56 0.06
0.57 0.07
0.58 0.08
0.59 0.09
0.6 0.1
0.61 0.11
0.62 0.12
0.63 0.13
0.64 0.14
0.65 0.15
0.66 0.16
0.67 0.17
0.68 0.18
0.69 0.19
0.7 0.2
0.71 0.21
0.72 0.22
0.73 0.23
0.74 0.24
0.75 0.25
0.76 0.26
0.77 0.27
0.78 0.28
0.79 0.29
0.8 0.3
0.81 0.31
0.82 0.32
0.83 0.33
0.84 0.34
0.85 0.35
0.86 0.36
0.87 0.37
0.88 0.38
0.89 0.39
0.9 0.4
0.91 0.41
0.92 0.42
0.93 0.43
0.94 0.44
0.95 0.45
0.96 0.46
0.97 0.47
0.98 0.48
0.99 0.49
1 0.5
1.01 -0.51
1.02 -0.52
1.03 -0.53
1.04 -0.54
1.05 -0.55
1.06 -0.56
1.07 -0.57
1.08 -0.58
1.09 -0.59
1.1 -0.6
1.11 -0.61
1.12 -0.62
1.13 -0.63
1.14 -0.64
1.15 -0.65
1.16 -0.66
1.17 -0.67
1.18 -0.68
1.19 -0.69
1.2 -0.7
1.21 -0.71
1.22 -0.72
1.23 -0.73
1.24 -0.74
1.25 -0.75
1.26 -0.76
1.27 -0.77
1.28 -0.78
1.29 -0.79
1.3 -0.8
1.31 -0.81
1.32 -0.82
1.33 -0.83
1.34 -0.839999
1.35 -0.849999
1.36 -0.859999
1.37 -0.869999
1.38 -0.879999
1.39 -0.889999
1.4 -0.899999
1.41 -0.909999
1.42 -0.919999
1.43 -0.929999
1.44 -0.939999
1.45 -0.949999
1.46 -0.959999
1.47 -0.969999
1.48 -0.979999
1.49 -0.989999
1.5 -0.999999
1.51 1
1.52 1
1.53 1
1.54 1
1.55 1
1.56 1
1.57 1
1.58 1
1.59 1
1.6 1
1.61 1
1.62 1
1.63 1
1.64 1
1.65 1
1.66 1
1.67 1
1.68 1
1.69 1
1.7 1
1.71 1
1.72 1
1.73 1
1.74 1
1.75 1
1.76 1
1.77 1
1.78 1
1.79 1
1.8 1
1.81 1
1.82 1
1.83 1
1.84 1
1.85 1
1.86 1
1.87 1
1.88 1
1.89 1
1.9 1
1.91 1
1.92 1
1.93 1
1.94 1
1.95 1
1.96 1
1.97 1
1.98 1
1.99 1
2 1
2.01 -1
2.02 -1
2.03 -1
2.04 -1
2.05 -1
2.06 -1
2.07 -1
2.08 -1
2.09 -1
2.1 -1
2.11 -1
2.12 -1
2.13 -1
2.14 -1
2.15 -1
2.16 -1
2.17 -1
2.18 -1
2.19 -1
2.2 -1
2.21 -1
2.22 -1
2.23 -1
2.24 -1
2.25 -1
2.26 -1
2.27 -1
2.28 -1
2.29 -1
2.3 -1
2.31 -1
2.32 -1
2.33 -1
2.34 -1
2.35 -1
2.36 -1
2.37 -1
2.38 -1
2.39 -1
2.4 -1
2.41 -1
2.42 -1
2.43 -1
2.44 -1
2.45 -1
2.46 -1
2.47 -1
2.48 -1
2.49 -1
2.5 -1
2.51 1
2.52 1
2.53 1
2.54 1
2.55 1
2.56 1
2.57 1
2.58 1
2.59 1
2.6 1
2.61 1
2.62 1
2.63 1
2.64 1
2.65 1
2.66 1
2.67 1
2.68 1
2.69 1
2.7 1
2.71 1
2.72 1
2.73 1
2.74 1
2.75 1
2.76 1
2.77 1
2.78 1
2.79 1
2.8 1
2.81 1
2.82 1
2.83 1
2.84 1
2.85 1
2.86 1
2.87 1
2.88 1
2.89 1
2.9 1
2.91 1
2.92 1
2.93 1
2.94 1
2.95 1
2.96 1
2.97 1
2.98 1
2.99 1
3 1
3.01 -1
3.02 -1
3.03 -1
3.04 -1
3.05 -1
3.06 -1
3.07 -1
3.08 -1
3.09 -1
3.1 -1
3.11 -1
3.12 -1
3.13 -1
3.14 -1
3.15 -1
3.16 -1
3.17 -1
3.18 -1
3.19 -1
3.2 -1
3.21 -1
3.22 -1
3.23 -1
3.24 -1
3.25 -1
3.26 -1
3.27 -1
3.28 -1
3.29 -1
3.3 -1
3.31 -1
3.32 -1
3.33 -1
3.34 -1
3.35 -1
3.36 -1
3.37 -1
3.38 -1
3.39 -1
3.4 -1
3.41 -1
3.42 -1
3.43 -1
3.44 -1
3.45 -1
3.46 -1
3.47 -1
3.48 -1
3.49 -1
3.5 -1
3.51 1
3.52 1
3.53 1
3.54 1
3.55 1
3.56 1
3.57 1
3.58 1
3.59 1
3.6 1
3.61 1
3.62 1
3.63 1
3.64 1
3.65 1
3.66 1
3.67 1
3.68 1
3.69 1
3.7 1
3.71 1
3.72 1
3.73 1
3.74 1
3.75 1
3.76 1
3.77 1
3.78 1
3.79 1
3.8 1
3.81 1
3.82 1
3.83 1
3.84 1
3.85 1
3.86 1
3.87 1
3.88 1
3.89 1
3.9 1
3.91 1
3.92 1
3.93 1
3.94 1
3.95 1
3.96 1
3.97 1
3.98 1
3.99 1
4 1
4.01 -1
4.02 -1
4.03 -1
4.04 -1
4.05 -1
4.06 -1
4.07 -1
4.08 -1
4.09 -1
4.1 -1
4.11 -1
4.12 -1
4.13 -1
4.14 -1
4.15 -1
4.16 -1
4.17 -1
4.18 -1
4.19 -1
4.2 -1
4.21 -1
4.22 -1
4.23 -1
4.24 -1
4.25 -1
4.26 -1
4.27 -1
4.28 -1
4.29 -1
4.3 -1
4.31 -1
4.32 -1
4.33 -1
4.34 -1
4.35 -1
4.36 -1
4.37 -1
4.38 -1
4.39 -1
4.4 -1
4.41 -1
4.42 -1
4.43 -1
4.44 -1
4.45 -1
4.46 -1
4.47 -1
4.48 -1
4.49 -1
4.5 -1
4.51 1
4.52 1
4.53 1
4.54 1
4.55 1
4.56 1
4.57 1
4.58 1
4.59 1
4.6 1
4.61 1
4.62 1
4.63 1
4.64 1
4.65 1
4.66 1
4.67 1
4.68 1
4.69 1
4.7 1
4.71 1
4.72 1
4.73 1
4.74 1
4.75 1
4.76 1
4.77 1
4.78 1
4.79 1
4.8 1
4.81 1
4.82 1
4.83 1
4.84 1
4.85 1
4.86 1
4.87 1
4.88 1
4.89 1
4.9 1
4.91 1
4.92 1
4.93 1
4.94 1
4.95 1
4.96 1
4.97 1
4.98 1
4.99 1

31
tests/lfo/lfo_subwave.sfz Normal file
View file

@ -0,0 +1,31 @@
<region>
sample=*noise
lokey=0
hikey=127
cutoff=1000.0
fil_type=brf_2p
lfo1_cutoff=1200.0
//
lfo1_freq=1
lfo1_phase=180
lfo1_wave=3
//
lfo2_freq=1
lfo2_phase=180
lfo2_wave=3
lfo2_wave2=1
//
lfo3_freq=1
lfo3_phase=180
lfo3_wave=3
lfo3_wave2=1
lfo3_ratio2=2
//
lfo4_freq=1
lfo4_phase=180
lfo4_wave=3
lfo4_wave2=1
lfo4_ratio2=2
lfo4_offset2=0.5
lfo4_scale2=0.5

View file

@ -0,0 +1,500 @@
0 -1 -1 -1 -0.5
0.01 -1 -0.9216 -0.8464 -0.4232
0.02 -1 -0.8464 -0.7056 -0.3528
0.03 -1 -0.7744 -0.5776 -0.2888
0.04 -1 -0.7056 -0.4624 -0.2312
0.05 -1 -0.64 -0.36 -0.18
0.06 -1 -0.5776 -0.2704 -0.1352
0.07 -1 -0.5184 -0.1936 -0.0968002
0.08 -1 -0.4624 -0.1296 -0.0648002
0.09 -1 -0.4096 -0.0784004 -0.0392002
0.1 -1 -0.36 -0.0400003 -0.0200002
0.11 -1 -0.3136 -0.0144002 -0.00720009
0.12 -1 -0.2704 -0.00160009 -0.000800043
0.13 -1 -0.230401 -0.00159991 -0.000799954
0.14 -1 -0.1936 -0.0143998 -0.00719988
0.15 -1 -0.16 -0.0399995 -0.0199998
0.16 -1 -0.1296 -0.0783993 -0.0391997
0.17 -1 -0.1024 -0.129599 -0.0647995
0.18 -1 -0.0784004 -0.193599 -0.0967994
0.19 -1 -0.0576003 -0.270398 -0.135199
0.2 -1 -0.0400003 -0.359998 -0.179999
0.21 -1 -0.0256003 -0.462398 -0.231199
0.22 -1 -0.0144002 -0.577597 -0.288799
0.23 -1 -0.00640017 -0.705597 -0.352799
0.24 -1 -0.00160009 -0.846397 -0.423198
0.25 -1 0 -0.999996 -0.499998
0.26 -1 -0.00159991 -1.1536 -0.576798
0.27 -1 -0.00639981 -1.2944 -0.647198
0.28 -1 -0.0143998 -1.4224 -0.711198
0.29 -1 -0.0255997 -1.5376 -0.768799
0.3 -1 -0.0399995 -1.64 -0.819999
0.31 -1 -0.0575994 -1.7296 -0.864799
0.32 -1 -0.0783993 -1.8064 -0.903199
0.33 -1 -0.102399 -1.8704 -0.935199
0.34 -1 -0.129599 -1.9216 -0.960799
0.35 -1 -0.159999 -1.96 -0.98
0.36 -1 -0.193599 -1.9856 -0.9928
0.37 -1 -0.230399 -1.9984 -0.9992
0.38 -1 -0.270398 -1.9984 -0.9992
0.39 -1 -0.313598 -1.9856 -0.9928
0.4 -1 -0.359998 -1.96 -0.98
0.41 -1 -0.409598 -1.9216 -0.960801
0.42 -1 -0.462398 -1.8704 -0.935201
0.43 -1 -0.518398 -1.8064 -0.903201
0.44 -1 -0.577597 -1.7296 -0.864801
0.45 -1 -0.639997 -1.64 -0.820001
0.46 -1 -0.705597 -1.5376 -0.768801
0.47 -1 -0.774397 -1.4224 -0.711201
0.48 -1 -0.846397 -1.2944 -0.647201
0.49 -1 -0.921596 -1.1536 -0.576801
0.5 -1 -0.999996 -1 -0.500002
0.51 1 0.921604 1.1536 1.5768
0.52 1 0.846404 1.2944 1.6472
0.53 1 0.774403 1.4224 1.7112
0.54 1 0.705603 1.5376 1.7688
0.55 1 0.640003 1.64 1.82
0.56 1 0.577603 1.7296 1.8648
0.57 1 0.518403 1.8064 1.9032
0.58 1 0.462403 1.8704 1.9352
0.59 1 0.409603 1.9216 1.9608
0.6 1 0.360002 1.96 1.98
0.61 1 0.313602 1.9856 1.9928
0.62 1 0.270402 1.9984 1.9992
0.63 1 0.230402 1.9984 1.9992
0.64 1 0.193602 1.9856 1.9928
0.65 1 0.160002 1.96 1.98
0.66 1 0.129601 1.9216 1.9608
0.67 1 0.102401 1.8704 1.9352
0.68 1 0.078401 1.8064 1.9032
0.69 1 0.0576009 1.7296 1.8648
0.7 1 0.0400007 1.64 1.82
0.71 1 0.0256006 1.5376 1.7688
0.72 1 0.0144004 1.4224 1.7112
0.73 1 0.00640029 1.29441 1.6472
0.74 1 0.00160015 1.15361 1.5768
0.75 1 0 1.00001 1.5
0.76 1 0.00159985 0.846406 1.4232
0.77 1 0.00639969 0.705606 1.3528
0.78 1 0.0143996 0.577605 1.2888
0.79 1 0.0255994 0.462405 1.2312
0.8 1 0.0399992 0.360004 1.18
0.81 1 0.0575991 0.270404 1.1352
0.82 1 0.0783989 0.193603 1.0968
0.83 1 0.102399 0.129602 1.0648
0.84 1 0.129599 0.078402 1.0392
0.85 1 0.159998 0.0400014 1.02
0.86 1 0.193598 0.0144008 1.0072
0.87 1 0.230398 0.00160027 1.0008
0.88 1 0.270398 0.00159973 1.0008
0.89 1 0.313598 0.0143992 1.0072
0.9 1 0.359997 0.0399987 1.02
0.91 1 0.409597 0.0783981 1.0392
0.92 1 0.462397 0.129598 1.0648
0.93 1 0.518397 0.193597 1.0968
0.94 1 0.577596 0.270397 1.1352
0.95 1 0.639996 0.359996 1.18
0.96 1 0.705596 0.462396 1.2312
0.97 1 0.774396 0.577595 1.2888
0.98 1 0.846395 0.705595 1.3528
0.99 1 0.921595 0.846394 1.4232
1 1 0.999995 0.999994 1.5
1.01 -1 -0.921605 -0.846405 -0.423203
1.02 -1 -0.846405 -0.705605 -0.352803
1.03 -1 -0.774405 -0.577605 -0.288802
1.04 -1 -0.705605 -0.462404 -0.231202
1.05 -1 -0.640005 -0.360004 -0.180002
1.06 -1 -0.577604 -0.270403 -0.135202
1.07 -1 -0.518404 -0.193603 -0.0968015
1.08 -1 -0.462404 -0.129602 -0.0648012
1.09 -1 -0.409604 -0.078402 -0.039201
1.1 -1 -0.360004 -0.0400015 -0.0200007
1.11 -1 -0.313603 -0.0144009 -0.00720045
1.12 -1 -0.270403 -0.00160033 -0.000800163
1.13 -1 -0.230403 -0.00159967 -0.000799835
1.14 -1 -0.193603 -0.0143991 -0.00719953
1.15 -1 -0.160003 -0.0399984 -0.0199992
1.16 -1 -0.129602 -0.0783977 -0.0391988
1.17 -1 -0.102402 -0.129597 -0.0647985
1.18 -1 -0.0784019 -0.193596 -0.0967982
1.19 -1 -0.0576016 -0.270396 -0.135198
1.2 -1 -0.0400013 -0.359995 -0.179997
1.21 -1 -0.0256011 -0.462394 -0.231197
1.22 -1 -0.0144008 -0.577593 -0.288797
1.23 -1 -0.00640059 -0.705592 -0.352796
1.24 -1 -0.00160027 -0.846391 -0.423196
1.25 -1 0 -0.99999 -0.499995
1.26 -1 -0.00159973 -1.15359 -0.576796
1.27 -1 -0.00639939 -1.29439 -0.647196
1.28 -1 -0.0143991 -1.42239 -0.711196
1.29 -1 -0.0255988 -1.53759 -0.768797
1.3 -1 -0.0399985 -1.63999 -0.819997
1.31 -1 -0.0575982 -1.72959 -0.864797
1.32 -1 -0.0783979 -1.8064 -0.903198
1.33 -1 -0.102398 -1.8704 -0.935198
1.34 -1 -0.129597 -1.9216 -0.960799
1.35 -1 -0.159997 -1.96 -0.979999
1.36 -1 -0.193596 -1.9856 -0.992799
1.37 -1 -0.230396 -1.9984 -0.9992
1.38 -1 -0.270396 -1.9984 -0.9992
1.39 -1 -0.313595 -1.9856 -0.992801
1.4 -1 -0.359995 -1.96 -0.980001
1.41 -1 -0.409595 -1.9216 -0.960801
1.42 -1 -0.462394 -1.8704 -0.935202
1.43 -1 -0.518394 -1.8064 -0.903202
1.44 -1 -0.577593 -1.7296 -0.864802
1.45 -1 -0.639993 -1.64001 -0.820003
1.46 -1 -0.705593 -1.53761 -0.768803
1.47 -1 -0.774392 -1.42241 -0.711203
1.48 -1 -0.846392 -1.29441 -0.647204
1.49 -1 -0.921591 -1.15361 -0.576804
1.5 -1 -0.999991 -1.00001 -0.500004
1.51 1 0.921608 1.15359 1.5768
1.52 1 0.846408 1.29439 1.6472
1.53 1 0.774408 1.42239 1.7112
1.54 1 0.705607 1.53759 1.7688
1.55 1 0.640007 1.63999 1.82
1.56 1 0.577606 1.7296 1.8648
1.57 1 0.518406 1.8064 1.9032
1.58 1 0.462406 1.8704 1.9352
1.59 1 0.409606 1.9216 1.9608
1.6 1 0.360005 1.96 1.98
1.61 1 0.313605 1.9856 1.9928
1.62 1 0.270405 1.9984 1.9992
1.63 1 0.230404 1.9984 1.9992
1.64 1 0.193604 1.9856 1.9928
1.65 1 0.160003 1.96 1.98
1.66 1 0.129603 1.9216 1.9608
1.67 1 0.102403 1.8704 1.9352
1.68 1 0.0784024 1.80641 1.9032
1.69 1 0.057602 1.72961 1.8648
1.7 1 0.0400017 1.64001 1.82
1.71 1 0.0256013 1.53761 1.7688
1.72 1 0.014401 1.42241 1.7112
1.73 1 0.00640064 1.29441 1.64721
1.74 1 0.00160033 1.15361 1.57681
1.75 1 0 1.00001 1.50001
1.76 1 0.00159967 0.846412 1.42321
1.77 1 0.00639933 0.705611 1.35281
1.78 1 0.014399 0.57761 1.2888
1.79 1 0.0255986 0.462409 1.2312
1.8 1 0.0399983 0.360008 1.18
1.81 1 0.0575979 0.270407 1.1352
1.82 1 0.0783976 0.193605 1.0968
1.83 1 0.102397 0.129605 1.0648
1.84 1 0.129597 0.0784036 1.0392
1.85 1 0.159996 0.0400025 1.02
1.86 1 0.193596 0.0144015 1.0072
1.87 1 0.230396 0.0016005 1.0008
1.88 1 0.270395 0.00159949 1.0008
1.89 1 0.313595 0.0143985 1.0072
1.9 1 0.359994 0.0399975 1.02
1.91 1 0.409594 0.0783965 1.0392
1.92 1 0.462394 0.129596 1.0648
1.93 1 0.518393 0.193595 1.0968
1.94 1 0.577593 0.270394 1.1352
1.95 1 0.639992 0.359993 1.18
1.96 1 0.705592 0.462392 1.2312
1.97 1 0.774391 0.577591 1.2888
1.98 1 0.846391 0.70559 1.3528
1.99 1 0.92159 0.846389 1.42319
2 1 0.99999 0.999988 1.49999
2.01 -1 -0.92161 -0.846411 -0.423205
2.02 -1 -0.846409 -0.70561 -0.352805
2.03 -1 -0.774409 -0.577609 -0.288805
2.04 -1 -0.705609 -0.462408 -0.231204
2.05 -1 -0.640008 -0.360007 -0.180004
2.06 -1 -0.577608 -0.270406 -0.135203
2.07 -1 -0.518408 -0.193605 -0.0968027
2.08 -1 -0.462407 -0.129605 -0.0648023
2.09 -1 -0.409607 -0.0784036 -0.0392018
2.1 -1 -0.360006 -0.0400026 -0.0200013
2.11 -1 -0.313606 -0.0144016 -0.00720078
2.12 -1 -0.270406 -0.0016005 -0.000800252
2.13 -1 -0.230405 -0.00159949 -0.000799745
2.14 -1 -0.193605 -0.0143984 -0.0071992
2.15 -1 -0.160004 -0.0399973 -0.0199986
2.16 -1 -0.129604 -0.0783961 -0.0391981
2.17 -1 -0.102404 -0.129595 -0.0647975
2.18 -1 -0.0784032 -0.193594 -0.0967969
2.19 -1 -0.0576028 -0.270393 -0.135196
2.2 -1 -0.0400023 -0.359991 -0.179996
2.21 -1 -0.0256019 -0.46239 -0.231195
2.22 -1 -0.0144014 -0.577589 -0.288794
2.23 -1 -0.00640094 -0.705587 -0.352794
2.24 -1 -0.00160044 -0.846386 -0.423193
2.25 -1 0 -0.999985 -0.499992
2.26 -1 -0.00159949 -1.15359 -0.576793
2.27 -1 -0.00639904 -1.29439 -0.647194
2.28 -1 -0.0143985 -1.42239 -0.711194
2.29 -1 -0.025598 -1.53759 -0.768795
2.3 -1 -0.0399975 -1.63999 -0.819995
2.31 -1 -0.057597 -1.72959 -0.864796
2.32 -1 -0.0783965 -1.80639 -0.903197
2.33 -1 -0.102396 -1.87039 -0.935197
2.34 -1 -0.129595 -1.9216 -0.960798
2.35 -1 -0.159995 -1.96 -0.979998
2.36 -1 -0.193594 -1.9856 -0.992799
2.37 -1 -0.230394 -1.9984 -0.9992
2.38 -1 -0.270393 -1.9984 -0.9992
2.39 -1 -0.313593 -1.9856 -0.992801
2.4 -1 -0.359992 -1.96 -0.980002
2.41 -1 -0.409592 -1.9216 -0.960802
2.42 -1 -0.462391 -1.87041 -0.935203
2.43 -1 -0.51839 -1.80641 -0.903203
2.44 -1 -0.57759 -1.72961 -0.864804
2.45 -1 -0.639989 -1.64001 -0.820004
2.46 -1 -0.705589 -1.53761 -0.768805
2.47 -1 -0.774388 -1.42241 -0.711206
2.48 -1 -0.846387 -1.29441 -0.647206
2.49 -1 -0.921587 -1.15361 -0.576807
2.5 -1 -0.999986 -1.00001 -0.500007
2.51 1 0.921613 1.15359 1.57679
2.52 1 0.846412 1.29439 1.64719
2.53 1 0.774412 1.42239 1.71119
2.54 1 0.705611 1.53759 1.76879
2.55 1 0.640011 1.63999 1.82
2.56 1 0.57761 1.72959 1.8648
2.57 1 0.51841 1.80639 1.9032
2.58 1 0.462409 1.87039 1.9352
2.59 1 0.409609 1.9216 1.9608
2.6 1 0.360008 1.96 1.98
2.61 1 0.313608 1.9856 1.9928
2.62 1 0.270407 1.9984 1.9992
2.63 1 0.230406 1.9984 1.9992
2.64 1 0.193606 1.9856 1.9928
2.65 1 0.160005 1.96 1.98
2.66 1 0.129605 1.9216 1.9608
2.67 1 0.102404 1.87041 1.9352
2.68 1 0.0784037 1.80641 1.9032
2.69 1 0.0576032 1.72961 1.8648
2.7 1 0.0400026 1.64001 1.82001
2.71 1 0.0256021 1.53761 1.76881
2.72 1 0.0144016 1.42241 1.71121
2.73 1 0.00640106 1.29441 1.64721
2.74 1 0.0016005 1.15362 1.57681
2.75 1 0 1.00002 1.50001
2.76 1 0.00159949 0.846417 1.42321
2.77 1 0.00639898 0.705615 1.35281
2.78 1 0.0143985 0.577614 1.28881
2.79 1 0.0255979 0.462412 1.23121
2.8 1 0.0399973 0.360011 1.18001
2.81 1 0.0575968 0.27041 1.1352
2.82 1 0.0783963 0.193608 1.0968
2.83 1 0.102396 0.129607 1.0648
2.84 1 0.129595 0.0784052 1.0392
2.85 1 0.159995 0.0400037 1.02
2.86 1 0.193594 0.0144022 1.0072
2.87 1 0.230393 0.00160074 1.0008
2.88 1 0.270393 0.00159925 1.0008
2.89 1 0.313592 0.0143978 1.0072
2.9 1 0.359992 0.0399963 1.02
2.91 1 0.409591 0.0783949 1.0392
2.92 1 0.46239 0.129593 1.0648
2.93 1 0.51839 0.193592 1.0968
2.94 1 0.577589 0.270391 1.1352
2.95 1 0.639988 0.359989 1.17999
2.96 1 0.705588 0.462388 1.23119
2.97 1 0.774387 0.577587 1.28879
2.98 1 0.846387 0.705585 1.35279
2.99 1 0.921586 0.846384 1.42319
3 1 0.999985 0.999983 1.49999
3.01 -1 -0.921614 -0.846416 -0.423208
3.02 -1 -0.846414 -0.705615 -0.352807
3.03 -1 -0.774413 -0.577613 -0.288807
3.04 -1 -0.705613 -0.462412 -0.231206
3.05 -1 -0.640012 -0.360011 -0.180005
3.06 -1 -0.577612 -0.270409 -0.135205
3.07 -1 -0.518411 -0.193608 -0.096804
3.08 -1 -0.46241 -0.129607 -0.0648033
3.09 -1 -0.40961 -0.0784052 -0.0392026
3.1 -1 -0.360009 -0.0400037 -0.0200019
3.11 -1 -0.313609 -0.0144023 -0.00720114
3.12 -1 -0.270408 -0.00160074 -0.000800371
3.13 -1 -0.230408 -0.00159925 -0.000799626
3.14 -1 -0.193607 -0.0143977 -0.00719884
3.15 -1 -0.160006 -0.0399961 -0.019998
3.16 -1 -0.129606 -0.0783945 -0.0391973
3.17 -1 -0.102405 -0.129593 -0.0647964
3.18 -1 -0.0784045 -0.193591 -0.0967956
3.19 -1 -0.0576039 -0.27039 -0.135195
3.2 -1 -0.0400032 -0.359988 -0.179994
3.21 -1 -0.0256026 -0.462386 -0.231193
3.22 -1 -0.014402 -0.577584 -0.288792
3.23 -1 -0.0064013 -0.705583 -0.352791
3.24 -1 -0.00160068 -0.846381 -0.42319
3.25 -1 0 -0.999979 -0.49999
3.26 -1 -0.00159931 -1.15358 -0.57679
3.27 -1 -0.00639868 -1.29438 -0.647191
3.28 -1 -0.014398 -1.42238 -0.711192
3.29 -1 -0.0255973 -1.53759 -0.768793
3.3 -1 -0.0399966 -1.63999 -0.819994
3.31 -1 -0.0575959 -1.72959 -0.864794
3.32 -1 -0.0783952 -1.80639 -0.903195
3.33 -1 -0.102394 -1.87039 -0.935196
3.34 -1 -0.129594 -1.92159 -0.960797
3.35 -1 -0.159993 -1.96 -0.979998
3.36 -1 -0.193592 -1.9856 -0.992799
3.37 -1 -0.230392 -1.9984 -0.9992
3.38 -1 -0.270391 -1.9984 -0.9992
3.39 -1 -0.31359 -1.9856 -0.992801
3.4 -1 -0.359989 -1.96 -0.980002
3.41 -1 -0.409589 -1.92161 -0.960803
3.42 -1 -0.462388 -1.87041 -0.935204
3.43 -1 -0.518387 -1.80641 -0.903205
3.44 -1 -0.577586 -1.72961 -0.864805
3.45 -1 -0.639985 -1.64001 -0.820006
3.46 -1 -0.705585 -1.53761 -0.768807
3.47 -1 -0.774384 -1.42242 -0.711208
3.48 -1 -0.846383 -1.29442 -0.647209
3.49 -1 -0.921582 -1.15362 -0.576809
3.5 -1 -0.999981 -1.00002 -0.50001
3.51 1 0.921617 1.15358 1.57679
3.52 1 0.846417 1.29438 1.64719
3.53 1 0.774416 1.42238 1.71119
3.54 1 0.705615 1.53759 1.76879
3.55 1 0.640015 1.63999 1.81999
3.56 1 0.577614 1.72959 1.86479
3.57 1 0.518413 1.80639 1.9032
3.58 1 0.462412 1.87039 1.9352
3.59 1 0.409612 1.92159 1.9608
3.6 1 0.360011 1.96 1.98
3.61 1 0.31361 1.9856 1.9928
3.62 1 0.27041 1.9984 1.9992
3.63 1 0.230409 1.9984 1.9992
3.64 1 0.193608 1.9856 1.9928
3.65 1 0.160007 1.96 1.98
3.66 1 0.129607 1.92161 1.9608
3.67 1 0.102406 1.87041 1.9352
3.68 1 0.0784051 1.80641 1.90321
3.69 1 0.0576044 1.72961 1.86481
3.7 1 0.0400036 1.64001 1.82001
3.71 1 0.0256029 1.53762 1.76881
3.72 1 0.0144022 1.42242 1.71121
3.73 1 0.00640142 1.29442 1.64721
3.74 1 0.00160068 1.15362 1.57681
3.75 1 0 1.00002 1.50001
3.76 1 0.00159931 0.846422 1.42321
3.77 1 0.00639856 0.70562 1.35281
3.78 1 0.0143979 0.577618 1.28881
3.79 1 0.0255972 0.462416 1.23121
3.8 1 0.0399964 0.360014 1.18001
3.81 1 0.0575957 0.270413 1.13521
3.82 1 0.0783949 0.193611 1.09681
3.83 1 0.102394 0.129609 1.0648
3.84 1 0.129593 0.0784068 1.0392
3.85 1 0.159993 0.0400048 1.02
3.86 1 0.193592 0.0144029 1.0072
3.87 1 0.230391 0.00160098 1.0008
3.88 1 0.27039 0.00159901 1.0008
3.89 1 0.31359 0.0143971 1.0072
3.9 1 0.359989 0.0399952 1.02
3.91 1 0.409588 0.0783933 1.0392
3.92 1 0.462387 0.129591 1.0648
3.93 1 0.518386 0.19359 1.09679
3.94 1 0.577585 0.270388 1.13519
3.95 1 0.639985 0.359986 1.17999
3.96 1 0.705584 0.462384 1.23119
3.97 1 0.774383 0.577582 1.28879
3.98 1 0.846382 0.70558 1.35279
3.99 1 0.921581 0.846379 1.42319
4 1 0.99998 0.999977 1.49999
4.01 -1 -0.921619 -0.846421 -0.423211
4.02 -1 -0.846418 -0.705619 -0.35281
4.03 -1 -0.774417 -0.577618 -0.288809
4.04 -1 -0.705617 -0.462416 -0.231208
4.05 -1 -0.640016 -0.360014 -0.180007
4.06 -1 -0.577615 -0.270412 -0.135206
4.07 -1 -0.518414 -0.193611 -0.0968053
4.08 -1 -0.462414 -0.129609 -0.0648043
4.09 -1 -0.409613 -0.0784068 -0.0392034
4.1 -1 -0.360012 -0.0400049 -0.0200025
4.11 -1 -0.313611 -0.0144029 -0.00720146
4.12 -1 -0.270411 -0.00160098 -0.00080049
4.13 -1 -0.23041 -0.00159901 -0.000799507
4.14 -1 -0.193609 -0.014397 -0.00719851
4.15 -1 -0.160008 -0.039995 -0.0199975
4.16 -1 -0.129607 -0.0783929 -0.0391965
4.17 -1 -0.102407 -0.129591 -0.0647954
4.18 -1 -0.0784059 -0.193589 -0.0967944
4.19 -1 -0.057605 -0.270387 -0.135193
4.2 -1 -0.0400042 -0.359984 -0.179992
4.21 -1 -0.0256034 -0.462382 -0.231191
4.22 -1 -0.0144026 -0.57758 -0.28879
4.23 -1 -0.00640172 -0.705578 -0.352789
4.24 -1 -0.00160086 -0.846376 -0.423188
4.25 -1 0 -0.999973 -0.499987
4.26 -1 -0.00159913 -1.15358 -0.576788
4.27 -1 -0.00639826 -1.29438 -0.647189
4.28 -1 -0.0143974 -1.42238 -0.71119
4.29 -1 -0.0255965 -1.53758 -0.768791
4.3 -1 -0.0399956 -1.63998 -0.819992
4.31 -1 -0.0575947 -1.72959 -0.864793
4.32 -1 -0.0783938 -1.80639 -0.903194
4.33 -1 -0.102393 -1.87039 -0.935195
4.34 -1 -0.129592 -1.92159 -0.960796
4.35 -1 -0.159991 -1.95999 -0.979997
4.36 -1 -0.19359 -1.9856 -0.992798
4.37 -1 -0.230389 -1.9984 -0.999199
4.38 -1 -0.270388 -1.9984 -0.999201
4.39 -1 -0.313587 -1.9856 -0.992802
4.4 -1 -0.359986 -1.96001 -0.980003
4.41 -1 -0.409585 -1.92161 -0.960804
4.42 -1 -0.462385 -1.87041 -0.935205
4.43 -1 -0.518384 -1.80641 -0.903206
4.44 -1 -0.577583 -1.72961 -0.864807
4.45 -1 -0.639982 -1.64002 -0.820008
4.46 -1 -0.705581 -1.53762 -0.768809
4.47 -1 -0.77438 -1.42242 -0.71121
4.48 -1 -0.846379 -1.29442 -0.647211
4.49 -1 -0.921578 -1.15362 -0.576812
4.5 -1 -0.999977 -1.00003 -0.500013
4.51 1 0.921622 1.15358 1.57679
4.52 1 0.846421 1.29438 1.64719
4.53 1 0.77442 1.42238 1.71119
4.54 1 0.705619 1.53758 1.76879
4.55 1 0.640018 1.63998 1.81999
4.56 1 0.577617 1.72959 1.86479
4.57 1 0.518417 1.80639 1.90319
4.58 1 0.462416 1.87039 1.9352
4.59 1 0.409615 1.92159 1.9608
4.6 1 0.360014 1.95999 1.98
4.61 1 0.313613 1.9856 1.9928
4.62 1 0.270412 1.9984 1.9992
4.63 1 0.230411 1.9984 1.9992
4.64 1 0.19361 1.9856 1.9928
4.65 1 0.160009 1.96001 1.98
4.66 1 0.129608 1.92161 1.9608
4.67 1 0.102407 1.87041 1.93521
4.68 1 0.0784064 1.80641 1.90321
4.69 1 0.0576055 1.72961 1.86481
4.7 1 0.0400046 1.64002 1.82001
4.71 1 0.0256036 1.53762 1.76881
4.72 1 0.0144027 1.42242 1.71121
4.73 1 0.00640184 1.29442 1.64721
4.74 1 0.00160092 1.15363 1.57681
4.75 1 0 1.00003 1.50001
4.76 1 0.00159907 0.846427 1.42321
4.77 1 0.0063982 0.705625 1.35281
4.78 1 0.0143973 0.577623 1.28881
4.79 1 0.0255964 0.46242 1.23121
4.8 1 0.0399954 0.360018 1.18001
4.81 1 0.0575945 0.270415 1.13521
4.82 1 0.0783936 0.193613 1.09681
4.83 1 0.102393 0.129611 1.06481
4.84 1 0.129592 0.0784084 1.0392
4.85 1 0.159991 0.040006 1.02
4.86 1 0.19359 0.0144036 1.0072
4.87 1 0.230389 0.00160122 1.0008
4.88 1 0.270388 0.00159878 1.0008
4.89 1 0.313587 0.0143964 1.0072
4.9 1 0.359986 0.0399941 1.02
4.91 1 0.409585 0.0783917 1.0392
4.92 1 0.462384 0.129589 1.06479
4.93 1 0.518383 0.193587 1.09679
4.94 1 0.577582 0.270385 1.13519
4.95 1 0.639981 0.359982 1.17999
4.96 1 0.70558 0.46238 1.23119
4.97 1 0.774379 0.577578 1.28879
4.98 1 0.846378 0.705576 1.35279
4.99 1 0.921577 0.846373 1.42319

23
tests/lfo/lfo_waves.sfz Normal file
View file

@ -0,0 +1,23 @@
<region>
sample=*sine
lfo1_wave=0
lfo1_freq=1.0
lfo2_wave=1
lfo2_freq=2.0
lfo2_scale=0.8
lfo3_wave=2
lfo3_freq=1.0
lfo3_scale=0.5
lfo4_wave=3
lfo4_freq=2.0
lfo4_ratio=2
lfo5_wave=4
lfo5_freq=1.0
lfo5_offset=0.5
lfo6_wave=5
lfo6_freq=2.0
lfo7_wave=6
lfo7_freq=1.0
lfo7_phase=180
lfo8_wave=7
lfo8_freq=2.0

View file

@ -0,0 +1,500 @@
0 0 0 0.5 1 1.5 1 0 1
0.01 0.04 -0.12288 0.5 1 1.5 1 0.02 0.96
0.02 0.08 -0.23552 0.5 1 1.5 1 0.04 0.92
0.03 0.12 -0.33792 0.5 1 1.5 1 0.0599999 0.88
0.04 0.16 -0.43008 0.5 1 1.5 1 0.0799999 0.84
0.05 0.2 -0.512 0.5 1 1.5 1 0.0999999 0.8
0.06 0.24 -0.58368 0.5 1 1.5 1 0.12 0.76
0.07 0.28 -0.64512 0.5 1 1.5 -1 0.14 0.72
0.08 0.32 -0.69632 0.5 1 1.5 -1 0.16 0.68
0.09 0.36 -0.73728 0.5 1 1.5 -1 0.18 0.64
0.1 0.4 -0.768 0.5 1 1.5 -1 0.2 0.6
0.11 0.44 -0.78848 0.5 1 1.5 -1 0.22 0.56
0.12 0.48 -0.79872 0.5 1 1.5 -1 0.24 0.52
0.13 0.52 -0.79872 0.5 -1 1.5 -1 0.26 0.48
0.14 0.56 -0.78848 0.5 -1 1.5 -1 0.28 0.44
0.15 0.6 -0.768 0.5 -1 1.5 -1 0.3 0.4
0.16 0.64 -0.73728 0.5 -1 1.5 -1 0.32 0.36
0.17 0.68 -0.69632 0.5 -1 1.5 -1 0.34 0.32
0.18 0.72 -0.64512 0.5 -1 1.5 -1 0.36 0.28
0.19 0.76 -0.58368 0.5 -1 1.5 -1 0.38 0.24
0.2 0.8 -0.512 0.5 -1 1.5 -1 0.4 0.2
0.21 0.84 -0.43008 0.5 -1 1.5 -1 0.42 0.16
0.22 0.88 -0.33792 0.5 -1 1.5 -1 0.44 0.12
0.23 0.92 -0.23552 0.5 -1 1.5 -1 0.46 0.0799999
0.24 0.96 -0.12288 0.5 -1 1.5 -1 0.48 0.0399998
0.25 1 3.8147e-07 0.5 1 -0.5 -1 0.5 -1.19209e-07
0.26 0.96 0.12288 0.5 1 -0.5 -1 0.52 -0.0400001
0.27 0.92 0.23552 0.5 1 -0.5 -1 0.539999 -0.08
0.28 0.88 0.33792 0.5 1 -0.5 -1 0.559999 -0.12
0.29 0.84 0.43008 0.5 1 -0.5 -1 0.579999 -0.16
0.3 0.8 0.512 0.5 1 -0.5 -1 0.599999 -0.2
0.31 0.76 0.58368 0.5 1 -0.5 -1 0.619999 -0.24
0.32 0.72 0.64512 0.5 1 -0.5 -1 0.639999 -0.28
0.33 0.68 0.69632 0.5 1 -0.5 -1 0.659999 -0.32
0.34 0.64 0.73728 0.5 1 -0.5 -1 0.679999 -0.36
0.35 0.6 0.768 0.5 1 -0.5 -1 0.699999 -0.4
0.36 0.56 0.78848 0.5 1 -0.5 -1 0.719999 -0.44
0.37 0.52 0.79872 0.5 1 -0.5 -1 0.739999 -0.48
0.38 0.48 0.79872 0.5 -1 -0.5 -1 0.759999 -0.52
0.39 0.44 0.78848 0.5 -1 -0.5 -1 0.779999 -0.56
0.4 0.4 0.768 0.5 -1 -0.5 -1 0.799999 -0.6
0.41 0.36 0.73728 0.5 -1 -0.5 -1 0.819999 -0.64
0.42 0.320001 0.696321 0.5 -1 -0.5 -1 0.839999 -0.679999
0.43 0.280001 0.645121 0.5 -1 -0.5 -1 0.859999 -0.719999
0.44 0.240001 0.583681 0.5 -1 -0.5 -1 0.879999 -0.759999
0.45 0.200001 0.512001 0.5 -1 -0.5 -1 0.899999 -0.799999
0.46 0.160001 0.430081 0.5 -1 -0.5 -1 0.919999 -0.839999
0.47 0.120001 0.337922 0.5 -1 -0.5 -1 0.939999 -0.879999
0.48 0.0800008 0.235522 0.5 -1 -0.5 -1 0.959999 -0.919999
0.49 0.0400008 0.122882 0.5 -1 -0.5 -1 0.979999 -0.959999
0.5 8.34465e-07 2.67029e-06 0.5 1 -0.5 -1 0.999999 -0.999999
0.51 -0.0399992 -0.122878 0.5 1 -0.5 1 -0.980001 0.960001
0.52 -0.0799992 -0.235518 0.5 1 -0.5 1 -0.960001 0.920001
0.53 -0.119999 -0.337918 0.5 1 -0.5 1 -0.940001 0.880001
0.54 -0.159999 -0.430078 0.5 1 -0.5 1 -0.920001 0.840001
0.55 -0.199999 -0.511998 0.5 1 -0.5 1 -0.900001 0.800001
0.56 -0.239999 -0.583679 0.5 1 -0.5 1 -0.880001 0.760001
0.57 -0.279999 -0.645119 0.5 1 -0.5 -1 -0.860001 0.720001
0.58 -0.319999 -0.696319 0.5 1 -0.5 -1 -0.840001 0.680001
0.59 -0.359999 -0.737279 0.5 1 -0.5 -1 -0.820001 0.640001
0.6 -0.399999 -0.767999 0.5 1 -0.5 -1 -0.800001 0.600001
0.61 -0.439999 -0.78848 0.5 1 -0.5 -1 -0.780001 0.560001
0.62 -0.479999 -0.79872 0.5 1 -0.5 -1 -0.760001 0.520001
0.63 -0.519999 -0.79872 0.5 -1 -0.5 -1 -0.740001 0.480001
0.64 -0.559999 -0.78848 0.5 -1 -0.5 -1 -0.720001 0.440001
0.65 -0.599999 -0.768001 0.5 -1 -0.5 -1 -0.700001 0.400001
0.66 -0.639999 -0.737281 0.5 -1 -0.5 -1 -0.680001 0.360001
0.67 -0.679999 -0.696321 0.5 -1 -0.5 -1 -0.660001 0.320001
0.68 -0.719999 -0.645121 0.5 -1 -0.5 -1 -0.640001 0.280001
0.69 -0.759999 -0.583681 0.5 -1 -0.5 -1 -0.620001 0.240001
0.7 -0.799999 -0.512001 0.5 -1 -0.5 -1 -0.600001 0.200001
0.71 -0.839998 -0.430081 0.5 -1 -0.5 -1 -0.580001 0.160001
0.72 -0.879998 -0.337921 0.5 -1 -0.5 -1 -0.560001 0.120001
0.73 -0.919998 -0.235522 0.5 -1 -0.5 -1 -0.540001 0.0800006
0.74 -0.959998 -0.122882 0.5 -1 -0.5 -1 -0.520001 0.0400006
0.75 -0.999998 -1.71661e-06 0.5 1 -0.5 -1 -0.500001 5.36442e-07
0.76 -0.960002 0.122878 -0.5 1 -0.5 -1 -0.480001 -0.0399995
0.77 -0.920002 0.235519 -0.5 1 -0.5 -1 -0.460001 -0.0799994
0.78 -0.880002 0.337919 -0.5 1 -0.5 -1 -0.440001 -0.119999
0.79 -0.840002 0.430079 -0.5 1 -0.5 -1 -0.420001 -0.159999
0.8 -0.800002 0.511999 -0.5 1 -0.5 -1 -0.400001 -0.199999
0.81 -0.760002 0.583679 -0.5 1 -0.5 -1 -0.380001 -0.239999
0.82 -0.720002 0.645119 -0.5 1 -0.5 -1 -0.360001 -0.279999
0.83 -0.680002 0.696319 -0.5 1 -0.5 -1 -0.340001 -0.319999
0.84 -0.640002 0.737279 -0.5 1 -0.5 -1 -0.320001 -0.359999
0.85 -0.600002 0.767999 -0.5 1 -0.5 -1 -0.300001 -0.399999
0.86 -0.560002 0.78848 -0.5 1 -0.5 -1 -0.280001 -0.439999
0.87 -0.520002 0.79872 -0.5 1 -0.5 -1 -0.260001 -0.479999
0.88 -0.480002 0.79872 -0.5 -1 -0.5 -1 -0.240001 -0.519999
0.89 -0.440002 0.78848 -0.5 -1 -0.5 -1 -0.220001 -0.559999
0.9 -0.400002 0.768001 -0.5 -1 -0.5 -1 -0.200001 -0.599999
0.91 -0.360002 0.737281 -0.5 -1 -0.5 -1 -0.180001 -0.639999
0.92 -0.320002 0.696321 -0.5 -1 -0.5 -1 -0.160001 -0.679999
0.93 -0.280002 0.645122 -0.5 -1 -0.5 -1 -0.140001 -0.719999
0.94 -0.240002 0.583682 -0.5 -1 -0.5 -1 -0.120001 -0.759999
0.95 -0.200002 0.512002 -0.5 -1 -0.5 -1 -0.100001 -0.799999
0.96 -0.160002 0.430083 -0.5 -1 -0.5 -1 -0.0800012 -0.839999
0.97 -0.120003 0.337923 -0.5 -1 -0.5 -1 -0.0600013 -0.879999
0.98 -0.0800025 0.235524 -0.5 -1 -0.5 -1 -0.0400013 -0.919999
0.99 -0.0400026 0.122884 -0.5 -1 -0.5 -1 -0.0200013 -0.959999
1 -2.6226e-06 4.57763e-06 -0.5 1 -0.5 -1 -1.3113e-06 -0.999999
1.01 0.0399976 -0.122876 0.5 1 1.5 1 0.0199987 0.960001
1.02 0.0799976 -0.235516 0.5 1 1.5 1 0.0399987 0.920001
1.03 0.119998 -0.337916 0.5 1 1.5 1 0.0599986 0.880001
1.04 0.159998 -0.430077 0.5 1 1.5 1 0.0799986 0.840001
1.05 0.199998 -0.511997 0.5 1 1.5 1 0.0999986 0.800002
1.06 0.239998 -0.583678 0.5 1 1.5 1 0.119999 0.760001
1.07 0.279998 -0.645118 0.5 1 1.5 -1 0.139999 0.720001
1.08 0.319998 -0.696318 0.5 1 1.5 -1 0.159999 0.680001
1.09 0.359998 -0.737279 0.5 1 1.5 -1 0.179999 0.640002
1.1 0.399998 -0.767999 0.5 1 1.5 -1 0.199998 0.600002
1.11 0.439998 -0.788479 0.5 1 1.5 -1 0.219998 0.560001
1.12 0.479998 -0.79872 0.5 1 1.5 -1 0.239998 0.520002
1.13 0.519998 -0.79872 0.5 -1 1.5 -1 0.259998 0.480002
1.14 0.559998 -0.788481 0.5 -1 1.5 -1 0.279998 0.440001
1.15 0.599998 -0.768001 0.5 -1 1.5 -1 0.299998 0.400001
1.16 0.639998 -0.737281 0.5 -1 1.5 -1 0.319998 0.360001
1.17 0.679998 -0.696322 0.5 -1 1.5 -1 0.339998 0.320001
1.18 0.719998 -0.645122 0.5 -1 1.5 -1 0.359998 0.280001
1.19 0.759998 -0.583682 0.5 -1 1.5 -1 0.379998 0.240001
1.2 0.799998 -0.512003 0.5 -1 1.5 -1 0.399998 0.200001
1.21 0.839998 -0.430083 0.5 -1 1.5 -1 0.419998 0.160001
1.22 0.879998 -0.337923 0.5 -1 1.5 -1 0.439998 0.120001
1.23 0.919998 -0.235523 0.5 -1 1.5 -1 0.459998 0.0800013
1.24 0.959998 -0.122884 0.5 -1 1.5 -1 0.479998 0.0400013
1.25 0.999998 -4.00543e-06 0.5 1 1.5 -1 0.499998 1.2517e-06
1.26 0.960002 0.122876 0.5 1 -0.5 -1 0.519998 -0.0399988
1.27 0.920002 0.235517 0.5 1 -0.5 -1 0.539998 -0.0799987
1.28 0.880002 0.337917 0.5 1 -0.5 -1 0.559998 -0.119999
1.29 0.840002 0.430077 0.5 1 -0.5 -1 0.579998 -0.159999
1.3 0.800002 0.511997 0.5 1 -0.5 -1 0.599998 -0.199999
1.31 0.760002 0.583678 0.5 1 -0.5 -1 0.619998 -0.239999
1.32 0.720002 0.645118 0.5 1 -0.5 -1 0.639998 -0.279999
1.33 0.680002 0.696318 0.5 1 -0.5 -1 0.659998 -0.319999
1.34 0.640002 0.737279 0.5 1 -0.5 -1 0.679998 -0.359998
1.35 0.600003 0.767999 0.5 1 -0.5 -1 0.699998 -0.399998
1.36 0.560003 0.788479 0.5 1 -0.5 -1 0.719998 -0.439998
1.37 0.520003 0.79872 0.5 1 -0.5 -1 0.739998 -0.479998
1.38 0.480003 0.79872 0.5 -1 -0.5 -1 0.759998 -0.519998
1.39 0.440003 0.788481 0.5 -1 -0.5 -1 0.779998 -0.559998
1.4 0.400003 0.768001 0.5 -1 -0.5 -1 0.799998 -0.599998
1.41 0.360003 0.737282 0.5 -1 -0.5 -1 0.819998 -0.639998
1.42 0.320003 0.696322 0.5 -1 -0.5 -1 0.839998 -0.679998
1.43 0.280003 0.645123 0.5 -1 -0.5 -1 0.859998 -0.719998
1.44 0.240003 0.583683 0.5 -1 -0.5 -1 0.879998 -0.759998
1.45 0.200003 0.512004 0.5 -1 -0.5 -1 0.899998 -0.799998
1.46 0.160003 0.430084 0.5 -1 -0.5 -1 0.919998 -0.839998
1.47 0.120003 0.337925 0.5 -1 -0.5 -1 0.939998 -0.879998
1.48 0.080003 0.235526 0.5 -1 -0.5 -1 0.959998 -0.919998
1.49 0.0400031 0.122886 0.5 -1 -0.5 -1 0.979998 -0.959998
1.5 3.09944e-06 6.86644e-06 0.5 1 -0.5 -1 0.999998 -0.999998
1.51 -0.0399969 -0.122874 0.5 1 -0.5 1 -0.980002 0.960002
1.52 -0.0799968 -0.235514 0.5 1 -0.5 1 -0.960002 0.920002
1.53 -0.119997 -0.337915 0.5 1 -0.5 1 -0.940002 0.880002
1.54 -0.159997 -0.430075 0.5 1 -0.5 1 -0.920002 0.840002
1.55 -0.199997 -0.511996 0.5 1 -0.5 1 -0.900002 0.800002
1.56 -0.239997 -0.583676 0.5 1 -0.5 1 -0.880002 0.760002
1.57 -0.279997 -0.645117 0.5 1 -0.5 -1 -0.860002 0.720002
1.58 -0.319997 -0.696317 0.5 1 -0.5 -1 -0.840002 0.680002
1.59 -0.359997 -0.737278 0.5 1 -0.5 -1 -0.820002 0.640002
1.6 -0.399997 -0.767999 0.5 1 -0.5 -1 -0.800002 0.600002
1.61 -0.439996 -0.788479 0.5 1 -0.5 -1 -0.780002 0.560002
1.62 -0.479996 -0.79872 0.5 1 -0.5 -1 -0.760002 0.520002
1.63 -0.519996 -0.79872 0.5 -1 -0.5 -1 -0.740002 0.480002
1.64 -0.559996 -0.788481 0.5 -1 -0.5 -1 -0.720002 0.440002
1.65 -0.599996 -0.768001 0.5 -1 -0.5 -1 -0.700002 0.400002
1.66 -0.639996 -0.737282 0.5 -1 -0.5 -1 -0.680002 0.360002
1.67 -0.679996 -0.696322 0.5 -1 -0.5 -1 -0.660002 0.320002
1.68 -0.719996 -0.645123 0.5 -1 -0.5 -1 -0.640002 0.280002
1.69 -0.759996 -0.583683 0.5 -1 -0.5 -1 -0.620002 0.240002
1.7 -0.799996 -0.512004 0.5 -1 -0.5 -1 -0.600002 0.200002
1.71 -0.839996 -0.430084 0.5 -1 -0.5 -1 -0.580002 0.160002
1.72 -0.879996 -0.337925 0.5 -1 -0.5 -1 -0.560002 0.120002
1.73 -0.919996 -0.235525 0.5 -1 -0.5 -1 -0.540002 0.080002
1.74 -0.959996 -0.122886 0.5 -1 -0.5 -1 -0.520002 0.040002
1.75 -0.999996 -6.29424e-06 0.5 1 -0.5 -1 -0.500002 1.96695e-06
1.76 -0.960004 0.122874 -0.5 1 -0.5 -1 -0.480002 -0.0399981
1.77 -0.920004 0.235515 -0.5 1 -0.5 -1 -0.460002 -0.079998
1.78 -0.880004 0.337915 -0.5 1 -0.5 -1 -0.440002 -0.119998
1.79 -0.840004 0.430076 -0.5 1 -0.5 -1 -0.420002 -0.159998
1.8 -0.800004 0.511996 -0.5 1 -0.5 -1 -0.400002 -0.199998
1.81 -0.760004 0.583676 -0.5 1 -0.5 -1 -0.380002 -0.239998
1.82 -0.720004 0.645117 -0.5 1 -0.5 -1 -0.360002 -0.279998
1.83 -0.680004 0.696317 -0.5 1 -0.5 -1 -0.340002 -0.319998
1.84 -0.640004 0.737278 -0.5 1 -0.5 -1 -0.320002 -0.359998
1.85 -0.600004 0.767999 -0.5 1 -0.5 -1 -0.300002 -0.399998
1.86 -0.560004 0.788479 -0.5 1 -0.5 -1 -0.280002 -0.439998
1.87 -0.520005 0.79872 -0.5 1 -0.5 -1 -0.260002 -0.479998
1.88 -0.480005 0.79872 -0.5 -1 -0.5 -1 -0.240002 -0.519998
1.89 -0.440005 0.788481 -0.5 -1 -0.5 -1 -0.220002 -0.559998
1.9 -0.400005 0.768002 -0.5 -1 -0.5 -1 -0.200002 -0.599998
1.91 -0.360005 0.737282 -0.5 -1 -0.5 -1 -0.180002 -0.639997
1.92 -0.320005 0.696323 -0.5 -1 -0.5 -1 -0.160002 -0.679997
1.93 -0.280005 0.645124 -0.5 -1 -0.5 -1 -0.140002 -0.719997
1.94 -0.240005 0.583684 -0.5 -1 -0.5 -1 -0.120002 -0.759997
1.95 -0.200005 0.512005 -0.5 -1 -0.5 -1 -0.100002 -0.799997
1.96 -0.160005 0.430086 -0.5 -1 -0.5 -1 -0.0800024 -0.839997
1.97 -0.120005 0.337927 -0.5 -1 -0.5 -1 -0.0600024 -0.879997
1.98 -0.0800049 0.235527 -0.5 -1 -0.5 -1 -0.0400025 -0.919997
1.99 -0.040005 0.122888 -0.5 -1 -0.5 -1 -0.0200025 -0.959997
2 -5.00679e-06 9.15525e-06 -0.5 1 -0.5 -1 -2.5034e-06 -0.999997
2.01 0.0399952 -0.122871 0.5 1 1.5 1 0.0199975 0.960003
2.02 0.0799952 -0.235512 0.5 1 1.5 1 0.0399975 0.920003
2.03 0.119995 -0.337913 0.5 1 1.5 1 0.0599974 0.880003
2.04 0.159995 -0.430074 0.5 1 1.5 1 0.0799974 0.840003
2.05 0.199995 -0.511994 0.5 1 1.5 1 0.0999974 0.800003
2.06 0.239995 -0.583675 0.5 1 1.5 1 0.119997 0.760003
2.07 0.279995 -0.645116 0.5 1 1.5 -1 0.139997 0.720003
2.08 0.319995 -0.696317 0.5 1 1.5 -1 0.159997 0.680003
2.09 0.359995 -0.737277 0.5 1 1.5 -1 0.179997 0.640003
2.1 0.399995 -0.767998 0.5 1 1.5 -1 0.199997 0.600003
2.11 0.439995 -0.788479 0.5 1 1.5 -1 0.219997 0.560003
2.12 0.479995 -0.79872 0.5 1 1.5 -1 0.239997 0.520003
2.13 0.519995 -0.79872 0.5 -1 1.5 -1 0.259997 0.480003
2.14 0.559995 -0.788481 0.5 -1 1.5 -1 0.279997 0.440003
2.15 0.599995 -0.768002 0.5 -1 1.5 -1 0.299997 0.400003
2.16 0.639995 -0.737283 0.5 -1 1.5 -1 0.319997 0.360003
2.17 0.679995 -0.696323 0.5 -1 1.5 -1 0.339997 0.320003
2.18 0.719995 -0.645124 0.5 -1 1.5 -1 0.359997 0.280003
2.19 0.759995 -0.583685 0.5 -1 1.5 -1 0.379997 0.240003
2.2 0.799995 -0.512005 0.5 -1 1.5 -1 0.399997 0.200003
2.21 0.839995 -0.430086 0.5 -1 1.5 -1 0.419997 0.160003
2.22 0.879995 -0.337927 0.5 -1 1.5 -1 0.439997 0.120003
2.23 0.919995 -0.235527 0.5 -1 1.5 -1 0.459997 0.0800027
2.24 0.959995 -0.122888 0.5 -1 1.5 -1 0.479997 0.0400027
2.25 0.999995 -8.58305e-06 0.5 1 1.5 -1 0.499997 2.68221e-06
2.26 0.960005 0.122872 0.5 1 -0.5 -1 0.519997 -0.0399973
2.27 0.920005 0.235513 0.5 1 -0.5 -1 0.539997 -0.0799973
2.28 0.880005 0.337913 0.5 1 -0.5 -1 0.559997 -0.119997
2.29 0.840005 0.430074 0.5 1 -0.5 -1 0.579997 -0.159997
2.3 0.800005 0.511995 0.5 1 -0.5 -1 0.599997 -0.199997
2.31 0.760005 0.583675 0.5 1 -0.5 -1 0.619997 -0.239997
2.32 0.720005 0.645116 0.5 1 -0.5 -1 0.639997 -0.279997
2.33 0.680005 0.696317 0.5 1 -0.5 -1 0.659997 -0.319997
2.34 0.640005 0.737277 0.5 1 -0.5 -1 0.679997 -0.359997
2.35 0.600005 0.767998 0.5 1 -0.5 -1 0.699997 -0.399997
2.36 0.560005 0.788479 0.5 1 -0.5 -1 0.719997 -0.439997
2.37 0.520005 0.79872 0.5 1 -0.5 -1 0.739997 -0.479997
2.38 0.480005 0.79872 0.5 -1 -0.5 -1 0.759997 -0.519997
2.39 0.440005 0.788481 0.5 -1 -0.5 -1 0.779997 -0.559997
2.4 0.400005 0.768002 0.5 -1 -0.5 -1 0.799997 -0.599997
2.41 0.360005 0.737283 0.5 -1 -0.5 -1 0.819997 -0.639997
2.42 0.320005 0.696324 0.5 -1 -0.5 -1 0.839997 -0.679997
2.43 0.280005 0.645125 0.5 -1 -0.5 -1 0.859997 -0.719997
2.44 0.240005 0.583686 0.5 -1 -0.5 -1 0.879997 -0.759997
2.45 0.200005 0.512007 0.5 -1 -0.5 -1 0.899997 -0.799997
2.46 0.160005 0.430087 0.5 -1 -0.5 -1 0.919997 -0.839997
2.47 0.120005 0.337928 0.5 -1 -0.5 -1 0.939997 -0.879997
2.48 0.0800054 0.235529 0.5 -1 -0.5 -1 0.959997 -0.919997
2.49 0.0400054 0.12289 0.5 -1 -0.5 -1 0.979997 -0.959996
2.5 5.48363e-06 1.14441e-05 0.5 1 -0.5 -1 0.999997 -0.999996
2.51 -0.0399945 -0.122869 0.5 1 -0.5 1 -0.980003 0.960004
2.52 -0.0799944 -0.23551 0.5 1 -0.5 1 -0.960003 0.920004
2.53 -0.119994 -0.337911 0.5 1 -0.5 1 -0.940003 0.880004
2.54 -0.159994 -0.430072 0.5 1 -0.5 1 -0.920003 0.840004
2.55 -0.199994 -0.511993 0.5 1 -0.5 1 -0.900003 0.800004
2.56 -0.239994 -0.583674 0.5 1 -0.5 1 -0.880003 0.760004
2.57 -0.279994 -0.645115 0.5 1 -0.5 -1 -0.860003 0.720004
2.58 -0.319994 -0.696316 0.5 1 -0.5 -1 -0.840003 0.680004
2.59 -0.359994 -0.737277 0.5 1 -0.5 -1 -0.820003 0.640004
2.6 -0.399994 -0.767998 0.5 1 -0.5 -1 -0.800003 0.600004
2.61 -0.439994 -0.788479 0.5 1 -0.5 -1 -0.780003 0.560004
2.62 -0.479994 -0.79872 0.5 1 -0.5 -1 -0.760003 0.520004
2.63 -0.519994 -0.79872 0.5 -1 -0.5 -1 -0.740003 0.480004
2.64 -0.559994 -0.788481 0.5 -1 -0.5 -1 -0.720003 0.440004
2.65 -0.599994 -0.768002 0.5 -1 -0.5 -1 -0.700003 0.400004
2.66 -0.639994 -0.737283 0.5 -1 -0.5 -1 -0.680003 0.360004
2.67 -0.679994 -0.696324 0.5 -1 -0.5 -1 -0.660003 0.320004
2.68 -0.719994 -0.645125 0.5 -1 -0.5 -1 -0.640003 0.280004
2.69 -0.759994 -0.583686 0.5 -1 -0.5 -1 -0.620003 0.240004
2.7 -0.799994 -0.512007 0.5 -1 -0.5 -1 -0.600003 0.200004
2.71 -0.839994 -0.430088 0.5 -1 -0.5 -1 -0.580003 0.160003
2.72 -0.879994 -0.337928 0.5 -1 -0.5 -1 -0.560003 0.120003
2.73 -0.919994 -0.235529 0.5 -1 -0.5 -1 -0.540003 0.0800034
2.74 -0.959994 -0.12289 0.5 -1 -0.5 -1 -0.520003 0.0400034
2.75 -0.999994 -1.08719e-05 0.5 1 -0.5 -1 -0.500003 3.39746e-06
2.76 -0.960006 0.12287 -0.5 1 -0.5 -1 -0.480003 -0.0399966
2.77 -0.920007 0.235511 -0.5 1 -0.5 -1 -0.460003 -0.0799966
2.78 -0.880007 0.337912 -0.5 1 -0.5 -1 -0.440003 -0.119997
2.79 -0.840007 0.430072 -0.5 1 -0.5 -1 -0.420003 -0.159997
2.8 -0.800007 0.511993 -0.5 1 -0.5 -1 -0.400003 -0.199996
2.81 -0.760007 0.583674 -0.5 1 -0.5 -1 -0.380003 -0.239996
2.82 -0.720007 0.645115 -0.5 1 -0.5 -1 -0.360003 -0.279996
2.83 -0.680007 0.696316 -0.5 1 -0.5 -1 -0.340003 -0.319996
2.84 -0.640007 0.737277 -0.5 1 -0.5 -1 -0.320003 -0.359996
2.85 -0.600007 0.767998 -0.5 1 -0.5 -1 -0.300003 -0.399996
2.86 -0.560007 0.788479 -0.5 1 -0.5 -1 -0.280003 -0.439996
2.87 -0.520007 0.79872 -0.5 1 -0.5 -1 -0.260003 -0.479996
2.88 -0.480007 0.79872 -0.5 -1 -0.5 -1 -0.240003 -0.519996
2.89 -0.440007 0.788482 -0.5 -1 -0.5 -1 -0.220003 -0.559996
2.9 -0.400007 0.768003 -0.5 -1 -0.5 -1 -0.200004 -0.599996
2.91 -0.360007 0.737284 -0.5 -1 -0.5 -1 -0.180004 -0.639996
2.92 -0.320007 0.696325 -0.5 -1 -0.5 -1 -0.160004 -0.679996
2.93 -0.280007 0.645126 -0.5 -1 -0.5 -1 -0.140004 -0.719996
2.94 -0.240007 0.583687 -0.5 -1 -0.5 -1 -0.120004 -0.759996
2.95 -0.200007 0.512008 -0.5 -1 -0.5 -1 -0.100004 -0.799996
2.96 -0.160007 0.430089 -0.5 -1 -0.5 -1 -0.0800036 -0.839996
2.97 -0.120007 0.33793 -0.5 -1 -0.5 -1 -0.0600036 -0.879996
2.98 -0.0800073 0.235531 -0.5 -1 -0.5 -1 -0.0400037 -0.919996
2.99 -0.0400074 0.122893 -0.5 -1 -0.5 -1 -0.0200037 -0.959996
3 -7.39098e-06 1.37329e-05 -0.5 1 -0.5 -1 -3.69549e-06 -0.999996
3.01 0.0399928 -0.122867 0.5 1 1.5 1 0.0199963 0.960004
3.02 0.0799928 -0.235508 0.5 1 1.5 1 0.0399963 0.920004
3.03 0.119993 -0.337909 0.5 1 1.5 1 0.0599962 0.880004
3.04 0.159993 -0.430071 0.5 1 1.5 1 0.0799962 0.840004
3.05 0.199993 -0.511992 0.5 1 1.5 1 0.0999962 0.800004
3.06 0.239993 -0.583673 0.5 1 1.5 1 0.119996 0.760004
3.07 0.279993 -0.645114 0.5 1 1.5 -1 0.139996 0.720004
3.08 0.319993 -0.696315 0.5 1 1.5 -1 0.159996 0.680004
3.09 0.359993 -0.737276 0.5 1 1.5 -1 0.179996 0.640004
3.1 0.399993 -0.767997 0.5 1 1.5 -1 0.199996 0.600004
3.11 0.439993 -0.788478 0.5 1 1.5 -1 0.219996 0.560004
3.12 0.479993 -0.798719 0.5 1 1.5 -1 0.239996 0.520004
3.13 0.519993 -0.798721 0.5 -1 1.5 -1 0.259996 0.480004
3.14 0.559993 -0.788482 0.5 -1 1.5 -1 0.279996 0.440004
3.15 0.599993 -0.768003 0.5 -1 1.5 -1 0.299996 0.400004
3.16 0.639993 -0.737284 0.5 -1 1.5 -1 0.319996 0.360004
3.17 0.679993 -0.696325 0.5 -1 1.5 -1 0.339996 0.320004
3.18 0.719993 -0.645126 0.5 -1 1.5 -1 0.359996 0.280004
3.19 0.759993 -0.583687 0.5 -1 1.5 -1 0.379996 0.240004
3.2 0.799993 -0.512008 0.5 -1 1.5 -1 0.399996 0.200004
3.21 0.839993 -0.430089 0.5 -1 1.5 -1 0.419996 0.160004
3.22 0.879993 -0.33793 0.5 -1 1.5 -1 0.439996 0.120004
3.23 0.919993 -0.235531 0.5 -1 1.5 -1 0.459996 0.0800042
3.24 0.959993 -0.122892 0.5 -1 1.5 -1 0.479996 0.0400041
3.25 0.999993 -1.31607e-05 0.5 1 1.5 -1 0.499996 4.11272e-06
3.26 0.960007 0.122868 0.5 1 -0.5 -1 0.519996 -0.0399959
3.27 0.920007 0.235509 0.5 1 -0.5 -1 0.539996 -0.0799959
3.28 0.880007 0.33791 0.5 1 -0.5 -1 0.559996 -0.119996
3.29 0.840007 0.430071 0.5 1 -0.5 -1 0.579996 -0.159996
3.3 0.800007 0.511992 0.5 1 -0.5 -1 0.599996 -0.199996
3.31 0.760007 0.583673 0.5 1 -0.5 -1 0.619996 -0.239996
3.32 0.720007 0.645114 0.5 1 -0.5 -1 0.639996 -0.279996
3.33 0.680007 0.696315 0.5 1 -0.5 -1 0.659996 -0.319996
3.34 0.640007 0.737276 0.5 1 -0.5 -1 0.679996 -0.359996
3.35 0.600007 0.767997 0.5 1 -0.5 -1 0.699996 -0.399996
3.36 0.560007 0.788478 0.5 1 -0.5 -1 0.719996 -0.439996
3.37 0.520007 0.798719 0.5 1 -0.5 -1 0.739996 -0.479995
3.38 0.480007 0.798721 0.5 -1 -0.5 -1 0.759996 -0.519995
3.39 0.440007 0.788482 0.5 -1 -0.5 -1 0.779996 -0.559995
3.4 0.400007 0.768003 0.5 -1 -0.5 -1 0.799996 -0.599995
3.41 0.360008 0.737284 0.5 -1 -0.5 -1 0.819996 -0.639995
3.42 0.320008 0.696325 0.5 -1 -0.5 -1 0.839996 -0.679995
3.43 0.280008 0.645127 0.5 -1 -0.5 -1 0.859995 -0.719995
3.44 0.240008 0.583688 0.5 -1 -0.5 -1 0.879995 -0.759995
3.45 0.200008 0.512009 0.5 -1 -0.5 -1 0.899995 -0.799995
3.46 0.160008 0.430091 0.5 -1 -0.5 -1 0.919995 -0.839995
3.47 0.120008 0.337932 0.5 -1 -0.5 -1 0.939995 -0.879995
3.48 0.0800078 0.235533 0.5 -1 -0.5 -1 0.959995 -0.919995
3.49 0.0400078 0.122895 0.5 -1 -0.5 -1 0.979995 -0.959995
3.5 7.86781e-06 1.60216e-05 0.5 1 -0.5 -1 0.999995 -0.999995
3.51 -0.0399921 -0.122865 0.5 1 -0.5 1 -0.980005 0.960005
3.52 -0.0799921 -0.235507 0.5 1 -0.5 1 -0.960005 0.920005
3.53 -0.119992 -0.337908 0.5 1 -0.5 1 -0.940005 0.880005
3.54 -0.159992 -0.430069 0.5 1 -0.5 1 -0.920005 0.840005
3.55 -0.199992 -0.51199 0.5 1 -0.5 1 -0.900005 0.800005
3.56 -0.239992 -0.583672 0.5 1 -0.5 1 -0.880005 0.760005
3.57 -0.279992 -0.645113 0.5 1 -0.5 -1 -0.860005 0.720005
3.58 -0.319992 -0.696314 0.5 1 -0.5 -1 -0.840005 0.680005
3.59 -0.359992 -0.737275 0.5 1 -0.5 -1 -0.820005 0.640005
3.6 -0.399992 -0.767997 0.5 1 -0.5 -1 -0.800005 0.600005
3.61 -0.439992 -0.788478 0.5 1 -0.5 -1 -0.780005 0.560005
3.62 -0.479992 -0.798719 0.5 1 -0.5 -1 -0.760005 0.520005
3.63 -0.519992 -0.798721 0.5 -1 -0.5 -1 -0.740005 0.480005
3.64 -0.559992 -0.788482 0.5 -1 -0.5 -1 -0.720005 0.440005
3.65 -0.599992 -0.768003 0.5 -1 -0.5 -1 -0.700005 0.400005
3.66 -0.639992 -0.737284 0.5 -1 -0.5 -1 -0.680005 0.360005
3.67 -0.679991 -0.696326 0.5 -1 -0.5 -1 -0.660004 0.320005
3.68 -0.719991 -0.645127 0.5 -1 -0.5 -1 -0.640005 0.280005
3.69 -0.759991 -0.583688 0.5 -1 -0.5 -1 -0.620005 0.240005
3.7 -0.799991 -0.512009 0.5 -1 -0.5 -1 -0.600004 0.200005
3.71 -0.839991 -0.430091 0.5 -1 -0.5 -1 -0.580004 0.160005
3.72 -0.879991 -0.337932 0.5 -1 -0.5 -1 -0.560004 0.120005
3.73 -0.919991 -0.235533 0.5 -1 -0.5 -1 -0.540004 0.0800049
3.74 -0.959991 -0.122894 0.5 -1 -0.5 -1 -0.520004 0.0400048
3.75 -0.999991 -1.54495e-05 0.5 1 -0.5 -1 -0.500004 4.82798e-06
3.76 -0.960009 0.122866 -0.5 1 -0.5 -1 -0.480004 -0.0399952
3.77 -0.920009 0.235507 -0.5 1 -0.5 -1 -0.460004 -0.0799952
3.78 -0.880009 0.337908 -0.5 1 -0.5 -1 -0.440004 -0.119995
3.79 -0.840009 0.430069 -0.5 1 -0.5 -1 -0.420004 -0.159995
3.8 -0.800009 0.51199 -0.5 1 -0.5 -1 -0.400005 -0.199995
3.81 -0.760009 0.583672 -0.5 1 -0.5 -1 -0.380005 -0.239995
3.82 -0.720009 0.645113 -0.5 1 -0.5 -1 -0.360005 -0.279995
3.83 -0.680009 0.696314 -0.5 1 -0.5 -1 -0.340005 -0.319995
3.84 -0.640009 0.737275 -0.5 1 -0.5 -1 -0.320005 -0.359995
3.85 -0.600009 0.767997 -0.5 1 -0.5 -1 -0.300005 -0.399995
3.86 -0.560009 0.788478 -0.5 1 -0.5 -1 -0.280005 -0.439995
3.87 -0.520009 0.798719 -0.5 1 -0.5 -1 -0.260005 -0.479995
3.88 -0.480009 0.798721 -0.5 -1 -0.5 -1 -0.240005 -0.519995
3.89 -0.440009 0.788482 -0.5 -1 -0.5 -1 -0.220005 -0.559995
3.9 -0.400009 0.768003 -0.5 -1 -0.5 -1 -0.200005 -0.599995
3.91 -0.360009 0.737285 -0.5 -1 -0.5 -1 -0.180005 -0.639995
3.92 -0.320009 0.696326 -0.5 -1 -0.5 -1 -0.160005 -0.679995
3.93 -0.28001 0.645128 -0.5 -1 -0.5 -1 -0.140005 -0.719995
3.94 -0.24001 0.583689 -0.5 -1 -0.5 -1 -0.120005 -0.759995
3.95 -0.20001 0.512011 -0.5 -1 -0.5 -1 -0.100005 -0.799994
3.96 -0.16001 0.430092 -0.5 -1 -0.5 -1 -0.0800048 -0.839994
3.97 -0.12001 0.337934 -0.5 -1 -0.5 -1 -0.0600048 -0.879994
3.98 -0.0800097 0.235535 -0.5 -1 -0.5 -1 -0.0400048 -0.919994
3.99 -0.0400097 0.122897 -0.5 -1 -0.5 -1 -0.0200049 -0.959994
4 -9.77516e-06 1.83104e-05 -0.5 1 -0.5 -1 -4.88758e-06 -0.999994
4.01 0.0399904 -0.122863 0.5 1 1.5 1 0.0199951 0.960006
4.02 0.0799904 -0.235505 0.5 1 1.5 1 0.0399951 0.920006
4.03 0.11999 -0.337906 0.5 1 1.5 1 0.0599951 0.880006
4.04 0.15999 -0.430068 0.5 1 1.5 1 0.079995 0.840006
4.05 0.19999 -0.511989 0.5 1 1.5 1 0.099995 0.800006
4.06 0.23999 -0.58367 0.5 1 1.5 1 0.119995 0.760006
4.07 0.27999 -0.645112 0.5 1 1.5 -1 0.139995 0.720006
4.08 0.31999 -0.696313 0.5 1 1.5 -1 0.159995 0.680006
4.09 0.35999 -0.737275 0.5 1 1.5 -1 0.179995 0.640006
4.1 0.39999 -0.767996 0.5 1 1.5 -1 0.199995 0.600006
4.11 0.43999 -0.788478 0.5 1 1.5 -1 0.219995 0.560006
4.12 0.47999 -0.798719 0.5 1 1.5 -1 0.239995 0.520006
4.13 0.51999 -0.798721 0.5 -1 1.5 -1 0.259995 0.480006
4.14 0.55999 -0.788482 0.5 -1 1.5 -1 0.279995 0.440006
4.15 0.59999 -0.768004 0.5 -1 1.5 -1 0.299995 0.400006
4.16 0.63999 -0.737285 0.5 -1 1.5 -1 0.319995 0.360006
4.17 0.67999 -0.696327 0.5 -1 1.5 -1 0.339995 0.320006
4.18 0.71999 -0.645128 0.5 -1 1.5 -1 0.359995 0.280006
4.19 0.759991 -0.583689 0.5 -1 1.5 -1 0.379995 0.240006
4.2 0.799991 -0.512011 0.5 -1 1.5 -1 0.399995 0.200006
4.21 0.839991 -0.430092 0.5 -1 1.5 -1 0.419995 0.160006
4.22 0.879991 -0.337934 0.5 -1 1.5 -1 0.439995 0.120006
4.23 0.919991 -0.235535 0.5 -1 1.5 -1 0.459995 0.0800056
4.24 0.959991 -0.122896 0.5 -1 1.5 -1 0.479995 0.0400056
4.25 0.999991 -1.77382e-05 0.5 1 1.5 -1 0.499995 5.54323e-06
4.26 0.960009 0.122864 0.5 1 -0.5 -1 0.519995 -0.0399945
4.27 0.920009 0.235505 0.5 1 -0.5 -1 0.539995 -0.0799944
4.28 0.880009 0.337906 0.5 1 -0.5 -1 0.559995 -0.119994
4.29 0.840009 0.430068 0.5 1 -0.5 -1 0.579995 -0.159994
4.3 0.800009 0.511989 0.5 1 -0.5 -1 0.599995 -0.199994
4.31 0.76001 0.58367 0.5 1 -0.5 -1 0.619995 -0.239994
4.32 0.72001 0.645112 0.5 1 -0.5 -1 0.639995 -0.279994
4.33 0.68001 0.696313 0.5 1 -0.5 -1 0.659994 -0.319994
4.34 0.64001 0.737275 0.5 1 -0.5 -1 0.679994 -0.359994
4.35 0.60001 0.767996 0.5 1 -0.5 -1 0.699994 -0.399994
4.36 0.56001 0.788478 0.5 1 -0.5 -1 0.719994 -0.439994
4.37 0.52001 0.798719 0.5 1 -0.5 -1 0.739994 -0.479994
4.38 0.48001 0.798721 0.5 -1 -0.5 -1 0.759994 -0.519994
4.39 0.44001 0.788482 0.5 -1 -0.5 -1 0.779994 -0.559994
4.4 0.40001 0.768004 0.5 -1 -0.5 -1 0.799994 -0.599994
4.41 0.36001 0.737285 0.5 -1 -0.5 -1 0.819994 -0.639994
4.42 0.32001 0.696327 0.5 -1 -0.5 -1 0.839994 -0.679994
4.43 0.28001 0.645129 0.5 -1 -0.5 -1 0.859994 -0.719994
4.44 0.24001 0.58369 0.5 -1 -0.5 -1 0.879994 -0.759994
4.45 0.20001 0.512012 0.5 -1 -0.5 -1 0.899994 -0.799994
4.46 0.16001 0.430094 0.5 -1 -0.5 -1 0.919994 -0.839994
4.47 0.12001 0.337935 0.5 -1 -0.5 -1 0.939994 -0.879994
4.48 0.0800102 0.235537 0.5 -1 -0.5 -1 0.959994 -0.919994
4.49 0.0400102 0.122899 0.5 -1 -0.5 -1 0.979994 -0.959994
4.5 1.0252e-05 2.05992e-05 0.5 1 -0.5 -1 0.999994 -0.999994
4.51 -0.0399897 -0.122861 0.5 1 -0.5 1 -0.980006 0.960006
4.52 -0.0799897 -0.235503 0.5 1 -0.5 1 -0.960006 0.920006
4.53 -0.11999 -0.337904 0.5 1 -0.5 1 -0.940006 0.880006
4.54 -0.15999 -0.430066 0.5 1 -0.5 1 -0.920006 0.840006
4.55 -0.19999 -0.511988 0.5 1 -0.5 1 -0.900006 0.800007
4.56 -0.23999 -0.583669 0.5 1 -0.5 1 -0.880006 0.760006
4.57 -0.279989 -0.645111 0.5 1 -0.5 -1 -0.860006 0.720006
4.58 -0.319989 -0.696313 0.5 1 -0.5 -1 -0.840006 0.680007
4.59 -0.359989 -0.737274 0.5 1 -0.5 -1 -0.820006 0.640007
4.6 -0.399989 -0.767996 0.5 1 -0.5 -1 -0.800006 0.600007
4.61 -0.439989 -0.788477 0.5 1 -0.5 -1 -0.780006 0.560006
4.62 -0.479989 -0.798719 0.5 1 -0.5 -1 -0.760006 0.520007
4.63 -0.519989 -0.798721 0.5 -1 -0.5 -1 -0.740006 0.480007
4.64 -0.559989 -0.788483 0.5 -1 -0.5 -1 -0.720006 0.440006
4.65 -0.599989 -0.768004 0.5 -1 -0.5 -1 -0.700006 0.400006
4.66 -0.639989 -0.737286 0.5 -1 -0.5 -1 -0.680006 0.360006
4.67 -0.679989 -0.696327 0.5 -1 -0.5 -1 -0.660006 0.320006
4.68 -0.719989 -0.645129 0.5 -1 -0.5 -1 -0.640006 0.280006
4.69 -0.759989 -0.583691 0.5 -1 -0.5 -1 -0.620006 0.240006
4.7 -0.799989 -0.512012 0.5 -1 -0.5 -1 -0.600006 0.200006
4.71 -0.839989 -0.430094 0.5 -1 -0.5 -1 -0.580006 0.160006
4.72 -0.879989 -0.337935 0.5 -1 -0.5 -1 -0.560006 0.120006
4.73 -0.919989 -0.235537 0.5 -1 -0.5 -1 -0.540006 0.0800063
4.74 -0.959989 -0.122898 0.5 -1 -0.5 -1 -0.520006 0.0400063
4.75 -0.999989 -2.0027e-05 0.5 1 -0.5 -1 -0.500006 6.25849e-06
4.76 -0.960011 0.122862 -0.5 1 -0.5 -1 -0.480006 -0.0399938
4.77 -0.920011 0.235503 -0.5 1 -0.5 -1 -0.460006 -0.0799937
4.78 -0.880011 0.337905 -0.5 1 -0.5 -1 -0.440006 -0.119994
4.79 -0.840011 0.430066 -0.5 1 -0.5 -1 -0.420006 -0.159994
4.8 -0.800011 0.511988 -0.5 1 -0.5 -1 -0.400006 -0.199994
4.81 -0.760011 0.583669 -0.5 1 -0.5 -1 -0.380006 -0.239994
4.82 -0.720011 0.645111 -0.5 1 -0.5 -1 -0.360006 -0.279994
4.83 -0.680012 0.696312 -0.5 1 -0.5 -1 -0.340006 -0.319993
4.84 -0.640012 0.737274 -0.5 1 -0.5 -1 -0.320006 -0.359993
4.85 -0.600012 0.767996 -0.5 1 -0.5 -1 -0.300006 -0.399993
4.86 -0.560012 0.788477 -0.5 1 -0.5 -1 -0.280006 -0.439993
4.87 -0.520012 0.798719 -0.5 1 -0.5 -1 -0.260006 -0.479993
4.88 -0.480012 0.798721 -0.5 -1 -0.5 -1 -0.240006 -0.519993
4.89 -0.440012 0.788483 -0.5 -1 -0.5 -1 -0.220006 -0.559993
4.9 -0.400012 0.768004 -0.5 -1 -0.5 -1 -0.200006 -0.599993
4.91 -0.360012 0.737286 -0.5 -1 -0.5 -1 -0.180006 -0.639993
4.92 -0.320012 0.696328 -0.5 -1 -0.5 -1 -0.160006 -0.679993
4.93 -0.280012 0.64513 -0.5 -1 -0.5 -1 -0.140006 -0.719993
4.94 -0.240012 0.583692 -0.5 -1 -0.5 -1 -0.120006 -0.759993
4.95 -0.200012 0.512013 -0.5 -1 -0.5 -1 -0.100006 -0.799993
4.96 -0.160012 0.430095 -0.5 -1 -0.5 -1 -0.080006 -0.839993
4.97 -0.120012 0.337937 -0.5 -1 -0.5 -1 -0.060006 -0.879993
4.98 -0.0800121 0.235539 -0.5 -1 -0.5 -1 -0.040006 -0.919993
4.99 -0.0400121 0.122901 -0.5 -1 -0.5 -1 -0.0200061 -0.959993

51
tests/lfo/plot_lfo.py Executable file
View file

@ -0,0 +1,51 @@
#!/usr/bin/env python3
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
from argparse import ArgumentParser
import os
parser = ArgumentParser(usage="Compare 2 files as outputted by sfizz_plot_lfo")
parser.add_argument("file", help="The file to test")
parser.add_argument("reference", help="The reference file")
args = parser.parse_args()
assert os.path.exists(args.file), "The file to test does not exist"
assert os.path.exists(args.reference), "The reference file does not exist"
reference_data = np.loadtxt(args.reference)
data = np.loadtxt(args.file)
assert reference_data.shape == data.shape, "The shapes of the data and reference are different"
n_samples, n_lfos = reference_data.shape
n_lfos -= 1 # The first column is the time
if n_lfos == 1:
fig, ax = plt.subplots(figsize=(20, 10))
ax.plot(reference_data[:, 0], reference_data[:, 1])
ax.plot(data[:, 0], data[:, 1])
ax.grid()
elif n_lfos > 4:
n_cols = 4
n_rows = n_lfos // n_cols
print(n_rows, n_cols)
fig, ax = plt.subplots(n_rows, n_cols, figsize=(20, 10))
for i in range(n_rows):
for j in range(n_cols):
lfo_index = 1 + i * 4 + j
ax[i, j].plot(reference_data[:, 0], reference_data[:, lfo_index])
ax[i, j].plot(data[:, 0], data[:, lfo_index])
ax[i, j].set_title("LFO {}".format(lfo_index))
ax[i, j].grid()
else:
fig, ax = plt.subplots(1, n_lfos, figsize=(20, 10))
for i in range(n_lfos):
lfo_index = i + 1
ax[i].plot(reference_data[:, 0], reference_data[:, lfo_index])
ax[i].plot(data[:, 0], data[:, lfo_index])
ax[i].set_title("LFO {}".format(lfo_index))
ax[i].grid()
plt.show()