Little speedup
This commit is contained in:
1 parent
ae9f8bb30a
commit
b1bca37bf8
2 files changed
+19
-20
No files matched your search
@@ -30,7 +30,7 @@ bool Tone::operator==(double f) const {
|
||||
return std::abs(freq / f - 1.0) < 0.05;
|
||||
}
|
||||
|
||||
Analyzer::Analyzer(double rate, std::string id, std::size_t step):
|
||||
Analyzer::Analyzer(double rate, std::string id, unsigned step):
|
||||
m_step(step),
|
||||
m_resampleFactor(1.0),
|
||||
m_resamplePos(),
|
||||
@@ -110,7 +110,7 @@ bool Analyzer::calcFFT() {
|
||||
float pcm[FFT_N];
|
||||
// Read FFT_N samples, move forward by m_step samples
|
||||
if (!m_buf.read(pcm, pcm + FFT_N)) return false;
|
||||
m_buf.pop(static_cast<unsigned>(m_step));
|
||||
m_buf.pop(m_step);
|
||||
// Peak level calculation of the most recent m_step samples (the rest is overlap)
|
||||
for (float const* ptr = pcm + FFT_N - m_step; ptr != pcm + FFT_N; ++ptr) {
|
||||
float s = *ptr;
|
||||
@@ -133,11 +133,11 @@ void Analyzer::calcTones() {
|
||||
const size_t kMax = std::min(FFT_N / 2, size_t(FFT_MAXFREQ / freqPerBin));
|
||||
std::vector<Peak> peaks(kMax + 1); // One extra to simplify loops
|
||||
for (size_t k = 1; k <= kMax; ++k) {
|
||||
double magnitude = std::abs(m_fft[k]);
|
||||
double phase = std::arg(m_fft[k]);
|
||||
float magnitude = std::abs(m_fft[k]);
|
||||
float phase = std::arg(m_fft[k]);
|
||||
// process phase difference
|
||||
double delta = phase - m_fftLastPhase[k];
|
||||
m_fftLastPhase[k] = static_cast<float>(phase);
|
||||
m_fftLastPhase[k] = phase;
|
||||
delta -= k * phaseStep; // subtract expected phase difference
|
||||
delta = remainder(delta, 2.0 * M_PI); // map delta phase into +/- M_PI interval
|
||||
delta /= phaseStep; // calculate diff from bin center frequency
|
||||
|
||||
+14
-15
@@ -34,35 +34,34 @@ static const unsigned FFT_P = 10;
|
||||
static const std::size_t FFT_N = 1 << FFT_P;
|
||||
|
||||
/// Lock-free ring buffer. Discards oldest data on overflow (not strictly thread-safe).
|
||||
template <size_t SIZE> class RingBuffer {
|
||||
template <unsigned SIZE> class RingBuffer {
|
||||
public:
|
||||
constexpr static size_t capacity = SIZE;
|
||||
constexpr static unsigned capacity = SIZE;
|
||||
RingBuffer(): m_read(), m_write() {} ///< Initialize empty buffer
|
||||
template <typename InIt> void insert(InIt begin, InIt end) {
|
||||
unsigned r = static_cast<unsigned>(m_read); // The read position
|
||||
unsigned w = static_cast<unsigned>(m_write); // The write position
|
||||
bool overflow = false;
|
||||
unsigned r = m_read; // The read position
|
||||
unsigned w = m_write; // The write position
|
||||
bool overflow = (end - begin >= SIZE - size());
|
||||
while (begin != end) {
|
||||
m_buf[w] = *begin++; // Copy sample
|
||||
w = modulo(w + 1); // Update cursor
|
||||
if (w == r) overflow = true;
|
||||
}
|
||||
m_write = w;
|
||||
if (overflow) m_read = modulo(w + 1); // Reset read pointer on overflow
|
||||
}
|
||||
/// Read data from current position if there is enough data to fill the range (otherwise return false). Does not move read pointer.
|
||||
template <typename OutIt> bool read(OutIt begin, OutIt end) {
|
||||
unsigned r = static_cast<unsigned>(m_read);
|
||||
if (modulo(static_cast<unsigned>(m_write) - r) <= end - begin) return false; // Not enough audio available
|
||||
unsigned r = m_read;
|
||||
if (size() <= end - begin) return false; // Not enough audio available
|
||||
while (begin != end) *begin++ = m_buf[r++ % SIZE]; // Copy audio to output iterator
|
||||
return true;
|
||||
}
|
||||
void pop(unsigned n) { m_read = modulo(static_cast<unsigned>(m_read + n)); } ///< Move reading pointer forward.
|
||||
unsigned size() const { return modulo(static_cast<unsigned>(m_write - m_read)); }
|
||||
void pop(unsigned n) { m_read = modulo(m_read + n); } ///< Move reading pointer forward.
|
||||
unsigned size() const { return modulo(m_write - m_read); }
|
||||
private:
|
||||
static unsigned modulo(unsigned idx) { return (SIZE + idx) % SIZE; } ///< Modulo operation with proper rounding (handles slightly "negative" idx as well)
|
||||
static unsigned modulo(int idx) { return (SIZE + idx) % SIZE; } ///< Modulo operation with proper rounding (handles slightly "negative" idx as well)
|
||||
float m_buf[SIZE];
|
||||
volatile size_t m_read, m_write; ///< The indices of the next read/write operations. read == write implies that buffer is empty.
|
||||
volatile unsigned m_read, m_write; ///< The indices of the next read/write operations. read == write implies that buffer is empty.
|
||||
};
|
||||
|
||||
/// analyzer class
|
||||
@@ -75,7 +74,7 @@ public:
|
||||
/// list of tones
|
||||
typedef std::list<Tone> tones_t;
|
||||
/// constructor
|
||||
Analyzer(double rate, std::string id, std::size_t step = 200);
|
||||
Analyzer(double rate, std::string id, unsigned step = 200);
|
||||
/** Add input data to buffer. This is thread-safe (against other functions). **/
|
||||
template <typename InIt> void input(InIt begin, InIt end) {
|
||||
m_buf.insert(begin, end);
|
||||
@@ -113,8 +112,8 @@ public:
|
||||
std::string const& getId() const { return m_id; }
|
||||
|
||||
private:
|
||||
const std::size_t m_step;
|
||||
RingBuffer<2 * FFT_N> m_buf; // Twice the FFT size should give enough room for sliding window and for engine delays
|
||||
const unsigned m_step;
|
||||
RingBuffer<4 * FFT_N> m_buf; // Twice the FFT size should give enough room for sliding window and for engine delays
|
||||
RingBuffer<4096> m_passthrough;
|
||||
double m_resampleFactor;
|
||||
double m_resamplePos;
|
||||
|
||||
Reference in new issue
Block a user