diff layer/SpectrogramLayer.cpp @ 33:651e4e868bcc

* Implement play mute, level and pan controls and a layer visibility control * Handle swapping the buffers in AudioCallbackPlaySource more gracefully, so that in many cases it can be done inaudibly. Still gets it wrong when playing in a noncontiguous selection. * Fix to SV file save for non-2d sparse models * Fixes to LED button drawing and AudioDial mouse functionality * Add progress bar for Ogg file import * Reshuffle PropertyContainer and its subclasses so it can be a QObject * Add layer dormancy (invisible layer permitted to free its cache space) * Optimisations to SpectrogramLayer, removing locks when reading/writing individual pixels in the cache (should be unnecessary there) -- there's still an issue here as we need a lock when reading from the model in case the model is replaced, and we don't currently have one * Several munlock() calls to make it harder to exhaust real memory if running in an RT mode with mlockall() active
author Chris Cannam
date Fri, 17 Feb 2006 18:04:26 +0000
parents fc802f7b112e
children c43f2c4f66f2
line wrap: on
line diff
--- a/layer/SpectrogramLayer.cpp	Wed Feb 15 17:58:35 2006 +0000
+++ b/layer/SpectrogramLayer.cpp	Fri Feb 17 18:04:26 2006 +0000
@@ -49,7 +49,6 @@
     m_fillThread(0),
     m_updateTimer(0),
     m_lastFillExtent(0),
-    m_dormant(false),
     m_exiting(false)
 {
     if (config == MelodicRange) {
@@ -597,16 +596,29 @@
 }
 
 void
-SpectrogramLayer::setLayerDormant()
+SpectrogramLayer::setLayerDormant(bool dormant)
 {
-    m_mutex.lock();
-    m_dormant = true;
-    delete m_cache;
-    m_cache = 0;
-    m_pixmapCacheInvalid = true;
-    delete m_pixmapCache;
-    m_pixmapCache = 0;
-    m_mutex.unlock();
+    if (dormant == m_dormant) return;
+
+    if (dormant) {
+
+	m_mutex.lock();
+	m_dormant = true;
+
+	delete m_cache;
+	m_cache = 0;
+	
+	m_pixmapCacheInvalid = true;
+	delete m_pixmapCache;
+	m_pixmapCache = 0;
+	
+	m_mutex.unlock();
+
+    } else {
+
+	m_dormant = false;
+	fillCache();
+    }
 }
 
 void
@@ -983,8 +995,17 @@
 	    m_layer.m_cache = new Cache(width, height);
 
 	    m_layer.setCacheColourmap();
+	    m_layer.m_cache->fill(0);
 
-	    m_layer.m_cache->fill(0);
+	    // We don't need a lock when writing to or reading from
+	    // the pixels in the cache, because it's a fixed size
+	    // array.  We do need to ensure we have the width and
+	    // height of the cache and the FFT parameters fixed before
+	    // we unlock, in case they change in the model while we
+	    // aren't holding a lock.  It's safe for us to continue to
+	    // use the "old" values if that happens, because they will
+	    // continue to match the dimensions of the actual cache
+	    // (which we manage, not the model).
 	    m_layer.m_mutex.unlock();
 
 	    double *input = (double *)
@@ -1002,7 +1023,6 @@
 		std::cerr << "WARNING: fftw_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl;
 		fftw_free(input);
 		fftw_free(output);
-		m_layer.m_mutex.lock();
 		continue;
 	    }
 
@@ -1014,8 +1034,6 @@
 
 	    if (doVisibleFirst) {
 
-		m_layer.m_mutex.lock();
-
 		for (size_t f = visibleStart; f < visibleEnd; f += windowIncrement) {
 	    
 		    m_layer.fillCacheColumn(int((f - start) / windowIncrement),
@@ -1023,9 +1041,6 @@
 					    windowSize, windowIncrement,
 					    windower, false);
 
-		    m_layer.m_mutex.unlock();
-		    m_layer.m_mutex.lock();
-
 		    if (m_layer.m_cacheInvalid || m_layer.m_exiting) {
 			interrupted = true;
 			m_fillExtent = 0;
@@ -1039,8 +1054,6 @@
 			counter = 0;
 		    }
 		}
-
-		m_layer.m_mutex.unlock();
 	    }
 
 	    m_layer.m_cachedInitialVisibleArea = true;
@@ -1290,9 +1303,7 @@
     }
 
     if (m_dormant) {
-	std::cerr << "SpectrogramLayer::paint(): Layer is dormant, de-hibernating" << std::endl;
-	m_dormant = false;
-	((SpectrogramLayer *)this)->fillCache();
+	std::cerr << "SpectrogramLayer::paint(): Layer is dormant" << std::endl;
 	return;
     }