sfizz/tests/PlotCurve.cpp

95 lines
2.4 KiB
C++
Raw Normal View History

2020-03-03 13:11:31 +01:00
// 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/Curve.h"
#include "sfizz/Parser.h"
#include "absl/strings/numbers.h"
#include "absl/types/span.h"
#include <iostream>
#include <cmath>
//==============================================================================
/**
* @brief Print usage information
*/
static void usage()
{
std::cerr << "Usage: sfizz_plot_curve <index> [file.sfz]"
<< "\n";
}
/**
* @brief Parser which extracts the configuration of curves
*/
class CurveParser : public sfz::Parser {
public:
explicit CurveParser(sfz::CurveSet& curveSet)
: curveSet(curveSet)
{
}
void callback(absl::string_view header, const std::vector<sfz::Opcode>& members) override
{
if (header == "effect")
curveSet.addCurveFromHeader(members);
}
private:
sfz::CurveSet& curveSet;
};
/**
* @brief Program which loads LFO configuration and generates plot data for the given duration.
*/
int main(int argc, char* argv[])
{
if (argc < 2 || argc > 3)
return usage(), 1;
int curveIndex = -1;
if (!absl::SimpleAtoi(argv[1], &curveIndex))
return usage(), 1;
std::string filePath;
if (argc > 2)
filePath = argv[2];
///
sfz::CurveSet curveSet = sfz::CurveSet::createPredefined();
if (!filePath.empty()) {
CurveParser parser(curveSet);
if (!parser.loadSfzFile(filePath)) {
std::cerr << "Cannot load SFZ: " << filePath << "\n";
return 1;
}
}
///
const sfz::Curve& curve = curveSet.getCurve(curveIndex);
constexpr unsigned numSamples = 1024; // number of points to evaluate
for (unsigned i = 0; i < numSamples; ++i) {
float x = i * (1.0f / (numSamples - 1));
std::cout << x << ' ' << curve.evalNormalized(x) << '\n';
}
return 0;
}