Allow the LFO tool to set options and output FLAC
This commit is contained in:
parent
b46076ba3b
commit
d47bca6f4e
1 changed files with 75 additions and 5 deletions
|
|
@ -18,16 +18,23 @@
|
||||||
#include "sfizz/Synth.h"
|
#include "sfizz/Synth.h"
|
||||||
#include "sfizz/LFO.h"
|
#include "sfizz/LFO.h"
|
||||||
#include "sfizz/LFODescription.h"
|
#include "sfizz/LFODescription.h"
|
||||||
|
#include "sfizz/MathHelpers.h"
|
||||||
#include "cxxopts.hpp"
|
#include "cxxopts.hpp"
|
||||||
#include <absl/types/span.h>
|
#include <absl/types/span.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cmath>
|
#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 sampleRate = 1000.0; // sample rate used to compute
|
||||||
static double duration = 5.0; // length in seconds
|
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)
|
static std::vector<sfz::LFODescription> lfoDescriptionFromSfzFile(const fs::path &sfzPath, bool &success)
|
||||||
{
|
{
|
||||||
|
|
@ -59,6 +66,8 @@ int main(int argc, char* argv[])
|
||||||
options.add_options()
|
options.add_options()
|
||||||
("s,samplerate", "Sample rate", cxxopts::value(sampleRate))
|
("s,samplerate", "Sample rate", cxxopts::value(sampleRate))
|
||||||
("d,duration", "Duration", cxxopts::value(duration))
|
("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")
|
("h,help", "Print usage")
|
||||||
;
|
;
|
||||||
options.positional_help("sfz-file");
|
options.positional_help("sfz-file");
|
||||||
|
|
@ -119,11 +128,72 @@ int main(int argc, char* argv[])
|
||||||
lfos[l].process(lfoOutputs[l]);
|
lfos[l].process(lfoOutputs[l]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < numFrames; ++i) {
|
if (saveFlac) {
|
||||||
std::cout << (i / sampleRate);
|
if (outputFilename.empty()) {
|
||||||
for (size_t l = 0; l < numLfos; ++l)
|
std::cerr << "Please indicate the audio file to save.\n";
|
||||||
std::cout << ' ' << lfoOutputs[l][i];
|
return 1;
|
||||||
std::cout << '\n';
|
}
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue