added frequency range option
This commit is contained in:
parent
9fcd31e193
commit
942bf79fea
13
src/FFT.hpp
13
src/FFT.hpp
|
@ -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;
|
||||||
|
|
35
src/main.cpp
35
src/main.cpp
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue