# HG changeset patch # User Chris Cannam # Date 1467705508 -3600 # Node ID c520f90bbf2e0391f609988bcbe9d2a9a88906d8 # Parent 6d990a24ac1b2561e6ddd0a6a52331a49b30e91c One FFT model per spectrogram (again!) - but we do still need a magnitude range per view, as views could be showing different regions diff -r 6d990a24ac1b -r c520f90bbf2e layer/SpectrogramLayer.cpp --- a/layer/SpectrogramLayer.cpp Sat Jul 02 12:56:07 2016 +0100 +++ b/layer/SpectrogramLayer.cpp Tue Jul 05 08:58:28 2016 +0100 @@ -79,8 +79,9 @@ m_synchronous(false), m_haveDetailedScale(false), m_exiting(false), - m_peakCacheDivisor(8), - m_sliceableModel(0) + m_fftModel(0), + m_peakCache(0), + m_peakCacheDivisor(8) { QString colourConfigName = "spectrogram-colour"; int colourConfigDefault = int(ColourMapper::Green); @@ -129,7 +130,7 @@ SpectrogramLayer::~SpectrogramLayer() { - invalidateFFTModels(); + invalidateFFTModel(); } void @@ -140,7 +141,7 @@ if (model == m_model) return; m_model = model; - invalidateFFTModels(); + invalidateFFTModel(); if (!m_model || !m_model->isOK()) return; @@ -607,7 +608,7 @@ invalidateImageCaches(); m_channel = ch; - invalidateFFTModels(); + invalidateFFTModel(); emit layerParametersChanged(); } @@ -651,7 +652,7 @@ m_windowSize = ws; - invalidateFFTModels(); + invalidateFFTModel(); emit layerParametersChanged(); } @@ -671,7 +672,7 @@ m_windowHopLevel = v; - invalidateFFTModels(); + invalidateFFTModel(); emit layerParametersChanged(); @@ -693,7 +694,7 @@ m_windowType = w; - invalidateFFTModels(); + invalidateFFTModel(); emit layerParametersChanged(); } @@ -913,27 +914,9 @@ m_imageCaches.erase(view->getId()); - if (m_fftModels.find(view->getId()) != m_fftModels.end()) { - - if (m_sliceableModel == m_fftModels[view->getId()]) { - bool replaced = false; - for (ViewFFTMap::iterator i = m_fftModels.begin(); - i != m_fftModels.end(); ++i) { - if (i->second != m_sliceableModel) { - emit sliceableModelReplaced(m_sliceableModel, i->second); - replaced = true; - break; - } - } - if (!replaced) emit sliceableModelReplaced(m_sliceableModel, 0); - } - - delete m_fftModels[view->getId()]; - m_fftModels.erase(view->getId()); - - delete m_peakCaches[view->getId()]; - m_peakCaches.erase(view->getId()); - } + //!!! in theory we should call invalidateFFTModel() if and + //!!! only if there are no remaining views in which we are not + //!!! dormant } else { @@ -1268,7 +1251,7 @@ return false; } - FFTModel *fft = getFFTModel(v); + FFTModel *fft = getFFTModel(); if (!fft) return false; double s0 = 0, s1 = 0; @@ -1349,7 +1332,7 @@ bool rv = false; - FFTModel *fft = getFFTModel(v); + FFTModel *fft = getFFTModel(); if (fft) { @@ -1390,115 +1373,81 @@ } FFTModel * -SpectrogramLayer::getFFTModel(const LayerGeometryProvider *v) const +SpectrogramLayer::getFFTModel() const { if (!m_model) return 0; int fftSize = getFFTSize(); - const View *view = v->getView(); + //!!! it is now surely slower to do this on every getFFTModel() + //!!! request than it would be to recreate the model immediately + //!!! when something changes instead of just invalidating it - if (m_fftModels.find(view->getId()) != m_fftModels.end()) { - if (m_fftModels[view->getId()] == 0) { -#ifdef DEBUG_SPECTROGRAM_REPAINT - cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found null model" << endl; -#endif - return 0; - } - if (m_fftModels[view->getId()]->getHeight() != fftSize / 2 + 1) { -#ifdef DEBUG_SPECTROGRAM_REPAINT - cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a model with the wrong height (" << m_fftModels[view->getId()]->getHeight() << ", wanted " << (fftSize / 2 + 1) << ")" << endl; -#endif - delete m_fftModels[view->getId()]; - m_fftModels.erase(view->getId()); - delete m_peakCaches[view->getId()]; - m_peakCaches.erase(view->getId()); - } else { -#ifdef DEBUG_SPECTROGRAM_REPAINT - cerr << "SpectrogramLayer::getFFTModel(" << v << "): Found a good model of height " << m_fftModels[view->getId()]->getHeight() << endl; -#endif - return m_fftModels[view->getId()]; - } + if (m_fftModel && + m_fftModel->getHeight() == fftSize / 2 + 1 && + m_fftModel->getWindowIncrement() == getWindowIncrement()) { + return m_fftModel; } - - if (m_fftModels.find(view->getId()) == m_fftModels.end()) { - - FFTModel *model = new FFTModel(m_model, - m_channel, - m_windowType, - m_windowSize, - getWindowIncrement(), - fftSize); - - if (!model->isOK()) { - QMessageBox::critical - (0, tr("FFT cache failed"), - tr("Failed to create the FFT model for this spectrogram.\n" - "There may be insufficient memory or disc space to continue.")); - delete model; - m_fftModels[view->getId()] = 0; - return 0; - } - - if (!m_sliceableModel) { -#ifdef DEBUG_SPECTROGRAM - cerr << "SpectrogramLayer: emitting sliceableModelReplaced(0, " << model << ")" << endl; -#endif - ((SpectrogramLayer *)this)->sliceableModelReplaced(0, model); - m_sliceableModel = model; - } - - m_fftModels[view->getId()] = model; + + delete m_peakCache; + m_peakCache = 0; + + delete m_fftModel; + m_fftModel = new FFTModel(m_model, + m_channel, + m_windowType, + m_windowSize, + getWindowIncrement(), + fftSize); + + if (!m_fftModel->isOK()) { + QMessageBox::critical + (0, tr("FFT cache failed"), + tr("Failed to create the FFT model for this spectrogram.\n" + "There may be insufficient memory or disc space to continue.")); + delete m_fftModel; + m_fftModel = 0; + return 0; } - return m_fftModels[view->getId()]; + ((SpectrogramLayer *)this)->sliceableModelReplaced(0, m_fftModel); + + return m_fftModel; } Dense3DModelPeakCache * -SpectrogramLayer::getPeakCache(const LayerGeometryProvider *v) const +SpectrogramLayer::getPeakCache() const { - const View *view = v->getView(); - if (!m_peakCaches[view->getId()]) { - FFTModel *f = getFFTModel(v); + //!!! see comment in getFFTModel + + if (!m_peakCache) { + FFTModel *f = getFFTModel(); if (!f) return 0; - m_peakCaches[view->getId()] = - new Dense3DModelPeakCache(f, m_peakCacheDivisor); + m_peakCache = new Dense3DModelPeakCache(f, m_peakCacheDivisor); } - return m_peakCaches[view->getId()]; + return m_peakCache; } const Model * SpectrogramLayer::getSliceableModel() const { - if (m_sliceableModel) return m_sliceableModel; - if (m_fftModels.empty()) return 0; - m_sliceableModel = m_fftModels.begin()->second; - return m_sliceableModel; + return m_fftModel; } void -SpectrogramLayer::invalidateFFTModels() +SpectrogramLayer::invalidateFFTModel() { #ifdef DEBUG_SPECTROGRAM - cerr << "SpectrogramLayer::invalidateFFTModels called" << endl; + cerr << "SpectrogramLayer::invalidateFFTModel called" << endl; #endif - for (ViewFFTMap::iterator i = m_fftModels.begin(); - i != m_fftModels.end(); ++i) { - delete i->second; - } - for (PeakCacheMap::iterator i = m_peakCaches.begin(); - i != m_peakCaches.end(); ++i) { - delete i->second; - } - - m_fftModels.clear(); - m_peakCaches.clear(); - - if (m_sliceableModel) { - cerr << "SpectrogramLayer: emitting sliceableModelReplaced(" << m_sliceableModel << ", 0)" << endl; - emit sliceableModelReplaced(m_sliceableModel, 0); - m_sliceableModel = 0; - } + + emit sliceableModelReplaced(m_fftModel, 0); + + delete m_fftModel; + delete m_peakCache; + + m_fftModel = 0; + m_peakCache = 0; } void @@ -2144,7 +2093,7 @@ if (minbin < 0) minbin = 0; if (maxbin < 0) maxbin = minbin+1; - FFTModel *fft = getFFTModel(v); + FFTModel *fft = getFFTModel(); if (!fft) return 0; FFTModel::PeakSet peakfreqs; @@ -2369,11 +2318,11 @@ int divisor = 1; if (usePeaksCache) { - peakCacheModel = getPeakCache(v); + peakCacheModel = getPeakCache(); divisor = m_peakCacheDivisor; sourceModel = peakCacheModel; } else { - fftModel = getFFTModel(v); + fftModel = getFFTModel(); sourceModel = fftModel; } @@ -2598,11 +2547,8 @@ int SpectrogramLayer::getCompletion(LayerGeometryProvider *v) const { - const View *view = v->getView(); - - if (m_fftModels.find(view->getId()) == m_fftModels.end()) return 100; - - int completion = m_fftModels[view->getId()]->getCompletion(); + if (!m_fftModel) return 100; + int completion = m_fftModel->getCompletion(); #ifdef DEBUG_SPECTROGRAM_REPAINT cerr << "SpectrogramLayer::getCompletion: completion = " << completion << endl; #endif @@ -2613,8 +2559,8 @@ SpectrogramLayer::getError(LayerGeometryProvider *v) const { const View *view = v->getView(); - if (m_fftModels.find(view->getId()) == m_fftModels.end()) return ""; - return m_fftModels[view->getId()]->getError(); + if (!m_fftModel) return ""; + return m_fftModel->getError(); } bool diff -r 6d990a24ac1b -r c520f90bbf2e layer/SpectrogramLayer.h --- a/layer/SpectrogramLayer.h Sat Jul 02 12:56:07 2016 +0100 +++ b/layer/SpectrogramLayer.h Tue Jul 05 08:58:28 2016 +0100 @@ -339,17 +339,10 @@ int getFFTOversampling() const; int getFFTSize() const; // m_windowSize * getFFTOversampling() - - FFTModel *getFFTModel(const LayerGeometryProvider *v) const; - Dense3DModelPeakCache *getPeakCache(const LayerGeometryProvider *v) const; - void invalidateFFTModels(); - typedef std::map ViewFFTMap; // key is view id - typedef std::map PeakCacheMap; // key is view id - mutable ViewFFTMap m_fftModels; - mutable PeakCacheMap m_peakCaches; + mutable FFTModel *m_fftModel; //!!! should not be mutable, see getFFTModel() + mutable Dense3DModelPeakCache *m_peakCache; const int m_peakCacheDivisor; - mutable Model *m_sliceableModel; typedef std::map ViewMagMap; // key is view id mutable ViewMagMap m_viewMags; @@ -357,6 +350,10 @@ void invalidateMagnitudes(); bool updateViewMagnitudes(LayerGeometryProvider *v) const; + FFTModel *getFFTModel() const; + Dense3DModelPeakCache *getPeakCache() const; + void invalidateFFTModel(); + int paintDrawBuffer(LayerGeometryProvider *v, int w, int h, const std::vector &binforx, const std::vector &binfory,