|
From: Lasse Kärkkäi. <tr...@us...> - 2011-01-24 14:17:01
|
Module: editor
Branch: master
Commit: 40c1ba440652a3b3b5e137f6cc1375f9d3c087b7
Author: Lasse Karkkainen <tro...@tr...>
Date: Mon Jan 24 15:16:30 2011 +0100
Various small changes and fixes
---
pitch.cc | 24 ++++++++++--------------
pitch.hh | 23 +++++++++++++++++------
pitchvis.cc | 13 ++++++++-----
pitchvis.hh | 10 +++++-----
4 files changed, 40 insertions(+), 30 deletions(-)
diff --git a/pitch.cc b/pitch.cc
index c0c0bb7..4b81537 100644
--- a/pitch.cc
+++ b/pitch.cc
@@ -61,19 +61,15 @@ namespace {
for (std::size_t n = 1; n < Tone::MAXHARM; ++n) if (matchFreq(n*ff, hf)) return true;
return false;
}
- struct Combo {
- double freq;
- double level;
- Combo(): freq(), level() {}
- void combine(Peak const& p) {
- freq += p.level * p.freq; // Multiplication for weighted average
- level += p.level;
- }
- bool match(double freqOther) const { return matchFreq(freq, freqOther); }
- };
- bool operator<(Combo const& a, Combo const& b) { return a.level < b.level; }
}
+void Combo::combine(Peak const& p) {
+ freq += p.level * p.freq; // Multiplication for weighted average
+ level += p.level;
+}
+
+bool Combo::match(double freqOther) const { return matchFreq(freq, freqOther); }
+
void Analyzer::calcTones() {
// Precalculated constants
const double freqPerBin = m_rate / FFT_N;
@@ -116,9 +112,9 @@ void Analyzer::calcTones() {
// Convert sum frequencies into averages
for (Combos::iterator it = combos.begin(), end = combos.end(); it != end; ++it) it->freq /= it->level;
// Strongest first
- std::sort(combos.rbegin(), combos.rend());
+ std::sort(combos.rbegin(), combos.rend(), Combo::cmpByLevel);
// Keep only a reasonable amount of strongest frequencies.
- if (combos.size() > 10) combos.resize(10);
+ //if (combos.size() > 10) combos.resize(10);
// Try to combine combos into tones (collections of harmonics)
Tones tones;
for (Combos::const_iterator it = combos.begin(), end = combos.end(); it != end; ++it) {
@@ -142,7 +138,7 @@ void Analyzer::calcTones() {
double l = harm->level;
t.harmonics[n - 1] += l;
t.level += l;
- t.freq += l * harm->freq / n; // The sum of all harmonics' fundies (weighted by m)
+ t.freq += l * harm->freq / n; // The sum of all harmonics' fundies (weighted by l)
}
if (miss) ++misses;
}
diff --git a/pitch.hh b/pitch.hh
index 2105c35..d75116e 100644
--- a/pitch.hh
+++ b/pitch.hh
@@ -23,6 +23,13 @@ struct Tone {
Tone* next;
};
+static inline bool operator==(Tone const& lhs, Tone const& rhs) { return lhs == rhs.freq; }
+static inline bool operator!=(Tone const& lhs, Tone const& rhs) { return !(lhs == rhs); }
+static inline bool operator<=(Tone const& lhs, Tone const& rhs) { return lhs.freq < rhs.freq || lhs == rhs; }
+static inline bool operator>=(Tone const& lhs, Tone const& rhs) { return lhs.freq > rhs.freq || lhs == rhs; }
+static inline bool operator<(Tone const& lhs, Tone const& rhs) { return lhs.freq < rhs.freq && lhs != rhs; }
+static inline bool operator>(Tone const& lhs, Tone const& rhs) { return lhs.freq > rhs.freq && lhs != rhs; }
+
struct Moment {
typedef std::list<Tone> Tones;
Tones m_tones;
@@ -39,12 +46,16 @@ struct Peak {
Peak(): freqFFT(), freq(), level() {}
};
-static inline bool operator==(Tone const& lhs, Tone const& rhs) { return lhs == rhs.freq; }
-static inline bool operator!=(Tone const& lhs, Tone const& rhs) { return !(lhs == rhs); }
-static inline bool operator<=(Tone const& lhs, Tone const& rhs) { return lhs.freq < rhs.freq || lhs == rhs; }
-static inline bool operator>=(Tone const& lhs, Tone const& rhs) { return lhs.freq > rhs.freq || lhs == rhs; }
-static inline bool operator<(Tone const& lhs, Tone const& rhs) { return lhs.freq < rhs.freq && lhs != rhs; }
-static inline bool operator>(Tone const& lhs, Tone const& rhs) { return lhs.freq > rhs.freq && lhs != rhs; }
+/// A combo combines multiple FFT peaks that all display the same frequency into one
+struct Combo {
+ double freq;
+ double level;
+ Combo(): freq(), level() {}
+ void combine(Peak const& p);
+ bool match(double freqOther) const;
+ static bool cmpByLevel(Combo const& a, Combo const& b) { return a.level < b.level; }
+};
+
static const std::size_t BUF_N = 100000; // Ringbuffer size in samples, major b0rkage will happen if this is too small; it won't cause latency, only wasted RAM
diff --git a/pitchvis.cc b/pitchvis.cc
index 20aea67..9b45539 100644
--- a/pitchvis.cc
+++ b/pitchvis.cc
@@ -40,7 +40,7 @@ void PitchVis::run()
curX = 0;
for (std::vector<float> data(step*2); mpeg.audioQueue(&*data.begin(), &*data.end(), curX * step * 2); ++curX) {
// Mix stereo into mono
- for (unsigned i = 0; i < step; ++i) data[i] = 0.5 * (data[2*i] + data[2*i + 1]);
+ for (unsigned i = 0; i < step; ++i) data[i] = data[2*i]; //0.5 * (data[2*i] + data[2*i + 1]);
// Process
analyzer.input(&data[0], &data[step]);
analyzer.process();
@@ -64,16 +64,19 @@ void PitchVis::run()
Moment::Tones const& tones = it->m_tones;
for (Moment::Tones::const_iterator it2 = tones.begin(), it2end = tones.end(); it2 != it2end; ++it2) {
if (it2->prev) continue; // The tone doesn't begin at this moment, skip
+ // Copy the linked list into vector for easier access and calculate max level
std::vector<Tone const*> tones;
- for (Tone const* n = &*it2; n; n = n->next) tones.push_back(n);
- if (tones.size() < 5) continue; // Too short tone, ignored
+ double lmax = 0.0;
+ for (Tone const* n = &*it2; n; n = n->next) { tones.push_back(n); lmax = std::max(lmax, n->level); }
+ if (tones.size() < 5) continue; // Too short or weak tone, ignored
+ std::cout << tones.size() << ", " << lmax << std::endl;
// Render
for (unsigned i = 0; i < tones.size(); ++i) {
unsigned x = curX + i;
if (x >= width()) throw std::logic_error("Tone past the end of moments");
- float value = 0.003 * (level2dB(tones[i]->level) + 80.0);
+ float value = 0.006 * (level2dB(tones[i]->level) + 60.0);
if (value <= 0.0) continue;
- unsigned int pix = Pixel(0.0f, value, 0.0f).rgba();
+ unsigned int pix = Pixel(0.0f, 1.0f, 0.0f, value).rgba();
unsigned y = freq2px(tones[i]->freq);
for (int j = std::max<int>(0, int(y) - 2), jend = std::min<int>(height, int(y) + 3); j < jend; ++j) rgba[j * width() + x] = pix;
}
diff --git a/pitchvis.hh b/pitchvis.hh
index 1e7b557..cef0ad5 100644
--- a/pitchvis.hh
+++ b/pitchvis.hh
@@ -14,7 +14,7 @@ struct Pixel {
Pixel(float r, float g, float b, float a = 1.0f): r(r), g(g), b(b), a(a) {}
Pixel(): r(), g(), b(), a(1.0f) {}
static unsigned char conv(float c, float a) {
- return static_cast<unsigned char>(255.0 * a * std::sqrt(c)); // sqrt(c) is gamma correction
+ return static_cast<unsigned char>(0.5 + 255.0 * clamp(a * std::sqrt(c))); // sqrt(c) is gamma correction
}
unsigned rgba() const {
unsigned char red = conv(r, a);
@@ -25,10 +25,10 @@ struct Pixel {
}
float& operator[](unsigned idx) { return (&r)[idx]; }
Pixel& operator+=(Pixel const& pix) {
- r = clamp(r + pix.r);
- g = clamp(g + pix.g);
- b = clamp(b + pix.b);
- a = clamp(a + pix.a);
+ r = r + pix.r;
+ g = g + pix.g;
+ b = b + pix.b;
+ a = a + pix.a;
return *this;
}
};
|