changeset 201:d892237cf790

* Remove some obsolete files
author Chris Cannam
date Wed, 15 Nov 2006 20:00:48 +0000
parents 2f2d282d45d0
children 91fdc752e540
files data/fileio/FFTDataServer.cpp data/fileio/FFTDataServer.h data/fileio/FFTFileCache.cpp data/fileio/FFTFileCache.h
diffstat 4 files changed, 0 insertions(+), 1365 deletions(-) [+]
line wrap: on
line diff
--- a/data/fileio/FFTDataServer.cpp	Mon Nov 13 14:48:57 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,751 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    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.
-*/
-
-#include "FFTDataServer.h"
-
-#include "FFTFileCache.h"
-
-#include "model/DenseTimeValueModel.h"
-
-#include "base/System.h"
-
-//#define DEBUG_FFT_SERVER 1
-//#define DEBUG_FFT_SERVER_FILL 1
-
-#ifdef DEBUG_FFT_SERVER_FILL
-#define DEBUG_FFT_SERVER
-#endif
-
-FFTDataServer::ServerMap FFTDataServer::m_servers;
-QMutex FFTDataServer::m_serverMapMutex;
-
-FFTDataServer *
-FFTDataServer::getInstance(const DenseTimeValueModel *model,
-                           int channel,
-                           WindowType windowType,
-                           size_t windowSize,
-                           size_t windowIncrement,
-                           size_t fftSize,
-                           bool polar,
-                           size_t fillFromColumn)
-{
-    QString n = generateFileBasename(model,
-                                     channel,
-                                     windowType,
-                                     windowSize,
-                                     windowIncrement,
-                                     fftSize,
-                                     polar);
-
-    FFTDataServer *server = 0;
-    
-    QMutexLocker locker(&m_serverMapMutex);
-
-    if ((server = findServer(n))) {
-        return server;
-    }
-
-    QString npn = generateFileBasename(model,
-                                       channel,
-                                       windowType,
-                                       windowSize,
-                                       windowIncrement,
-                                       fftSize,
-                                       !polar);
-
-    if ((server = findServer(npn))) {
-        return server;
-    }
-
-    m_servers[n] = ServerCountPair
-        (new FFTDataServer(n,
-                           model,
-                           channel,
-                           windowType,
-                           windowSize,
-                           windowIncrement,
-                           fftSize,
-                           polar,
-                           fillFromColumn),
-         1);
-
-    return m_servers[n].first;
-}
-
-FFTDataServer *
-FFTDataServer::getFuzzyInstance(const DenseTimeValueModel *model,
-                                int channel,
-                                WindowType windowType,
-                                size_t windowSize,
-                                size_t windowIncrement,
-                                size_t fftSize,
-                                bool polar,
-                                size_t fillFromColumn)
-{
-    // Fuzzy matching:
-    // 
-    // -- if we're asked for polar and have non-polar, use it (and
-    // vice versa).  This one is vital, and we do it for non-fuzzy as
-    // well (above).
-    //
-    // -- if we're asked for an instance with a given fft size and we
-    // have one already with a multiple of that fft size but the same
-    // window size and type (and model), we can draw the results from
-    // it (e.g. the 1st, 2nd, 3rd etc bins of a 512-sample FFT are the
-    // same as the the 1st, 5th, 9th etc of a 2048-sample FFT of the
-    // same window plus zero padding).
-    //
-    // -- if we're asked for an instance with a given window type and
-    // size and fft size and we have one already the same but with a
-    // smaller increment, we can draw the results from it (provided
-    // our increment is a multiple of its)
-    //
-    // The FFTFuzzyAdapter knows how to interpret these things.  In
-    // both cases we require that the larger one is a power-of-two
-    // multiple of the smaller (e.g. even though in principle you can
-    // draw the results at increment 256 from those at increment 768
-    // or 1536, the fuzzy adapter doesn't support this).
-
-    {
-        QMutexLocker locker(&m_serverMapMutex);
-
-        ServerMap::iterator best = m_servers.end();
-        int bestdist = -1;
-    
-        for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) {
-
-            FFTDataServer *server = i->second.first;
-
-            if (server->getModel() == model &&
-                (server->getChannel() == channel || model->getChannelCount() == 1) &&
-                server->getWindowType() == windowType &&
-                server->getWindowSize() == windowSize &&
-                server->getWindowIncrement() <= windowIncrement &&
-                server->getFFTSize() >= fftSize) {
-                
-                if ((windowIncrement % server->getWindowIncrement()) != 0) continue;
-                int ratio = windowIncrement / server->getWindowIncrement();
-                bool poweroftwo = true;
-                while (ratio > 1) {
-                    if (ratio & 0x1) {
-                        poweroftwo = false;
-                        break;
-                    }
-                    ratio >>= 1;
-                }
-                if (!poweroftwo) continue;
-
-                if ((server->getFFTSize() % fftSize) != 0) continue;
-                ratio = server->getFFTSize() / fftSize;
-                while (ratio > 1) {
-                    if (ratio & 0x1) {
-                        poweroftwo = false;
-                        break;
-                    }
-                    ratio >>= 1;
-                }
-                if (!poweroftwo) continue;
-                
-                int distance = 0;
-                
-                if (server->getPolar() != polar) distance += 1;
-                
-                distance += ((windowIncrement / server->getWindowIncrement()) - 1) * 15;
-                distance += ((server->getFFTSize() / fftSize) - 1) * 10;
-                
-                if (server->getFillCompletion() < 50) distance += 100;
-
-#ifdef DEBUG_FFT_SERVER
-                std::cerr << "Distance " << distance << ", best is " << bestdist << std::endl;
-#endif
-                
-                if (bestdist == -1 || distance < bestdist) {
-                    bestdist = distance;
-                    best = i;
-                }
-            }
-        }
-
-        if (bestdist >= 0) {
-            ++best->second.second;
-            return best->second.first;
-        }
-    }
-
-    // Nothing found, make a new one
-
-    return getInstance(model,
-                       channel,
-                       windowType,
-                       windowSize,
-                       windowIncrement,
-                       fftSize,
-                       polar,
-                       fillFromColumn);
-}
-
-FFTDataServer *
-FFTDataServer::findServer(QString n)
-{    
-    if (m_servers.find(n) != m_servers.end()) {
-        ++m_servers[n].second;
-        return m_servers[n].first;
-    }
-
-    return 0;
-}
-
-void
-FFTDataServer::releaseInstance(FFTDataServer *server)
-{
-#ifdef DEBUG_FFT_SERVER
-    std::cerr << "FFTDataServer::releaseInstance(" << server << ")" << std::endl;
-#endif
-
-    QMutexLocker locker(&m_serverMapMutex);
-
-    //!!! not a good strategy.  Want something like:
-
-    // -- if ref count > 0, decrement and return
-    // -- if the instance hasn't been used at all, delete it immediately 
-    // -- if fewer than N instances (N = e.g. 3) remain with zero refcounts,
-    //    leave them hanging around
-    // -- if N instances with zero refcounts remain, delete the one that
-    //    was last released first
-    // -- if we run out of disk space when allocating an instance, go back
-    //    and delete the spare N instances before trying again
-    // -- have an additional method to indicate that a model has been
-    //    destroyed, so that we can delete all of its fft server instances
-
-    // also:
-    //
-
-    for (ServerMap::iterator i = m_servers.begin(); i != m_servers.end(); ++i) {
-        if (i->second.first == server) {
-            if (i->second.second == 0) {
-                std::cerr << "ERROR: FFTDataServer::releaseInstance("
-                          << server << "): instance not allocated" << std::endl;
-            } else if (--i->second.second == 0) {
-                if (server->m_lastUsedCache == -1) { // never used
-                    delete server;
-                    m_servers.erase(i);
-                } else {
-                    server->suspend();
-                    purgeLimbo();
-                }
-            }
-            return;
-        }
-    }
-
-    std::cerr << "ERROR: FFTDataServer::releaseInstance(" << server << "): "
-              << "instance not found" << std::endl;
-}
-
-void
-FFTDataServer::purgeLimbo(int maxSize)
-{
-    ServerMap::iterator i = m_servers.end();
-
-    int count = 0;
-
-    while (i != m_servers.begin()) {
-        --i;
-        if (i->second.second == 0) {
-            if (++count > maxSize) {
-                delete i->second.first;
-                m_servers.erase(i);
-                return;
-            }
-        }
-    }
-}
-
-FFTDataServer::FFTDataServer(QString fileBaseName,
-                             const DenseTimeValueModel *model,
-                             int channel,
-			     WindowType windowType,
-			     size_t windowSize,
-			     size_t windowIncrement,
-			     size_t fftSize,
-                             bool polar,
-                             size_t fillFromColumn) :
-    m_fileBaseName(fileBaseName),
-    m_model(model),
-    m_channel(channel),
-    m_windower(windowType, windowSize),
-    m_windowSize(windowSize),
-    m_windowIncrement(windowIncrement),
-    m_fftSize(fftSize),
-    m_polar(polar),
-    m_lastUsedCache(-1),
-    m_fftInput(0),
-    m_exiting(false),
-    m_fillThread(0)
-{
-    size_t start = m_model->getStartFrame();
-    size_t end = m_model->getEndFrame();
-
-    m_width = (end - start) / m_windowIncrement + 1;
-    m_height = m_fftSize / 2;
-
-    size_t maxCacheSize = 20 * 1024 * 1024;
-    size_t columnSize = m_height * sizeof(fftsample) * 2 + sizeof(fftsample);
-    if (m_width * columnSize < maxCacheSize * 2) m_cacheWidth = m_width;
-    else m_cacheWidth = maxCacheSize / columnSize;
-    
-    int bits = 0;
-    while (m_cacheWidth) { m_cacheWidth >>= 1; ++bits; }
-    m_cacheWidth = 2;
-    while (bits) { m_cacheWidth <<= 1; --bits; }
-    
-#ifdef DEBUG_FFT_SERVER
-    std::cerr << "Width " << m_width << ", cache width " << m_cacheWidth << " (size " << m_cacheWidth * columnSize << ")" << std::endl;
-#endif
-
-    for (size_t i = 0; i <= m_width / m_cacheWidth; ++i) {
-        m_caches.push_back(0);
-    }
-
-    m_fftInput = (fftsample *)
-        fftwf_malloc(fftSize * sizeof(fftsample));
-
-    m_fftOutput = (fftwf_complex *)
-        fftwf_malloc(fftSize * sizeof(fftwf_complex));
-
-    m_workbuffer = (float *)
-        fftwf_malloc(fftSize * sizeof(float));
-
-    m_fftPlan = fftwf_plan_dft_r2c_1d(m_fftSize,
-                                      m_fftInput,
-                                      m_fftOutput,
-                                      FFTW_ESTIMATE);
-
-    if (!m_fftPlan) {
-        std::cerr << "ERROR: fftwf_plan_dft_r2c_1d(" << m_windowSize << ") failed!" << std::endl;
-        throw(0);
-    }
-
-    m_fillThread = new FillThread(*this, fillFromColumn);
-
-    //!!! respond appropriately when thread exits (deleteProcessingData etc)
-}
-
-FFTDataServer::~FFTDataServer()
-{
-#ifdef DEBUG_FFT_SERVER
-    std::cerr << "FFTDataServer(" << this << ")::~FFTDataServer()" << std::endl;
-#endif
-
-    m_exiting = true;
-    m_condition.wakeAll();
-    if (m_fillThread) {
-        m_fillThread->wait();
-        delete m_fillThread;
-    }
-
-    QMutexLocker locker(&m_writeMutex);
-
-    for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) {
-        delete *i;
-    }
-
-    deleteProcessingData();
-}
-
-void
-FFTDataServer::deleteProcessingData()
-{
-    if (m_fftInput) {
-        fftwf_destroy_plan(m_fftPlan);
-        fftwf_free(m_fftInput);
-        fftwf_free(m_fftOutput);
-        fftwf_free(m_workbuffer);
-    }
-    m_fftInput = 0;
-}
-
-void
-FFTDataServer::suspend()
-{
-#ifdef DEBUG_FFT_SERVER
-    std::cerr << "FFTDataServer(" << this << "): suspend" << std::endl;
-#endif
-    QMutexLocker locker(&m_writeMutex);
-    m_suspended = true;
-    for (CacheVector::iterator i = m_caches.begin(); i != m_caches.end(); ++i) {
-        if (*i) (*i)->suspend();
-    }
-}
-
-void
-FFTDataServer::resume()
-{
-    m_suspended = false;
-    m_condition.wakeAll();
-}
-
-FFTCache *
-FFTDataServer::getCacheAux(size_t c)
-{
-    QMutexLocker locker(&m_writeMutex);
-
-    if (m_lastUsedCache == -1) {
-        m_fillThread->start();
-    }
-
-    if (int(c) != m_lastUsedCache) {
-
-//        std::cerr << "switch from " << m_lastUsedCache << " to " << c << std::endl;
-
-        for (IntQueue::iterator i = m_dormantCaches.begin();
-             i != m_dormantCaches.end(); ++i) {
-            if (*i == c) {
-                m_dormantCaches.erase(i);
-                break;
-            }
-        }
-
-        if (m_lastUsedCache >= 0) {
-            bool inDormant = false;
-            for (size_t i = 0; i < m_dormantCaches.size(); ++i) {
-                if (m_dormantCaches[i] == m_lastUsedCache) {
-                    inDormant = true;
-                    break;
-                }
-            }
-            if (!inDormant) {
-                m_dormantCaches.push_back(m_lastUsedCache);
-            }
-            while (m_dormantCaches.size() > 4) {
-                int dc = m_dormantCaches.front();
-                m_dormantCaches.pop_front();
-                m_caches[dc]->suspend();
-            }
-        }
-    }
-
-    if (m_caches[c]) {
-        m_lastUsedCache = c;
-        return m_caches[c];
-    }
-
-    QString name = QString("%1-%2").arg(m_fileBaseName).arg(c);
-
-    FFTCache *cache = new FFTFileCache(name, MatrixFile::ReadWrite,
-                                       m_polar ? FFTFileCache::Polar :
-                                                 FFTFileCache::Rectangular);
-
-    size_t width = m_cacheWidth;
-    if (c * m_cacheWidth + width > m_width) {
-        width = m_width - c * m_cacheWidth;
-    }
-
-    cache->resize(width, m_height);
-    cache->reset();
-
-    m_caches[c] = cache;
-    m_lastUsedCache = c;
-
-    return cache;
-}
-
-float
-FFTDataServer::getMagnitudeAt(size_t x, size_t y)
-{
-    size_t col;
-    FFTCache *cache = getCache(x, col);
-
-    if (!cache->haveSetColumnAt(col)) {
-        fillColumn(x);
-    }
-    return cache->getMagnitudeAt(col, y);
-}
-
-float
-FFTDataServer::getNormalizedMagnitudeAt(size_t x, size_t y)
-{
-    size_t col;
-    FFTCache *cache = getCache(x, col);
-
-    if (!cache->haveSetColumnAt(col)) {
-        fillColumn(x);
-    }
-    return cache->getNormalizedMagnitudeAt(col, y);
-}
-
-float
-FFTDataServer::getMaximumMagnitudeAt(size_t x)
-{
-    size_t col;
-    FFTCache *cache = getCache(x, col);
-
-    if (!cache->haveSetColumnAt(col)) {
-        fillColumn(x);
-    }
-    return cache->getMaximumMagnitudeAt(col);
-}
-
-float
-FFTDataServer::getPhaseAt(size_t x, size_t y)
-{
-    size_t col;
-    FFTCache *cache = getCache(x, col);
-
-    if (!cache->haveSetColumnAt(col)) {
-        fillColumn(x);
-    }
-    return cache->getPhaseAt(col, y);
-}
-
-void
-FFTDataServer::getValuesAt(size_t x, size_t y, float &real, float &imaginary)
-{
-    size_t col;
-    FFTCache *cache = getCache(x, col);
-
-    if (!cache->haveSetColumnAt(col)) {
-#ifdef DEBUG_FFT_SERVER
-        std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl;
-#endif
-        fillColumn(x);
-    }        
-    float magnitude = cache->getMagnitudeAt(col, y);
-    float phase = cache->getPhaseAt(col, y);
-    real = magnitude * cosf(phase);
-    imaginary = magnitude * sinf(phase);
-}
-
-bool
-FFTDataServer::isColumnReady(size_t x)
-{
-    if (!haveCache(x)) {
-        if (m_lastUsedCache == -1) {
-            m_fillThread->start();
-        }
-        return false;
-    }
-
-    size_t col;
-    FFTCache *cache = getCache(x, col);
-
-    return cache->haveSetColumnAt(col);
-}    
-
-void
-FFTDataServer::fillColumn(size_t x)
-{
-    size_t col;
-#ifdef DEBUG_FFT_SERVER_FILL
-    std::cout << "FFTDataServer::fillColumn(" << x << ")" << std::endl;
-#endif
-    FFTCache *cache = getCache(x, col);
-
-    QMutexLocker locker(&m_writeMutex);
-
-    if (cache->haveSetColumnAt(col)) return;
-
-    int startFrame = m_windowIncrement * x;
-    int endFrame = startFrame + m_windowSize;
-
-    startFrame -= int(m_windowSize - m_windowIncrement) / 2;
-    endFrame   -= int(m_windowSize - m_windowIncrement) / 2;
-    size_t pfx = 0;
-
-    size_t off = (m_fftSize - m_windowSize) / 2;
-
-    for (size_t i = 0; i < off; ++i) {
-        m_fftInput[i] = 0.0;
-        m_fftInput[m_fftSize - i - 1] = 0.0;
-    }
-
-    if (startFrame < 0) {
-	pfx = size_t(-startFrame);
-	for (size_t i = 0; i < pfx; ++i) {
-	    m_fftInput[off + i] = 0.0;
-	}
-    }
-
-    size_t got = m_model->getValues(m_channel, startFrame + pfx,
-				    endFrame, m_fftInput + off + pfx);
-
-    while (got + pfx < m_windowSize) {
-	m_fftInput[off + got + pfx] = 0.0;
-	++got;
-    }
-
-    if (m_channel == -1) {
-	int channels = m_model->getChannelCount();
-	if (channels > 1) {
-	    for (size_t i = 0; i < m_windowSize; ++i) {
-		m_fftInput[off + i] /= channels;
-	    }
-	}
-    }
-
-    m_windower.cut(m_fftInput + off);
-
-    for (size_t i = 0; i < m_fftSize/2; ++i) {
-	fftsample temp = m_fftInput[i];
-	m_fftInput[i] = m_fftInput[i + m_fftSize/2];
-	m_fftInput[i + m_fftSize/2] = temp;
-    }
-
-    fftwf_execute(m_fftPlan);
-
-    fftsample factor = 0.0;
-
-    for (size_t i = 0; i < m_fftSize/2; ++i) {
-
-	fftsample mag = sqrtf(m_fftOutput[i][0] * m_fftOutput[i][0] +
-                              m_fftOutput[i][1] * m_fftOutput[i][1]);
-	mag /= m_windowSize / 2;
-
-	if (mag > factor) factor = mag;
-
-	fftsample phase = atan2f(m_fftOutput[i][1], m_fftOutput[i][0]);
-	phase = princargf(phase);
-
-        m_workbuffer[i] = mag;
-        m_workbuffer[i + m_fftSize/2] = phase;
-    }
-
-    cache->setColumnAt(col,
-                       m_workbuffer,
-                       m_workbuffer + m_fftSize/2,
-                       factor);
-}    
-
-size_t
-FFTDataServer::getFillCompletion() const 
-{
-    if (m_fillThread) return m_fillThread->getCompletion();
-    else return 100;
-}
-
-size_t
-FFTDataServer::getFillExtent() const
-{
-    if (m_fillThread) return m_fillThread->getExtent();
-    else return m_model->getEndFrame();
-}
-
-QString
-FFTDataServer::generateFileBasename() const
-{
-    return generateFileBasename(m_model, m_channel, m_windower.getType(),
-                                m_windowSize, m_windowIncrement, m_fftSize,
-                                m_polar);
-}
-
-QString
-FFTDataServer::generateFileBasename(const DenseTimeValueModel *model,
-                                    int channel,
-                                    WindowType windowType,
-                                    size_t windowSize,
-                                    size_t windowIncrement,
-                                    size_t fftSize,
-                                    bool polar)
-{
-    char buffer[200];
-
-    sprintf(buffer, "%u-%u-%u-%u-%u-%u%s",
-            (unsigned int)XmlExportable::getObjectExportId(model),
-            (unsigned int)(channel + 1),
-            (unsigned int)windowType,
-            (unsigned int)windowSize,
-            (unsigned int)windowIncrement,
-            (unsigned int)fftSize,
-            polar ? "-p" : "-r");
-
-    return buffer;
-}
-
-void
-FFTDataServer::FillThread::run()
-{
-    m_extent = 0;
-    m_completion = 0;
-    
-    size_t start = m_server.m_model->getStartFrame();
-    size_t end = m_server.m_model->getEndFrame();
-    size_t remainingEnd = end;
-
-    int counter = 0;
-    int updateAt = (end / m_server.m_windowIncrement) / 20;
-    if (updateAt < 100) updateAt = 100;
-
-    if (m_fillFrom > start) {
-
-        for (size_t f = m_fillFrom; f < end; f += m_server.m_windowIncrement) {
-	    
-            m_server.fillColumn(int((f - start) / m_server.m_windowIncrement));
-
-            if (m_server.m_exiting) return;
-
-            while (m_server.m_suspended) {
-#ifdef DEBUG_FFT_SERVER
-                std::cerr << "FFTDataServer(" << this << "): suspended, waiting..." << std::endl;
-#endif
-                m_server.m_writeMutex.lock();
-                m_server.m_condition.wait(&m_server.m_writeMutex, 10000);
-                m_server.m_writeMutex.unlock();
-                if (m_server.m_exiting) return;
-            }
-
-            if (++counter == updateAt) {
-                m_extent = f;
-                m_completion = size_t(100 * fabsf(float(f - m_fillFrom) /
-                                                  float(end - start)));
-                counter = 0;
-            }
-        }
-
-        remainingEnd = m_fillFrom;
-        if (remainingEnd > start) --remainingEnd;
-        else remainingEnd = start;
-    }
-
-    size_t baseCompletion = m_completion;
-
-    for (size_t f = start; f < remainingEnd; f += m_server.m_windowIncrement) {
-
-        m_server.fillColumn(int((f - start) / m_server.m_windowIncrement));
-
-        if (m_server.m_exiting) return;
-
-        while (m_server.m_suspended) {
-#ifdef DEBUG_FFT_SERVER
-            std::cerr << "FFTDataServer(" << this << "): suspended, waiting..." << std::endl;
-#endif
-            m_server.m_writeMutex.lock();
-            m_server.m_condition.wait(&m_server.m_writeMutex, 10000);
-            m_server.m_writeMutex.unlock();
-            if (m_server.m_exiting) return;
-        }
-		    
-        if (++counter == updateAt) {
-            m_extent = f;
-            m_completion = baseCompletion +
-                size_t(100 * fabsf(float(f - start) /
-                                   float(end - start)));
-            counter = 0;
-        }
-    }
-
-    m_completion = 100;
-    m_extent = end;
-}
-
--- a/data/fileio/FFTDataServer.h	Mon Nov 13 14:48:57 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,201 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    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.
-*/
-
-#ifndef _FFT_DATA_SERVER_H_
-#define _FFT_DATA_SERVER_H_
-
-#include "base/Window.h"
-#include "base/Thread.h"
-
-#include <fftw3.h>
-
-#include <QMutex>
-#include <QWaitCondition>
-#include <QString>
-
-#include <vector>
-#include <deque>
-
-class DenseTimeValueModel;
-class FFTCache;
-
-class FFTDataServer
-{
-public:
-    static FFTDataServer *getInstance(const DenseTimeValueModel *model,
-                                      int channel,
-                                      WindowType windowType,
-                                      size_t windowSize,
-                                      size_t windowIncrement,
-                                      size_t fftSize,
-                                      bool polar,
-                                      size_t fillFromColumn = 0);
-
-    static FFTDataServer *getFuzzyInstance(const DenseTimeValueModel *model,
-                                           int channel,
-                                           WindowType windowType,
-                                           size_t windowSize,
-                                           size_t windowIncrement,
-                                           size_t fftSize,
-                                           bool polar,
-                                           size_t fillFromColumn = 0);
-
-    static void releaseInstance(FFTDataServer *);
-
-    const DenseTimeValueModel *getModel() const { return m_model; }
-    int        getChannel() const { return m_channel; }
-    WindowType getWindowType() const { return m_windower.getType(); }
-    size_t     getWindowSize() const { return m_windowSize; }
-    size_t     getWindowIncrement() const { return m_windowIncrement; }
-    size_t     getFFTSize() const { return m_fftSize; }
-    bool       getPolar() const { return m_polar; }
-
-    size_t     getWidth() const  { return m_width;  }
-    size_t     getHeight() const { return m_height; }
-
-    float      getMagnitudeAt(size_t x, size_t y);
-    float      getNormalizedMagnitudeAt(size_t x, size_t y);
-    float      getMaximumMagnitudeAt(size_t x);
-    float      getPhaseAt(size_t x, size_t y);
-    void       getValuesAt(size_t x, size_t y, float &real, float &imaginary);
-    bool       isColumnReady(size_t x);
-
-    void       suspend();
-
-    // Convenience functions:
-
-    bool isLocalPeak(size_t x, size_t y) {
-        float mag = getMagnitudeAt(x, y);
-        if (y > 0 && mag < getMagnitudeAt(x, y - 1)) return false;
-        if (y < getHeight()-1 && mag < getMagnitudeAt(x, y + 1)) return false;
-        return true;
-    }
-    bool isOverThreshold(size_t x, size_t y, float threshold) {
-        return getMagnitudeAt(x, y) > threshold;
-    }
-
-    size_t getFillCompletion() const;
-    size_t getFillExtent() const;
-
-private:
-    FFTDataServer(QString fileBaseName,
-                  const DenseTimeValueModel *model,
-                  int channel,
-                  WindowType windowType,
-                  size_t windowSize,
-                  size_t windowIncrement,
-                  size_t fftSize,
-                  bool polar,
-                  size_t fillFromColumn = 0);
-
-    virtual ~FFTDataServer();
-
-    FFTDataServer(const FFTDataServer &); // not implemented
-    FFTDataServer &operator=(const FFTDataServer &); // not implemented
-
-    typedef float fftsample;
-
-    QString m_fileBaseName;
-    const DenseTimeValueModel *m_model;
-    int m_channel;
-
-    Window<fftsample> m_windower;
-
-    size_t m_windowSize;
-    size_t m_windowIncrement;
-    size_t m_fftSize;
-    bool m_polar;
-
-    size_t m_width;
-    size_t m_height;
-    size_t m_cacheWidth;
-
-    typedef std::vector<FFTCache *> CacheVector;
-    CacheVector m_caches;
-    
-    typedef std::deque<int> IntQueue;
-    IntQueue m_dormantCaches;
-
-    int m_lastUsedCache;
-    FFTCache *getCache(size_t x, size_t &col) {
-        if (m_suspended) resume();
-        col   = x % m_cacheWidth;
-        int c = x / m_cacheWidth;
-        // The only use of m_lastUsedCache without a lock is to
-        // establish whether a cache has been created at all (they're
-        // created on demand, but not destroyed until the server is).
-        if (c == m_lastUsedCache) return m_caches[c];
-        else return getCacheAux(c);
-    }
-    bool haveCache(size_t x) {
-        int c = x / m_cacheWidth;
-        if (c == m_lastUsedCache) return true;
-        else return (m_caches[c] != 0);
-    }
-        
-    FFTCache *getCacheAux(size_t c);
-    QMutex m_writeMutex;
-    QWaitCondition m_condition;
-
-    fftsample *m_fftInput;
-    fftwf_complex *m_fftOutput;
-    float *m_workbuffer;
-    fftwf_plan m_fftPlan;
-
-    class FillThread : public Thread
-    {
-    public:
-        FillThread(FFTDataServer &server, size_t fillFromColumn) :
-            m_server(server), m_extent(0), m_completion(0),
-            m_fillFrom(fillFromColumn) { }
-
-        size_t getExtent() const { return m_extent; }
-        size_t getCompletion() const { return m_completion ? m_completion : 1; }
-        virtual void run();
-
-    protected:
-        FFTDataServer &m_server;
-        size_t m_extent;
-        size_t m_completion;
-        size_t m_fillFrom;
-    };
-
-    bool m_exiting;
-    bool m_suspended;
-    FillThread *m_fillThread;
-
-    void deleteProcessingData();
-    void fillColumn(size_t x);
-    void resume();
-
-    QString generateFileBasename() const;
-    static QString generateFileBasename(const DenseTimeValueModel *model,
-                                        int channel,
-                                        WindowType windowType,
-                                        size_t windowSize,
-                                        size_t windowIncrement,
-                                        size_t fftSize,
-                                        bool polar);
-
-    typedef std::pair<FFTDataServer *, int> ServerCountPair;
-    typedef std::map<QString, ServerCountPair> ServerMap;
-
-    static ServerMap m_servers;
-    static QMutex m_serverMapMutex;
-    static FFTDataServer *findServer(QString); // call with serverMapMutex held
-    static void purgeLimbo(int maxSize = 3); // call with serverMapMutex held
-};
-
-#endif
--- a/data/fileio/FFTFileCache.cpp	Mon Nov 13 14:48:57 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,288 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    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.
-*/
-
-#include "FFTFileCache.h"
-
-#include "MatrixFile.h"
-
-#include "base/Profiler.h"
-
-#include <iostream>
-
-#include <QMutexLocker>
-
-// The underlying matrix has height (m_height * 2 + 1).  In each
-// column we store magnitude at [0], [2] etc and phase at [1], [3]
-// etc, and then store the normalization factor (maximum magnitude) at
-// [m_height * 2].
-
-FFTFileCache::FFTFileCache(QString fileBase, MatrixFile::Mode mode,
-                           StorageType storageType) :
-    m_writebuf(0),
-    m_readbuf(0),
-    m_readbufCol(0),
-    m_readbufWidth(0),
-    m_mfc(new MatrixFile
-          (fileBase, mode, 
-           storageType == Compact ? sizeof(uint16_t) : sizeof(float),
-           mode == MatrixFile::ReadOnly)),
-    m_storageType(storageType)
-{
-    std::cerr << "FFTFileCache: storage type is " << (storageType == Compact ? "Compact" : storageType == Polar ? "Polar" : "Rectangular") << std::endl;
-}
-
-FFTFileCache::~FFTFileCache()
-{
-    if (m_readbuf) delete[] m_readbuf;
-    if (m_writebuf) delete[] m_writebuf;
-    delete m_mfc;
-}
-
-size_t
-FFTFileCache::getWidth() const
-{
-    return m_mfc->getWidth();
-}
-
-size_t
-FFTFileCache::getHeight() const
-{
-    size_t mh = m_mfc->getHeight();
-    if (mh > 0) return (mh - 1) / 2;
-    else return 0;
-}
-
-void
-FFTFileCache::resize(size_t width, size_t height)
-{
-    QMutexLocker locker(&m_writeMutex);
-
-    m_mfc->resize(width, height * 2 + 1);
-    if (m_readbuf) {
-        delete[] m_readbuf;
-        m_readbuf = 0;
-    }
-    if (m_writebuf) {
-        delete[] m_writebuf;
-    }
-    m_writebuf = new char[(height * 2 + 1) * m_mfc->getCellSize()];
-}
-
-void
-FFTFileCache::reset()
-{
-    m_mfc->reset();
-}
-
-float
-FFTFileCache::getMagnitudeAt(size_t x, size_t y) const
-{
-    float value = 0.f;
-
-    switch (m_storageType) {
-
-    case Compact:
-        value = (getFromReadBufCompactUnsigned(x, y * 2) / 65535.0)
-            * getNormalizationFactor(x);
-        break;
-
-    case Rectangular:
-    {
-        float real, imag;
-        getValuesAt(x, y, real, imag);
-        value = sqrtf(real * real + imag * imag);
-        break;
-    }
-
-    case Polar:
-        value = getFromReadBufStandard(x, y * 2);
-        break;
-    }
-
-    return value;
-}
-
-float
-FFTFileCache::getNormalizedMagnitudeAt(size_t x, size_t y) const
-{
-    float value = 0.f;
-
-    switch (m_storageType) {
-
-    case Compact:
-        value = getFromReadBufCompactUnsigned(x, y * 2) / 65535.0;
-        break;
-
-    default:
-    {
-        float mag = getMagnitudeAt(x, y);
-        float factor = getNormalizationFactor(x);
-        if (factor != 0) value = mag / factor;
-        else value = 0.f;
-        break;
-    }
-    }
-
-    return value;
-}
-
-float
-FFTFileCache::getMaximumMagnitudeAt(size_t x) const
-{
-    return getNormalizationFactor(x);
-}
-
-float
-FFTFileCache::getPhaseAt(size_t x, size_t y) const
-{
-    float value = 0.f;
-    
-    switch (m_storageType) {
-
-    case Compact:
-        value = (getFromReadBufCompactSigned(x, y * 2 + 1) / 32767.0) * M_PI;
-        break;
-
-    case Rectangular:
-    {
-        float real, imag;
-        getValuesAt(x, y, real, imag);
-        value = princargf(atan2f(imag, real));
-        break;
-    }
-
-    case Polar:
-        value = getFromReadBufStandard(x, y * 2 + 1);
-        break;
-    }
-
-    return value;
-}
-
-void
-FFTFileCache::getValuesAt(size_t x, size_t y, float &real, float &imag) const
-{
-    switch (m_storageType) {
-
-    case Rectangular:
-        real = getFromReadBufStandard(x, y * 2);
-        imag = getFromReadBufStandard(x, y * 2 + 1);
-        return;
-
-    default:
-        float mag = getMagnitudeAt(x, y);
-        float phase = getPhaseAt(x, y);
-        real = mag * cosf(phase);
-        imag = mag * sinf(phase);
-        return;
-    }
-}
-
-bool
-FFTFileCache::haveSetColumnAt(size_t x) const
-{
-    return m_mfc->haveSetColumnAt(x);
-}
-
-void
-FFTFileCache::setColumnAt(size_t x, float *mags, float *phases, float factor)
-{
-    QMutexLocker locker(&m_writeMutex);
-
-    size_t h = getHeight();
-
-    switch (m_storageType) {
-
-    case Compact:
-        for (size_t y = 0; y < h; ++y) {
-            ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mags[y] / factor) * 65535.0);
-            ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phases[y] * 32767) / M_PI));
-        }
-        break;
-
-    case Rectangular:
-        for (size_t y = 0; y < h; ++y) {
-            ((float *)m_writebuf)[y * 2] = mags[y] * cosf(phases[y]);
-            ((float *)m_writebuf)[y * 2 + 1] = mags[y] * sinf(phases[y]);
-        }
-        break;
-
-    case Polar:
-        for (size_t y = 0; y < h; ++y) {
-            ((float *)m_writebuf)[y * 2] = mags[y];
-            ((float *)m_writebuf)[y * 2 + 1] = phases[y];
-        }
-        break;
-    }
-
-    static float maxFactor = 0;
-    if (factor > maxFactor) maxFactor = factor;
-//    std::cerr << "Normalization factor: " << factor << ", max " << maxFactor << " (height " << getHeight() << ")" << std::endl;
-
-    if (m_storageType == Compact) {
-        ((uint16_t *)m_writebuf)[h * 2] = factor * 65535.0;
-    } else {
-        ((float *)m_writebuf)[h * 2] = factor;
-    }
-    m_mfc->setColumnAt(x, m_writebuf);
-}
-
-void
-FFTFileCache::setColumnAt(size_t x, float *real, float *imag)
-{
-    QMutexLocker locker(&m_writeMutex);
-
-    size_t h = getHeight();
-
-    float max = 0.0f;
-
-    switch (m_storageType) {
-
-    case Compact:
-        for (size_t y = 0; y < h; ++y) {
-            float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
-            if (mag > max) max = mag;
-        }
-        for (size_t y = 0; y < h; ++y) {
-            float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
-            float phase = princargf(atan2f(imag[y], real[y]));
-            ((uint16_t *)m_writebuf)[y * 2] = uint16_t((mag / max) * 65535.0);
-            ((uint16_t *)m_writebuf)[y * 2 + 1] = uint16_t(int16_t((phase * 32767) / M_PI));
-        }
-        break;
-
-    case Rectangular:
-        for (size_t y = 0; y < h; ++y) {
-            ((float *)m_writebuf)[y * 2] = real[y];
-            ((float *)m_writebuf)[y * 2 + 1] = imag[y];
-            float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
-            if (mag > max) max = mag;
-        }
-        break;
-
-    case Polar:
-        for (size_t y = 0; y < h; ++y) {
-            float mag = sqrtf(real[y] * real[y] + imag[y] * imag[y]);
-            if (mag > max) max = mag;
-            ((float *)m_writebuf)[y * 2] = mag;
-            ((float *)m_writebuf)[y * 2 + 1] = princargf(atan2f(imag[y], real[y]));
-        }
-        break;
-    }
-
-    ((float *)m_writebuf)[h * 2] = max;
-    m_mfc->setColumnAt(x, m_writebuf);
-}
-
--- a/data/fileio/FFTFileCache.h	Mon Nov 13 14:48:57 2006 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
-
-/*
-    Sonic Visualiser
-    An audio file viewer and annotation editor.
-    Centre for Digital Music, Queen Mary, University of London.
-    This file copyright 2006 Chris Cannam.
-    
-    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.
-*/
-
-#ifndef _FFT_FILE_CACHE_H_
-#define _FFT_FILE_CACHE_H_
-
-#include "FFTCache.h"
-#include "MatrixFile.h"
-
-#include <QMutex>
-
-class FFTFileCache : public FFTCache
-{
-public:
-    enum StorageType {
-        Compact, // 16 bits normalized polar
-        Rectangular, // floating point real+imag
-        Polar, // floating point mag+phase
-    };
-
-    FFTFileCache(QString fileBase, MatrixFile::Mode mode,
-                 StorageType storageType);
-    virtual ~FFTFileCache();
-
-    MatrixFile::Mode getMode() const { return m_mfc->getMode(); }
-
-    virtual size_t getWidth() const;
-    virtual size_t getHeight() const;
-	
-    virtual void resize(size_t width, size_t height);
-    virtual void reset(); // zero-fill or 1-fill as appropriate without changing size
-	
-    virtual float getMagnitudeAt(size_t x, size_t y) const;
-    virtual float getNormalizedMagnitudeAt(size_t x, size_t y) const;
-    virtual float getMaximumMagnitudeAt(size_t x) const;
-    virtual float getPhaseAt(size_t x, size_t y) const;
-
-    virtual void getValuesAt(size_t x, size_t y, float &real, float &imag) const;
-
-    virtual bool haveSetColumnAt(size_t x) const;
-
-    virtual void setColumnAt(size_t x, float *mags, float *phases, float factor);
-    virtual void setColumnAt(size_t x, float *reals, float *imags);
-
-    virtual void suspend() { m_mfc->suspend(); }
-
-protected:
-    char *m_writebuf;
-    mutable char *m_readbuf;
-    mutable size_t m_readbufCol;
-    mutable size_t m_readbufWidth;
-
-    float getFromReadBufStandard(size_t x, size_t y) const {
-        if (m_readbuf &&
-            (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
-            return ((float *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y];
-        } else {
-            populateReadBuf(x);
-            return getFromReadBufStandard(x, y);
-        }
-    }
-
-    float getFromReadBufCompactUnsigned(size_t x, size_t y) const {
-        if (m_readbuf &&
-            (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
-            return ((uint16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y];
-        } else {
-            populateReadBuf(x);
-            return getFromReadBufCompactUnsigned(x, y);
-        }
-    }
-
-    float getFromReadBufCompactSigned(size_t x, size_t y) const {
-        if (m_readbuf &&
-            (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
-            return ((int16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y];
-        } else {
-            populateReadBuf(x);
-            return getFromReadBufCompactSigned(x, y);
-        }
-    }
-
-    void populateReadBuf(size_t x) const {
-        if (!m_readbuf) {
-            m_readbuf = new char[m_mfc->getHeight() * 2 * m_mfc->getCellSize()];
-        }
-        m_mfc->getColumnAt(x, m_readbuf);
-        if (m_mfc->haveSetColumnAt(x + 1)) {
-            m_mfc->getColumnAt
-                (x + 1, m_readbuf + m_mfc->getCellSize() * m_mfc->getHeight());
-            m_readbufWidth = 2;
-        } else {
-            m_readbufWidth = 1;
-        }
-        m_readbufCol = x;
-    }
-
-    float getNormalizationFactor(size_t col) const {
-        if (m_storageType != Compact) {
-            return getFromReadBufStandard(col, m_mfc->getHeight() - 1);
-        } else {
-            float factor;
-            factor = getFromReadBufCompactUnsigned(col, m_mfc->getHeight() - 1);
-            return factor / 65535.0;
-        }
-    }
-
-    MatrixFile *m_mfc;
-    QMutex m_writeMutex;
-    StorageType m_storageType;
-};
-
-#endif