|
From: Lasse Kärkkäi. <tr...@us...> - 2010-09-11 23:10:56
|
Module: performous
Branch: master
Commit: 0bbcb5457e5d730cb86239428f15a93e610f5fca
Author: Lasse Karkkainen <tro...@tr...>
Date: Sun Sep 12 01:54:32 2010 +0300
Cleanup and more comments for pitch.hh/cc.
Added postfix operator++ for sample step_iterator.
---
game/libda/sample.hpp | 1 +
game/pitch.cc | 24 ++++++++++++++----------
game/pitch.hh | 44 +++++++++++++++++++++++---------------------
3 files changed, 38 insertions(+), 31 deletions(-)
diff --git a/game/libda/sample.hpp b/game/libda/sample.hpp
index f785347..5d53b6e 100644
--- a/game/libda/sample.hpp
+++ b/game/libda/sample.hpp
@@ -55,6 +55,7 @@ namespace da {
ValueType& operator*() { return *m_pos; }
step_iterator operator+(std::ptrdiff_t rhs) { return step_iterator(m_pos + m_step * rhs, m_step); }
step_iterator& operator++() { m_pos += m_step; return *this; }
+ step_iterator operator++(int) { step_iterator ret = *this; ++*this; return ret; }
bool operator!=(step_iterator const& rhs) const { return m_pos != rhs.m_pos; }
std::ptrdiff_t operator-(step_iterator const& rhs) const { return (m_pos - rhs.m_pos) / m_step; }
// TODO: more operators
diff --git a/game/pitch.cc b/game/pitch.cc
index 773183a..614860d 100644
--- a/game/pitch.cc
+++ b/game/pitch.cc
@@ -76,10 +76,10 @@ namespace {
bool Analyzer::calcFFT() {
float pcm[FFT_N];
size_t r = m_bufRead;
+ // Test if there is enough audio available
if ((BUF_N + m_bufWrite - r) % BUF_N <= FFT_N) return false;
- for (size_t i = 0; i < FFT_N; ++i) {
- pcm[i] = m_buf[(r + i) % BUF_N];
- }
+ // Copy audio to local buffer
+ for (size_t i = 0; i < FFT_N; ++i) pcm[i] = m_buf[(r + i) % BUF_N];
m_bufRead = (r + m_step) % BUF_N;
// Calculate FFT
m_fft = da::fft<FFT_P>(pcm, m_window);
@@ -172,23 +172,27 @@ void Analyzer::calcTones() {
void Analyzer::mergeWithOld(tones_t& tones) const {
tones.sort();
tones_t::iterator it = tones.begin();
+ // Iterate over old tones
for (tones_t::const_iterator oldit = m_tones.begin(); oldit != m_tones.end(); ++oldit) {
+ // Try to find a matching new tone
while (it != tones.end() && *it < *oldit) ++it;
- if (it == tones.end() || *it != *oldit) {
- if (oldit->db > -80.0) {
- Tone& t = *tones.insert(it, *oldit);
- t.db -= 5.0;
- t.stabledb -= 0.1;
- }
- } else if (*it == *oldit) {
+ // If match found
+ if (it != tones.end() && *it == *oldit) {
+ // Merge the old tone into the new tone
it->age = oldit->age + 1;
it->stabledb = 0.8 * oldit->stabledb + 0.2 * it->db;
it->freq = 0.5 * oldit->freq + 0.5 * it->freq;
+ } else if (oldit->db > -80.0) {
+ // Insert a decayed version of the old tone into new tones
+ Tone& t = *tones.insert(it, *oldit);
+ t.db -= 5.0;
+ t.stabledb -= 0.1;
}
}
}
void Analyzer::process() {
+ // Try calculating FFT and calculate tones until no more data in input buffer
while (calcFFT()) calcTones();
}
diff --git a/game/pitch.hh b/game/pitch.hh
index 0fa159d..d39cc46 100644
--- a/game/pitch.hh
+++ b/game/pitch.hh
@@ -8,18 +8,17 @@
/// struct to represent tones
struct Tone {
- static const std::size_t MAXHARM = 48; ///< maximum harmonics
- static const std::size_t MINAGE = 2; ///< minimum age
- double freq; ///< frequency
- double db; ///< dezibels
- double stabledb; ///< stable decibels
- double harmonics[MAXHARM]; ///< harmonics array
- std::size_t age; ///< age
+ static const std::size_t MAXHARM = 48; ///< The maximum number of harmonics tracked
+ static const std::size_t MINAGE = 2; ///< The minimum age required for a tone to be output
+ double freq; ///< Frequency (Hz)
+ double db; ///< Level (dB)
+ double stabledb; ///< Stable level, useful for graphics rendering
+ double harmonics[MAXHARM]; ///< Harmonics' levels
+ std::size_t age; ///< How many times the tone has been detected in row
Tone();
- void print() const; ///< prints Tone
- bool operator==(double f) const; ///< equality operator
- void update(Tone const& t); ///< update Tone
- /// compares left and right volume
+ void print() const; ///< Prints Tone to std::cout
+ bool operator==(double f) const; ///< Compare for rough frequency match
+ /// Less-than compare by levels (instead of frequencies like operator< does)
static bool dbCompare(Tone const& l, Tone const& r) { return l.db < r.db; }
};
@@ -47,19 +46,22 @@ class Analyzer {
Analyzer(double rate, std::size_t step = 200);
/** Add input data to buffer. This is thread-safe (against other functions). **/
template <typename InIt> void input(InIt begin, InIt end) {
+ size_t r = m_bufRead; // The read position
+ size_t w = m_bufWrite; // The write position
+ size_t wNext; // The next write position
+ bool overflow = false;
while (begin != end) {
- float s = *begin;
- ++begin;
- m_peak *= 0.999;
+ float s = *begin++; // Read input sample
+ // Peak level calculation
float p = s * s;
- if (p > m_peak) m_peak = p;
- size_t w = m_bufWrite;
- size_t w2 = (m_bufWrite + 1) % BUF_N;
- size_t r = m_bufRead;
- if (w2 == r) m_bufRead = (r + 1) % BUF_N;
- m_buf[w] = s;
- m_bufWrite = w2;
+ if (p > m_peak) m_peak = p; else m_peak *= 0.999;
+ // Cursor updates
+ wNext = (w + 1) % BUF_N;
+ if (wNext == r) overflow = true;
+ w = wNext;
}
+ m_bufWrite = w;
+ if (overflow) m_bufRead = wNext; // Reset read pointer on overflow
}
/** Call this to process all data input so far. **/
void process();
|