diff --git a/src/common/mathmisc.h b/src/common/mathmisc.h new file mode 100644 index 0000000..e6697ff --- /dev/null +++ b/src/common/mathmisc.h @@ -0,0 +1,56 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rubber Band Library + An audio time-stretching and pitch-shifting library. + Copyright 2007-2022 Particular Programs Ltd. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. + + Alternatively, if you have a valid commercial licence for the + Rubber Band Library obtained by agreement with the copyright + holders, you may redistribute and/or modify it under the terms + described in that licence. + + If you wish to distribute code using the Rubber Band Library + under terms other than those of the GNU General Public License, + you must obtain a valid commercial licence before doing so. +*/ + +#ifndef RUBBERBAND_MATHMISC_H +#define RUBBERBAND_MATHMISC_H + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif // M_PI + +namespace RubberBand { + +inline double mod(double x, double y) { + return x - (y * floor(x / y)); +} +inline float modf(float x, float y) { + return x - (y * float(floor(x / y))); +} + +inline double princarg(double a) { + return mod(a + M_PI, -2.0 * M_PI) + M_PI; +} +inline float princargf(float a) { + return modf(a + (float)M_PI, -2.f * (float)M_PI) + (float)M_PI; +} + +inline int binForFrequency(double f, int fftSize, double sampleRate) { + return int(round(f * double(fftSize) / sampleRate)); +} +inline double frequencyForBin(int b, int fftSize, double sampleRate) { + return (double(b) * sampleRate) / double(fftSize); +} + +} + +#endif diff --git a/src/common/sysutils.h b/src/common/sysutils.h index 798c5d6..06755ec 100644 --- a/src/common/sysutils.h +++ b/src/common/sysutils.h @@ -92,16 +92,6 @@ struct timeval { long tv_sec; long tv_usec; }; void gettimeofday(struct timeval *p, void *tz); #endif // _WIN32 -inline double mod(double x, double y) { return x - (y * floor(x / y)); } -inline float modf(float x, float y) { return x - (y * float(floor(x / y))); } - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif // M_PI - -inline double princarg(double a) { return mod(a + M_PI, -2.0 * M_PI) + M_PI; } -inline float princargf(float a) { return modf(a + (float)M_PI, -2.f * (float)M_PI) + (float)M_PI; } - } // end namespace // The following should be functions in the RubberBand namespace, really diff --git a/src/faster/StretcherProcess.cpp b/src/faster/StretcherProcess.cpp index c5a8b60..1a4e823 100644 --- a/src/faster/StretcherProcess.cpp +++ b/src/faster/StretcherProcess.cpp @@ -29,6 +29,7 @@ #include "../common/Profiler.h" #include "../common/VectorOps.h" #include "../common/sysutils.h" +#include "../common/mathmisc.h" #include #include diff --git a/src/finer/BinSegmenter.h b/src/finer/BinSegmenter.h index 1e00521..c49f03d 100644 --- a/src/finer/BinSegmenter.h +++ b/src/finer/BinSegmenter.h @@ -25,7 +25,9 @@ #define RUBBERBAND_BIN_SEGMENTER_H #include "BinClassifier.h" + #include "../common/HistogramFilter.h" +#include "../common/mathmisc.h" #include @@ -83,11 +85,12 @@ public: } } std::cout << std::endl; -*/ +*/ double f0 = 0.0; for (int i = 1; i < n; ++i) { if (m_numeric[i] != 1) { - f0 = frequencyForBin(i); + f0 = frequencyForBin + (i, m_parameters.fftSize, m_parameters.sampleRate); break; } } @@ -102,14 +105,17 @@ public: continue; } else if (c == 1) { // percussive inPercussive = true; - f2 = frequencyForBin(i); + f2 = frequencyForBin + (i, m_parameters.fftSize, m_parameters.sampleRate); } else { // harmonic - f1 = f2 = frequencyForBin(i); + f1 = f2 = frequencyForBin + (i, m_parameters.fftSize, m_parameters.sampleRate); break; } } else { // inPercussive if (c != 1) { // non-percussive - f1 = frequencyForBin(i); + f1 = frequencyForBin + (i, m_parameters.fftSize, m_parameters.sampleRate); break; } } @@ -128,16 +134,6 @@ protected: std::vector m_numeric; HistogramFilter m_classFilter; - //!!! dupes - int binForFrequency(double f) const { - return int(round(f * double(m_parameters.fftSize) / - m_parameters.sampleRate)); - } - double frequencyForBin(int b) const { - return (double(b) * m_parameters.sampleRate) - / double(m_parameters.fftSize); - } - BinSegmenter(const BinSegmenter &) =delete; BinSegmenter &operator=(const BinSegmenter &) =delete; }; diff --git a/src/finer/Guide.h b/src/finer/Guide.h index 2204065..905e61d 100644 --- a/src/finer/Guide.h +++ b/src/finer/Guide.h @@ -312,15 +312,6 @@ protected: double m_maxLower; double m_maxHigher; - int binForFrequency(double f) const { - return int(round(f * double(m_configuration.classificationFftSize) / - m_parameters.sampleRate)); - } - double frequencyForBin(int b) const { - return (double(b) * m_parameters.sampleRate) - / double(m_configuration.classificationFftSize); - } - // near-dupe with R2 RubberBandStretcher::Impl int roundUp(int value) const { if (value < 1) return 1; @@ -333,7 +324,8 @@ protected: bool checkPotentialKick(const double *const magnitudes, const double *const prevMagnitudes) const { - int b = binForFrequency(200.0); + int b = binForFrequency(200.0, m_configuration.classificationFftSize, + m_parameters.sampleRate); double here = 0.0, there = 0.0; for (int i = 1; i <= b; ++i) { here += magnitudes[i]; @@ -345,7 +337,8 @@ protected: } double descendToValley(double f, const double *const magnitudes) const { - int b = binForFrequency(f); + int b = binForFrequency(f, m_configuration.classificationFftSize, + m_parameters.sampleRate); for (int i = 0; i < 3; ++i) { if (magnitudes[b+1] < magnitudes[b]) { ++b; @@ -355,7 +348,8 @@ protected: break; } } - double sf = frequencyForBin(b); + double sf = frequencyForBin(b, m_configuration.classificationFftSize, + m_parameters.sampleRate); return sf; } diff --git a/src/finer/PhaseAdvance.h b/src/finer/PhaseAdvance.h index 79c7db0..c20cf1d 100644 --- a/src/finer/PhaseAdvance.h +++ b/src/finer/PhaseAdvance.h @@ -26,6 +26,8 @@ #include "Guide.h" +#include "../common/mathmisc.h" + #include #include @@ -129,8 +131,10 @@ public: m_currentPeaks[c][i] = i; } for (const auto &band : guidance[c]->phaseLockBands) { - int startBin = binForFrequency(band.f0); - int endBin = binForFrequency(band.f1); + int startBin = binForFrequency + (band.f0, m_parameters.fftSize, m_parameters.sampleRate); + int endBin = binForFrequency + (band.f1, m_parameters.fftSize, m_parameters.sampleRate); if (startBin > highest || endBin < lowest) continue; int count = endBin - startBin + 1; m_peakPicker.findNearestAndNextPeaks(mag[c], @@ -176,7 +180,8 @@ public: const Guide::Guidance *g = guidance[c]; int phaseLockBand = 0; for (int i = lowest; i <= highest; ++i) { - double f = frequencyForBin(i); + double f = frequencyForBin + (i, m_parameters.fftSize, m_parameters.sampleRate); while (f > g->phaseLockBands[phaseLockBand].f1) { ++phaseLockBand; } @@ -237,14 +242,6 @@ protected: double **m_unlocked; bool m_reported; - int binForFrequency(double f) const { - return int(round(f * double(m_parameters.fftSize) / - m_parameters.sampleRate)); - } - double frequencyForBin(int b) const { - return (double(b) * m_parameters.sampleRate) - / double(m_parameters.fftSize); - } bool inRange(double f, const Guide::Range &r) { return r.present && f >= r.f0 && f < r.f1; } diff --git a/src/finer/R3StretcherImpl.cpp b/src/finer/R3StretcherImpl.cpp index cd73c76..a0d80d2 100644 --- a/src/finer/R3StretcherImpl.cpp +++ b/src/finer/R3StretcherImpl.cpp @@ -688,9 +688,9 @@ R3StretcherImpl::analyseChannel(int c, int inhop, int prevInhop, int prevOuthop) double pb = cd->nextSegmentation.percussiveBelow; double pa = cd->nextSegmentation.percussiveAbove; double ra = cd->nextSegmentation.residualAbove; - int pbb = binForFrequency(pb, classify); - int pab = binForFrequency(pa, classify); - int rab = binForFrequency(ra, classify); + int pbb = binForFrequency(pb, classify, m_parameters.sampleRate); + int pab = binForFrequency(pa, classify, m_parameters.sampleRate); + int rab = binForFrequency(ra, classify, m_parameters.sampleRate); std::cout << "pb = " << pb << ", pbb = " << pbb << std::endl; std::cout << "pa = " << pa << ", pab = " << pab << std::endl; std::cout << "ra = " << ra << ", rab = " << rab << std::endl; @@ -804,8 +804,10 @@ R3StretcherImpl::adjustPreKick(int c) auto fftSize = cd->guidance.fftBands[0].fftSize; if (cd->guidance.preKick.present) { auto &scale = cd->scales.at(fftSize); - int from = binForFrequency(cd->guidance.preKick.f0, fftSize); - int to = binForFrequency(cd->guidance.preKick.f1, fftSize); + int from = binForFrequency(cd->guidance.preKick.f0, + fftSize, m_parameters.sampleRate); + int to = binForFrequency(cd->guidance.preKick.f1, + fftSize, m_parameters.sampleRate); for (int i = from; i <= to; ++i) { double diff = scale->mag[i] - scale->prevMag[i]; if (diff > 0.0) { @@ -815,8 +817,10 @@ R3StretcherImpl::adjustPreKick(int c) } } else if (cd->guidance.kick.present) { auto &scale = cd->scales.at(fftSize); - int from = binForFrequency(cd->guidance.preKick.f0, fftSize); - int to = binForFrequency(cd->guidance.preKick.f1, fftSize); + int from = binForFrequency(cd->guidance.preKick.f0, + fftSize, m_parameters.sampleRate); + int to = binForFrequency(cd->guidance.preKick.f1, + fftSize, m_parameters.sampleRate); for (int i = from; i <= to; ++i) { scale->mag[i] += scale->pendingKick[i]; scale->pendingKick[i] = 0.0; @@ -852,12 +856,9 @@ R3StretcherImpl::synthesiseChannel(int c, int outhop) // The frequency filter is applied naively in the frequency // domain. Aliasing is reduced by the shorter resynthesis // window - - //!!! I don't think we have binForFrequency etc available in - //!!! this class - really that's ridiculous - int lowBin = int(floor(fftSize * band.f0 / m_parameters.sampleRate)); - int highBin = int(floor(fftSize * band.f1 / m_parameters.sampleRate)); + int lowBin = binForFrequency(band.f0, fftSize, m_parameters.sampleRate); + int highBin = binForFrequency(band.f1, fftSize, m_parameters.sampleRate); if (highBin % 2 == 0 && highBin > 0) --highBin; for (int i = 0; i < lowBin; ++i) { diff --git a/src/finer/R3StretcherImpl.h b/src/finer/R3StretcherImpl.h index ad97207..14d095d 100644 --- a/src/finer/R3StretcherImpl.h +++ b/src/finer/R3StretcherImpl.h @@ -294,16 +294,6 @@ protected: static void logCout(const std::string &message) { std::cout << "RubberBandStretcher: " << message << std::endl; } - - //!!! dupes - int binForFrequency(double f, int fftSize) const { - return int(round(f * double(fftSize) / - m_parameters.sampleRate)); - } - double frequencyForBin(int b, int fftSize) const { - return (double(b) * m_parameters.sampleRate) - / double(fftSize); - } }; }