Add some preliminary FFT cache aging... while it "works" it doesn't do so in a very useful fashion, since unused cache segments are killed off much faster when you scroll the view in short segments than when doing large scrolls. It should, however, limit memory usage to cache_line_age_limit*line_length*sizeof(float) bytes, which is 64 MB with the current Audio Spectrum Window size.

Originally committed to SVN as r1298.
This commit is contained in:
Niels Martin Hansen 2007-06-24 02:58:33 +00:00
parent b28eeabc47
commit 7779ad6dde
2 changed files with 52 additions and 5 deletions

View File

@ -44,6 +44,7 @@
// Audio spectrum FFT data cache
AudioSpectrumCache::LineAge AudioSpectrumCache::cache_line_age_limit = 0x10000; // TODO: make this less arbitrary
AudioSpectrumCache::CacheLine AudioSpectrumCache::null_line;
unsigned long AudioSpectrumCache::line_length;
@ -60,10 +61,13 @@ class FinalSpectrumCache : public AudioSpectrumCache {
private:
std::vector<CacheLine> data;
unsigned long start, length; // start and end of range
unsigned long last_access; // aging parameter
public:
CacheLine& GetLine(unsigned long i)
CacheLine& GetLine(unsigned long i, LineAge aging_time)
{
last_access = aging_time;
// This check ought to be redundant
if (i >= start && i-start < length)
return data[i - start];
@ -71,10 +75,18 @@ public:
return null_line;
}
bool Age(LineAge aging_time)
{
assert(aging_time >= last_access);
return aging_time - last_access <= cache_line_age_limit;
}
FinalSpectrumCache(AudioProvider *provider, unsigned long _start, unsigned long _length)
{
start = _start;
length = _length;
last_access = 0;
assert(length > 2);
@ -138,7 +150,7 @@ private:
AudioProvider *provider;
public:
CacheLine &GetLine(unsigned long i)
CacheLine &GetLine(unsigned long i, LineAge aging_time)
{
if (i >= start && i-start <= length) {
// Determine which sub-cache this line resides in
@ -153,12 +165,33 @@ public:
}
}
return sub_caches[subcache]->GetLine(i);
return sub_caches[subcache]->GetLine(i, aging_time);
} else {
return null_line;
}
}
bool Age(LineAge aging_time)
{
bool living_caches = false;
// Age every active sub-cache
for (size_t i = 0; i < sub_caches.size(); ++i) {
if (sub_caches[i]) {
if (sub_caches[i]->Age(aging_time)) {
// The sub-cache is still fresh, so we are too
living_caches = true;
} else {
// Sub-cache is too old, remove it
delete sub_caches[i];
sub_caches[i] = 0;
}
}
}
return living_caches;
}
IntermediateSpectrumCache(AudioProvider *_provider, unsigned long _start, unsigned long _length, int _depth)
{
provider = _provider;
@ -203,12 +236,14 @@ AudioSpectrum::AudioSpectrum(AudioProvider *_provider, unsigned long _line_lengt
AudioSpectrumCache::SetLineLength(line_length);
cache = new IntermediateSpectrumCache(provider, 0, num_lines, 0);
cache_age = 0;
power_scale = 1;
minband = Options.AsInt(_T("Audio Spectrum Cutoff"));
maxband = line_length - minband * 2/3; // TODO: make this customisable?
// Generate colour maps
// TODO? allow selecting between several colour maps
unsigned char *palptr = colours_normal;
for (int i = 0; i < 256; i++) {
//hsl_to_rgb(170 + i * 2/3, 128 + i/2, i, palptr+0, palptr+1, palptr+2); // Previous
@ -258,7 +293,8 @@ void AudioSpectrum::RenderRange(__int64 range_start, __int64 range_end, bool sel
if (imgcol <= last_imgcol_rendered)
continue;
AudioSpectrumCache::CacheLine &line = cache->GetLine(i);
AudioSpectrumCache::CacheLine &line = cache->GetLine(i, cache_age);
cache_age++;
// Calculate the signal power over frequency
// "Compressed" scale
@ -325,6 +361,8 @@ void AudioSpectrum::RenderRange(__int64 range_start, __int64 range_end, bool sel
}
delete[] power;
cache->Age(cache_age);
}

View File

@ -46,14 +46,22 @@
class AudioSpectrumCache {
public:
typedef std::vector<float> CacheLine;
typedef unsigned long LineAge;
virtual CacheLine& GetLine(unsigned long i) = 0;
// Get the i'th cache line from the tree and propagate down the current "age time"
virtual CacheLine& GetLine(unsigned long i, LineAge aging_time) = 0;
// Set the desired length of cache lines
static void SetLineLength(unsigned long new_length);
// Perform cache aging process
// Return true if the object Age was called on is still fresh, false if it's old and should be purged
virtual bool Age(LineAge aging_time) = 0;
virtual ~AudioSpectrumCache() {};
protected:
static LineAge cache_line_age_limit;
static CacheLine null_line;
static unsigned long line_length;
};
@ -63,6 +71,7 @@ class AudioSpectrum {
private:
// Data provider
AudioSpectrumCache *cache;
AudioSpectrumCache::LineAge cache_age;
// Colour pallettes
unsigned char colours_normal[256*3];