added frequency range option

This commit is contained in:
Robert 2021-04-28 20:10:52 +02:00
parent 9fcd31e193
commit 942bf79fea
2 changed files with 41 additions and 7 deletions

View file

@ -49,7 +49,11 @@ std::vector<std::complex<double>> radix2dit(const std::vector<double>::const_ite
return output; return output;
} }
std::vector<std::pair<double, double>> FFT(const std::vector<double>::const_iterator& begin, const std::vector<double>::const_iterator& end, size_t sampleRate) std::vector<std::pair<double, double>>
FFT(const std::vector<double>::const_iterator& begin,
const std::vector<double>::const_iterator& end,
size_t sampleRate,
double minFreq, double maxFreq)
{ {
std::vector<double> signal(begin, end); std::vector<double> signal(begin, end);
size_t N = signal.size(); size_t N = signal.size();
@ -65,8 +69,11 @@ std::vector<std::pair<double, double>> FFT(const std::vector<double>::const_iter
double nyquistLimit = (double)sampleRate / 2.0f; double nyquistLimit = (double)sampleRate / 2.0f;
std::vector<std::pair<double, double>> output; std::vector<std::pair<double, double>> output;
double freq = 0.0f; double freq = minFreq;
for (int k = 0; freq < nyquistLimit; k++) if (maxFreq == 0)
maxFreq = nyquistLimit;
for (int k = freq / freqRes; freq < nyquistLimit && freq < maxFreq; k++)
{ {
output.push_back(std::make_pair(freq, 2.0f * std::abs(spectrum[k]) / (double)N)); output.push_back(std::make_pair(freq, 2.0f * std::abs(spectrum[k]) / (double)N));
freq += freqRes; freq += freqRes;

View file

@ -14,6 +14,7 @@ struct Settings {
std::vector<std::filesystem::path> files; std::vector<std::filesystem::path> files;
bool quiet; bool quiet;
float splitInterval; float splitInterval;
double minFreq, maxFreq;
}; };
Settings Parse(int argc, char** argv); Settings Parse(int argc, char** argv);
@ -46,7 +47,12 @@ int main(int argc, char** argv)
if (setts.splitInterval == 0.0f) if (setts.splitInterval == 0.0f)
{ {
std::vector<std::pair<double, double>> spectrum = FFT(audioFile.samples[c-1].cbegin(), audioFile.samples[c-1].cend(), sampleRate); std::vector<std::pair<double, double>> spectrum =
FFT(
audioFile.samples[c-1].cbegin(),
audioFile.samples[c-1].cend(),
sampleRate,
setts.minFreq, setts.maxFreq);
output[chName] = nlohmann::json::array(); output[chName] = nlohmann::json::array();
for (const std::pair<double, double>& pair : spectrum) { for (const std::pair<double, double>& pair : spectrum) {
@ -64,8 +70,10 @@ int main(int argc, char** argv)
audioFile.samples[c-1].cbegin() + currentSample, audioFile.samples[c-1].cbegin() + currentSample,
std::min( std::min(
audioFile.samples[c-1].cbegin() + currentSample + sampleInterval, audioFile.samples[c-1].cbegin() + currentSample + sampleInterval,
audioFile.samples[c-1].cend()), audioFile.samples[c-1].cend()
sampleRate ),
sampleRate,
setts.minFreq, setts.maxFreq
); );
output[chName].push_back({ output[chName].push_back({
@ -102,10 +110,11 @@ Settings Parse(int argc, char** argv)
cxxopts::Options options("spectralyze", "Fourier transforms audio files"); cxxopts::Options options("spectralyze", "Fourier transforms audio files");
options options
.set_width(70) .set_width(70)
.positional_help("file1 [file2...]") .positional_help("FILE1 [FILE2...]")
.add_options() .add_options()
("q,quiet", "Suppress text output", cxxopts::value<bool>()->default_value("false")) ("q,quiet", "Suppress text output", cxxopts::value<bool>()->default_value("false"))
("i,interval", "Splits audio file into intervals of length i milliseconds and transforms them individually (0 to not split file)", cxxopts::value<float>()) ("i,interval", "Splits audio file into intervals of length i milliseconds and transforms them individually (0 to not split file)", cxxopts::value<float>())
("f,frequency", "Defines the frequency range of the output spectrum (Default: all the frequencies)", cxxopts::value<std::vector<double>>())
("files", "Files to fourier transform", cxxopts::value<std::vector<std::filesystem::path>>()) ("files", "Files to fourier transform", cxxopts::value<std::vector<std::filesystem::path>>())
("h,help", "Print usage") ("h,help", "Print usage")
; ;
@ -119,6 +128,17 @@ Settings Parse(int argc, char** argv)
exit(0); exit(0);
} }
if (!result.count("frequency"))
{
setts.minFreq = 0.0f;
setts.maxFreq = 0.0f;
}
else
{
setts.minFreq = result["frequency"].as<std::vector<double>>()[0];
setts.maxFreq = result["frequency"].as<std::vector<double>>()[1];
}
if (!result.count("files")) if (!result.count("files"))
{ {
std::cerr << "At least one positional argument is required." << std::endl; std::cerr << "At least one positional argument is required." << std::endl;
@ -128,6 +148,13 @@ Settings Parse(int argc, char** argv)
setts.files = result["files"].as<std::vector<std::filesystem::path>>(); setts.files = result["files"].as<std::vector<std::filesystem::path>>();
setts.quiet = (result.count("quiet") ? result["quiet"].as<bool>() : false); setts.quiet = (result.count("quiet") ? result["quiet"].as<bool>() : false);
setts.splitInterval = (result.count("interval") ? result["interval"].as<float>() : 0.0f); setts.splitInterval = (result.count("interval") ? result["interval"].as<float>() : 0.0f);
if (setts.maxFreq <= setts.minFreq && (setts.maxFreq != 0))
{
std::cerr << "Maximum frequency cannot be smaller than minimum frequency" << std::endl;
exit(1);
}
} }
catch (const cxxopts::OptionException& e) catch (const cxxopts::OptionException& e)
{ {