Put binForFrequency/frequencyForBin in a common place
This commit is contained in:
56
src/common/mathmisc.h
Normal file
56
src/common/mathmisc.h
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "../common/Profiler.h"
|
||||
#include "../common/VectorOps.h"
|
||||
#include "../common/sysutils.h"
|
||||
#include "../common/mathmisc.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#define RUBBERBAND_BIN_SEGMENTER_H
|
||||
|
||||
#include "BinClassifier.h"
|
||||
|
||||
#include "../common/HistogramFilter.h"
|
||||
#include "../common/mathmisc.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -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<int> 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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "Guide.h"
|
||||
|
||||
#include "../common/mathmisc.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <functional>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user