# HG changeset patch # User Chris Cannam # Date 1571298626 -3600 # Thu Oct 17 08:50:26 2019 +0100 # Node ID 84bfe609d6042f74bb48b50ca1930b35c861ed1a # Parent d9841c82b134a4c4762e68687d8dafb29eb4644b Untabify diff --git a/src/MiniBpm.cpp b/src/MiniBpm.cpp --- a/src/MiniBpm.cpp +++ b/src/MiniBpm.cpp @@ -94,24 +94,24 @@ template void acf(const T *R__ in, T *R__ out) const { - for (int i = 0; i < m_m; ++i) { - out[i] = 0.0; - for (int j = i; j < m_n; ++j) { - out[i] += in[j] * in[j - i]; - } - } + for (int i = 0; i < m_m; ++i) { + out[i] = 0.0; + for (int j = i; j < m_n; ++j) { + out[i] += in[j] * in[j - i]; + } + } } template void acfUnityNormalised(const T *R__ in, T *R__ out) const { - acf(in, out); + acf(in, out); double max = 0.0; - for (int i = 0; i < m_m; ++i) { - out[i] /= m_n - i; + for (int i = 0; i < m_m; ++i) { + out[i] /= m_n - i; if (out[i] > max) max = out[i]; - } + } if (max > 0.0) { for (int i = 0; i < m_m; ++i) { out[i] /= max; @@ -120,10 +120,10 @@ } static int bpmToLag(double bpm, double hopsPerSec) { - return int((60.0 / bpm) * hopsPerSec + 0.5); + return int((60.0 / bpm) * hopsPerSec + 0.5); } static double lagToBpm(double lag, double hopsPerSec) { - return (60.0 * hopsPerSec) / lag; + return (60.0 * hopsPerSec) / lag; } private: @@ -135,14 +135,14 @@ { public: FourierFilterbank(int n, double fs, double minFreq, double maxFreq, - bool windowed) : - m_n(n), m_fs(fs), m_fmin(minFreq), m_fmax(maxFreq), - m_windowed(windowed) + bool windowed) : + m_n(n), m_fs(fs), m_fmin(minFreq), m_fmax(maxFreq), + m_windowed(windowed) { - m_binmin = int(floor(n * m_fmin) / fs); - m_binmax = int(ceil(n * m_fmax) / fs); - m_bins = m_binmax - m_binmin + 1; - initFilters(); + m_binmin = int(floor(n * m_fmin) / fs); + m_binmax = int(ceil(n * m_fmax) / fs); + m_bins = m_binmax - m_binmin + 1; + initFilters(); } ~FourierFilterbank() { @@ -155,18 +155,18 @@ } int getOutputSize() const { - return m_bins; + return m_bins; } void forwardMagnitude(const double *R__ realIn, double *R__ magOut) const { - for (int i = 0; i < m_bins; ++i) { - const double *R__ sin = m_sin[i]; - const double *R__ cos = m_cos[i]; - double real = 0.0, imag = 0.0; - for (int j = 0; j < m_n; ++j) real += realIn[j] * cos[j]; - for (int j = 0; j < m_n; ++j) imag += realIn[j] * sin[j]; - magOut[i] = sqrt(real*real + imag*imag); - } + for (int i = 0; i < m_bins; ++i) { + const double *R__ sin = m_sin[i]; + const double *R__ cos = m_cos[i]; + double real = 0.0, imag = 0.0; + for (int j = 0; j < m_n; ++j) real += realIn[j] * cos[j]; + for (int j = 0; j < m_n; ++j) imag += realIn[j] * sin[j]; + magOut[i] = sqrt(real*real + imag*imag); + } } private: @@ -185,20 +185,20 @@ void initFilters() { m_sin = new double*[m_bins]; m_cos = new double*[m_bins]; - double twopi = M_PI * 2.0; + double twopi = M_PI * 2.0; double win = 1.0; - for (int i = 0; i < m_bins; ++i) { + for (int i = 0; i < m_bins; ++i) { m_sin[i] = new double[m_n]; m_cos[i] = new double[m_n]; - int bin = i + m_binmin; - double delta = (twopi * bin) / m_n; - for (int j = 0; j < m_n; ++j) { - double angle = j * delta; + int bin = i + m_binmin; + double delta = (twopi * bin) / m_n; + for (int j = 0; j < m_n; ++j) { + double angle = j * delta; if (m_windowed) win = 0.5 - 0.5 * cos(twopi * j / m_n); - m_sin[i][j] = sin(angle) * win; - m_cos[i][j] = cos(angle) * win; - } - } + m_sin[i][j] = sin(angle) * win; + m_cos[i][j] = cos(angle) * win; + } + } } }; @@ -230,7 +230,7 @@ void filter(const double *acf, int acfLength, double *filtered) { - int flen = getFilteredLength(); + int flen = getFilteredLength(); for (int i = 0; i < flen; ++i) { @@ -323,11 +323,11 @@ template void copy(T *R__ t, const S *R__ s, const int n) { - for (int i = 0; i < n; ++i) t[i] = s[i]; + for (int i = 0; i < n; ++i) t[i] = s[i]; } template void zero(T *R__ t, const int n) { - for (int i = 0; i < n; ++i) t[i] = T(0); + for (int i = 0; i < n; ++i) t[i] = T(0); } template void unityNormalise(T *R__ t, const int n) { @@ -344,114 +344,114 @@ } D(float sampleRate) : - m_minbpm(55), - m_maxbpm(190), - m_beatsPerBar(4), - m_inputSampleRate(sampleRate), - m_lfmin(0), - m_lfmax(550), - m_hfmin(9000), - m_hfmax(9001), - m_input(0), - m_partial(0), - m_partialFill(0), - m_frame(0), - m_lfprev(0), - m_hfprev(0) + m_minbpm(55), + m_maxbpm(190), + m_beatsPerBar(4), + m_inputSampleRate(sampleRate), + m_lfmin(0), + m_lfmax(550), + m_hfmin(9000), + m_hfmax(9001), + m_input(0), + m_partial(0), + m_partialFill(0), + m_frame(0), + m_lfprev(0), + m_hfprev(0) { - int lfbinmax = 6; - m_blockSize = (m_inputSampleRate * lfbinmax) / m_lfmax; - m_stepSize = m_blockSize / 2; + int lfbinmax = 6; + m_blockSize = (m_inputSampleRate * lfbinmax) / m_lfmax; + m_stepSize = m_blockSize / 2; - m_lf = new FourierFilterbank(m_blockSize, m_inputSampleRate, - m_lfmin, m_lfmax, true); + m_lf = new FourierFilterbank(m_blockSize, m_inputSampleRate, + m_lfmin, m_lfmax, true); - m_hf = new FourierFilterbank(m_blockSize, m_inputSampleRate, - m_hfmin, m_hfmax, true); + m_hf = new FourierFilterbank(m_blockSize, m_inputSampleRate, + m_hfmin, m_hfmax, true); - int lfsize = m_lf->getOutputSize(); - int hfsize = m_hf->getOutputSize(); + int lfsize = m_lf->getOutputSize(); + int hfsize = m_hf->getOutputSize(); - m_lfprev = new double[lfsize]; - for (int i = 0; i < lfsize; ++i) m_lfprev[i] = 0.0; + m_lfprev = new double[lfsize]; + for (int i = 0; i < lfsize; ++i) m_lfprev[i] = 0.0; - m_hfprev = new double[hfsize]; - for (int i = 0; i < hfsize; ++i) m_hfprev[i] = 0.0; + m_hfprev = new double[hfsize]; + for (int i = 0; i < hfsize; ++i) m_hfprev[i] = 0.0; - m_input = new double[m_blockSize]; - m_partial = new double[m_stepSize]; + m_input = new double[m_blockSize]; + m_partial = new double[m_stepSize]; int frameSize = std::max(lfsize, hfsize); - m_frame = new double[frameSize]; + m_frame = new double[frameSize]; zero(m_input, m_blockSize); zero(m_partial, m_stepSize); zero(m_frame, frameSize); } - + ~D() { - delete m_lf; - delete m_hf; - delete[] m_lfprev; - delete[] m_hfprev; - delete[] m_input; - delete[] m_partial; - delete[] m_frame; + delete m_lf; + delete m_hf; + delete[] m_lfprev; + delete[] m_hfprev; + delete[] m_input; + delete[] m_partial; + delete[] m_frame; } double specdiff(const double *a, const double *b, int n) { - double tot = 0.0; - for (int i = 0; i < n; ++i) { - tot += sqrt(fabs(a[i]*a[i] - b[i]*b[i])); - } - return tot; + double tot = 0.0; + for (int i = 0; i < n; ++i) { + tot += sqrt(fabs(a[i]*a[i] - b[i]*b[i])); + } + return tot; } double estimateTempoOfSamples(const float *samples, int nsamples) { - int i = 0; - while (i + m_blockSize < nsamples) { - copy(m_input, samples + i, m_blockSize); - processInputBlock(); - i += m_stepSize; - } - return finish(); + int i = 0; + while (i + m_blockSize < nsamples) { + copy(m_input, samples + i, m_blockSize); + processInputBlock(); + i += m_stepSize; + } + return finish(); } void process(const float *samples, int nsamples) { - int n = 0; - while (n < nsamples) { - int hole = m_blockSize - m_stepSize; - int remaining = nsamples - n; - if (m_partialFill + remaining < m_stepSize) { - copy(m_partial + m_partialFill, samples + n, remaining); - m_partialFill += remaining; - break; - } - copy(m_input + hole, m_partial, m_partialFill); - int toConsume = m_stepSize - m_partialFill; - copy(m_input + hole + m_partialFill, samples + n, toConsume); - n += toConsume; - m_partialFill = 0; - processInputBlock(); - copy(m_input, m_input + m_stepSize, hole); - } + int n = 0; + while (n < nsamples) { + int hole = m_blockSize - m_stepSize; + int remaining = nsamples - n; + if (m_partialFill + remaining < m_stepSize) { + copy(m_partial + m_partialFill, samples + n, remaining); + m_partialFill += remaining; + break; + } + copy(m_input + hole, m_partial, m_partialFill); + int toConsume = m_stepSize - m_partialFill; + copy(m_input + hole + m_partialFill, samples + n, toConsume); + n += toConsume; + m_partialFill = 0; + processInputBlock(); + copy(m_input, m_input + m_stepSize, hole); + } } double estimateTempo() { - if (m_partialFill > 0) { - int hole = m_blockSize - m_stepSize; - copy(m_input + hole, m_partial, m_partialFill); - zero(m_input + hole + m_partialFill, m_stepSize - m_partialFill); - m_partialFill = 0; - processInputBlock(); - } - return finish(); + if (m_partialFill > 0) { + int hole = m_blockSize - m_stepSize; + copy(m_input + hole, m_partial, m_partialFill); + zero(m_input + hole + m_partialFill, m_stepSize - m_partialFill); + m_partialFill = 0; + processInputBlock(); + } + return finish(); } std::vector getTempoCandidates() const @@ -461,83 +461,83 @@ void reset() { - m_lfdf.clear(); - m_hfdf.clear(); - m_rms.clear(); + m_lfdf.clear(); + m_hfdf.clear(); + m_rms.clear(); m_candidates.clear(); - m_partialFill = 0; + m_partialFill = 0; } void processInputBlock() { - double rms = 0.0; + double rms = 0.0; - for (int i = 0; i < m_blockSize; ++i) { - rms += m_input[i] * m_input[i]; - } + for (int i = 0; i < m_blockSize; ++i) { + rms += m_input[i] * m_input[i]; + } - rms = sqrt(rms / m_blockSize); - m_rms.push_back(rms); + rms = sqrt(rms / m_blockSize); + m_rms.push_back(rms); - int lfsize = m_lf->getOutputSize(); - int hfsize = m_hf->getOutputSize(); + int lfsize = m_lf->getOutputSize(); + int hfsize = m_hf->getOutputSize(); - m_lf->forwardMagnitude(m_input, m_frame); - m_lfdf.push_back(specdiff(m_frame, m_lfprev, lfsize)); - copy(m_lfprev, m_frame, lfsize); - - m_hf->forwardMagnitude(m_input, m_frame); - m_hfdf.push_back(specdiff(m_frame, m_hfprev, hfsize)); - copy(m_hfprev, m_frame, hfsize); + m_lf->forwardMagnitude(m_input, m_frame); + m_lfdf.push_back(specdiff(m_frame, m_lfprev, lfsize)); + copy(m_lfprev, m_frame, lfsize); + + m_hf->forwardMagnitude(m_input, m_frame); + m_hfdf.push_back(specdiff(m_frame, m_hfprev, hfsize)); + copy(m_hfprev, m_frame, hfsize); } double finish() { m_candidates.clear(); - double hopsPerSec = m_inputSampleRate / m_stepSize; - int dfLength = m_lfdf.size(); + double hopsPerSec = m_inputSampleRate / m_stepSize; + int dfLength = m_lfdf.size(); - // We have no use for any lag beyond 4 bars at minimum bpm - double barPM = m_minbpm / (4 * m_beatsPerBar); - int acfLength = Autocorrelation::bpmToLag(barPM, hopsPerSec); + // We have no use for any lag beyond 4 bars at minimum bpm + double barPM = m_minbpm / (4 * m_beatsPerBar); + int acfLength = Autocorrelation::bpmToLag(barPM, hopsPerSec); while (acfLength > dfLength) acfLength /= 2; - Autocorrelation acfcalc(dfLength, acfLength); + Autocorrelation acfcalc(dfLength, acfLength); - double *acf = new double[acfLength]; - double *temp = new double[acfLength]; + double *acf = new double[acfLength]; + double *temp = new double[acfLength]; - zero(acf, acfLength); + zero(acf, acfLength); - acfcalc.acfUnityNormalised(&m_lfdf[0], temp); - for (int i = 0; i < acfLength; ++i) acf[i] += temp[i]; + acfcalc.acfUnityNormalised(&m_lfdf[0], temp); + for (int i = 0; i < acfLength; ++i) acf[i] += temp[i]; - acfcalc.acfUnityNormalised(&m_hfdf[0], temp); - for (int i = 0; i < acfLength; ++i) acf[i] += temp[i] * 0.5; + acfcalc.acfUnityNormalised(&m_hfdf[0], temp); + for (int i = 0; i < acfLength; ++i) acf[i] += temp[i] * 0.5; - acfcalc.acfUnityNormalised(&m_rms[0], temp); - for (int i = 0; i < acfLength; ++i) acf[i] += temp[i] * 0.1; + acfcalc.acfUnityNormalised(&m_rms[0], temp); + for (int i = 0; i < acfLength; ++i) acf[i] += temp[i] * 0.1; - int minlag = Autocorrelation::bpmToLag(m_maxbpm, hopsPerSec); - int maxlag = Autocorrelation::bpmToLag(m_minbpm, hopsPerSec); + int minlag = Autocorrelation::bpmToLag(m_maxbpm, hopsPerSec); + int maxlag = Autocorrelation::bpmToLag(m_minbpm, hopsPerSec); - if (acfLength < maxlag) { - // Not enough data + if (acfLength < maxlag) { + // Not enough data delete[] acf; delete[] temp; - return 0.0; - } + return 0.0; + } ACFCombFilter filter(m_beatsPerBar, minlag, maxlag, hopsPerSec); int cflen = filter.getFilteredLength(); - double *cf = new double[cflen]; + double *cf = new double[cflen]; filter.filter(acf, acfLength, cf); unityNormalise(cf, cflen); - for (int i = 0; i < cflen; ++i) { - // perceptual weighting: prefer middling values - double bpm = Autocorrelation::lagToBpm(minlag + i, hopsPerSec); + for (int i = 0; i < cflen; ++i) { + // perceptual weighting: prefer middling values + double bpm = Autocorrelation::lagToBpm(minlag + i, hopsPerSec); double weight; double centre = 130.0; if (bpm < centre) { @@ -545,16 +545,16 @@ } else { weight = 1.0 - pow(fabs(centre - bpm) / 80.0, 2.4); } - if (weight < 0.0) weight = 0.0; - cf[i] *= weight; - } + if (weight < 0.0) weight = 0.0; + cf[i] *= weight; + } std::multimap candidateMap; - for (int i = 1; i + 1 < cflen; ++i) { + for (int i = 1; i + 1 < cflen; ++i) { if (cf[i] > cf[i-1] && cf[i] > cf[i+1]) { candidateMap.insert(std::pair(cf[i], i)); } - } + } if (candidateMap.empty()) { delete[] cf; @@ -571,13 +571,13 @@ m_candidates.push_back(bpm); } - delete[] cf; - delete[] acf; - delete[] temp; + delete[] cf; + delete[] acf; + delete[] temp; - return m_candidates[0]; + return m_candidates[0]; } - + private: float m_inputSampleRate;