Add peak finder
This commit is contained in:
@@ -31,6 +31,8 @@
|
|||||||
#include "dsp/FFT.h"
|
#include "dsp/FFT.h"
|
||||||
#include "system/Allocators.h"
|
#include "system/Allocators.h"
|
||||||
|
|
||||||
|
#include "dsp/Peak.h"
|
||||||
|
|
||||||
namespace RubberBand
|
namespace RubberBand
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
127
src/dsp/Peak.h
Normal file
127
src/dsp/Peak.h
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/* -*- 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_PEAK_H
|
||||||
|
#define RUBBERBAND_PEAK_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace RubberBand
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Peak
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Peak(int n) :
|
||||||
|
m_n(n),
|
||||||
|
m_locations(n, 0) { }
|
||||||
|
|
||||||
|
// Find the nearest peak to each bin, and optionally the next
|
||||||
|
// highest peak above each bin, within an array v, where a peak is
|
||||||
|
// a value greater than the p nearest neighbours on each side. The
|
||||||
|
// array must have length n where n is the size passed the the
|
||||||
|
// constructor.
|
||||||
|
void findNearestAndNextPeaks(const T *const v,
|
||||||
|
int p,
|
||||||
|
int *nearest,
|
||||||
|
int *next = nullptr)
|
||||||
|
{
|
||||||
|
findNearestAndNextPeaks(v, 0, m_n, p, nearest, next);
|
||||||
|
}
|
||||||
|
|
||||||
|
// As above but consider only the range of size rangeCount from
|
||||||
|
// index rangeStart. Write rangeCount results into nearest and
|
||||||
|
// optionally next, starting to write at index rangeStart - so
|
||||||
|
// these arrays must have the full length even if rangeCount is
|
||||||
|
// shorter. Leave the rest of nearest and/or next unmodified.
|
||||||
|
void findNearestAndNextPeaks(const T *const v,
|
||||||
|
int rangeStart,
|
||||||
|
int rangeCount,
|
||||||
|
int p,
|
||||||
|
int *nearest,
|
||||||
|
int *next = nullptr)
|
||||||
|
{
|
||||||
|
int nPeaks = 0;
|
||||||
|
int n = rangeStart + rangeCount;
|
||||||
|
|
||||||
|
for (int i = rangeStart; i < n; ++i) {
|
||||||
|
T x = v[i];
|
||||||
|
bool good = true;
|
||||||
|
for (int k = i - p; k <= i + p; ++k) {
|
||||||
|
if (k < rangeStart || k == i) continue;
|
||||||
|
if (k >= n) break;
|
||||||
|
if (k < i && x <= v[k]) {
|
||||||
|
good = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (k > i && x < v[k]) {
|
||||||
|
good = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (good) {
|
||||||
|
m_locations[nPeaks++] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int pp = rangeStart - 1;
|
||||||
|
for (int i = rangeStart, j = 0; i < n; ++i) {
|
||||||
|
int np = i;
|
||||||
|
if (j < nPeaks) {
|
||||||
|
np = m_locations[j];
|
||||||
|
}
|
||||||
|
if (next) {
|
||||||
|
if (pp == i) {
|
||||||
|
next[i] = i;
|
||||||
|
} else {
|
||||||
|
next[i] = np;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nearest) {
|
||||||
|
if (j == 0) {
|
||||||
|
nearest[i] = np;
|
||||||
|
} else {
|
||||||
|
if (np - i < i - pp) {
|
||||||
|
nearest[i] = np;
|
||||||
|
} else {
|
||||||
|
nearest[i] = pp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (j < nPeaks && m_locations[j] <= i) {
|
||||||
|
pp = np;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int m_n;
|
||||||
|
std::vector<int> m_locations;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user