Put binForFrequency/frequencyForBin in a common place

This commit is contained in:
Chris Cannam
2022-06-13 10:08:05 +01:00
parent 05fb611544
commit 182e2b0e3b
8 changed files with 95 additions and 70 deletions

56
src/common/mathmisc.h Normal file
View 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

View File

@@ -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

View File

@@ -29,6 +29,7 @@
#include "../common/Profiler.h"
#include "../common/VectorOps.h"
#include "../common/sysutils.h"
#include "../common/mathmisc.h"
#include <cassert>
#include <cmath>

View File

@@ -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;
};

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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);
}
};
}