comparison 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
comparison
equal deleted inserted replaced
32:c53b949ef142 33:651e4e868bcc
47 m_pixmapCache(0), 47 m_pixmapCache(0),
48 m_pixmapCacheInvalid(true), 48 m_pixmapCacheInvalid(true),
49 m_fillThread(0), 49 m_fillThread(0),
50 m_updateTimer(0), 50 m_updateTimer(0),
51 m_lastFillExtent(0), 51 m_lastFillExtent(0),
52 m_dormant(false),
53 m_exiting(false) 52 m_exiting(false)
54 { 53 {
55 if (config == MelodicRange) { 54 if (config == MelodicRange) {
56 setWindowSize(8192); 55 setWindowSize(8192);
57 setWindowOverlap(90); 56 setWindowOverlap(90);
595 { 594 {
596 return m_frequencyScale; 595 return m_frequencyScale;
597 } 596 }
598 597
599 void 598 void
600 SpectrogramLayer::setLayerDormant() 599 SpectrogramLayer::setLayerDormant(bool dormant)
601 { 600 {
602 m_mutex.lock(); 601 if (dormant == m_dormant) return;
603 m_dormant = true; 602
604 delete m_cache; 603 if (dormant) {
605 m_cache = 0; 604
606 m_pixmapCacheInvalid = true; 605 m_mutex.lock();
607 delete m_pixmapCache; 606 m_dormant = true;
608 m_pixmapCache = 0; 607
609 m_mutex.unlock(); 608 delete m_cache;
609 m_cache = 0;
610
611 m_pixmapCacheInvalid = true;
612 delete m_pixmapCache;
613 m_pixmapCache = 0;
614
615 m_mutex.unlock();
616
617 } else {
618
619 m_dormant = false;
620 fillCache();
621 }
610 } 622 }
611 623
612 void 624 void
613 SpectrogramLayer::cacheInvalid() 625 SpectrogramLayer::cacheInvalid()
614 { 626 {
981 size_t width = (end - start) / windowIncrement + 1; 993 size_t width = (end - start) / windowIncrement + 1;
982 size_t height = windowSize / 2; 994 size_t height = windowSize / 2;
983 m_layer.m_cache = new Cache(width, height); 995 m_layer.m_cache = new Cache(width, height);
984 996
985 m_layer.setCacheColourmap(); 997 m_layer.setCacheColourmap();
986
987 m_layer.m_cache->fill(0); 998 m_layer.m_cache->fill(0);
999
1000 // We don't need a lock when writing to or reading from
1001 // the pixels in the cache, because it's a fixed size
1002 // array. We do need to ensure we have the width and
1003 // height of the cache and the FFT parameters fixed before
1004 // we unlock, in case they change in the model while we
1005 // aren't holding a lock. It's safe for us to continue to
1006 // use the "old" values if that happens, because they will
1007 // continue to match the dimensions of the actual cache
1008 // (which we manage, not the model).
988 m_layer.m_mutex.unlock(); 1009 m_layer.m_mutex.unlock();
989 1010
990 double *input = (double *) 1011 double *input = (double *)
991 fftw_malloc(windowSize * sizeof(double)); 1012 fftw_malloc(windowSize * sizeof(double));
992 1013
1000 1021
1001 if (!plan) { 1022 if (!plan) {
1002 std::cerr << "WARNING: fftw_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl; 1023 std::cerr << "WARNING: fftw_plan_dft_r2c_1d(" << windowSize << ") failed!" << std::endl;
1003 fftw_free(input); 1024 fftw_free(input);
1004 fftw_free(output); 1025 fftw_free(output);
1005 m_layer.m_mutex.lock();
1006 continue; 1026 continue;
1007 } 1027 }
1008 1028
1009 int counter = 0; 1029 int counter = 0;
1010 int updateAt = (end / windowIncrement) / 20; 1030 int updateAt = (end / windowIncrement) / 20;
1011 if (updateAt < 100) updateAt = 100; 1031 if (updateAt < 100) updateAt = 100;
1012 1032
1013 bool doVisibleFirst = (visibleStart != start && visibleEnd != end); 1033 bool doVisibleFirst = (visibleStart != start && visibleEnd != end);
1014 1034
1015 if (doVisibleFirst) { 1035 if (doVisibleFirst) {
1016
1017 m_layer.m_mutex.lock();
1018 1036
1019 for (size_t f = visibleStart; f < visibleEnd; f += windowIncrement) { 1037 for (size_t f = visibleStart; f < visibleEnd; f += windowIncrement) {
1020 1038
1021 m_layer.fillCacheColumn(int((f - start) / windowIncrement), 1039 m_layer.fillCacheColumn(int((f - start) / windowIncrement),
1022 input, output, plan, 1040 input, output, plan,
1023 windowSize, windowIncrement, 1041 windowSize, windowIncrement,
1024 windower, false); 1042 windower, false);
1025
1026 m_layer.m_mutex.unlock();
1027 m_layer.m_mutex.lock();
1028 1043
1029 if (m_layer.m_cacheInvalid || m_layer.m_exiting) { 1044 if (m_layer.m_cacheInvalid || m_layer.m_exiting) {
1030 interrupted = true; 1045 interrupted = true;
1031 m_fillExtent = 0; 1046 m_fillExtent = 0;
1032 break; 1047 break;
1037 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) / 1052 m_fillCompletion = size_t(100 * fabsf(float(f - visibleStart) /
1038 float(end - start))); 1053 float(end - start)));
1039 counter = 0; 1054 counter = 0;
1040 } 1055 }
1041 } 1056 }
1042
1043 m_layer.m_mutex.unlock();
1044 } 1057 }
1045 1058
1046 m_layer.m_cachedInitialVisibleArea = true; 1059 m_layer.m_cachedInitialVisibleArea = true;
1047 1060
1048 if (!interrupted && doVisibleFirst) { 1061 if (!interrupted && doVisibleFirst) {
1288 if (!m_model || !m_model->isOK() || !m_model->isReady()) { 1301 if (!m_model || !m_model->isOK() || !m_model->isReady()) {
1289 return; 1302 return;
1290 } 1303 }
1291 1304
1292 if (m_dormant) { 1305 if (m_dormant) {
1293 std::cerr << "SpectrogramLayer::paint(): Layer is dormant, de-hibernating" << std::endl; 1306 std::cerr << "SpectrogramLayer::paint(): Layer is dormant" << std::endl;
1294 m_dormant = false;
1295 ((SpectrogramLayer *)this)->fillCache();
1296 return; 1307 return;
1297 } 1308 }
1298 1309
1299 #ifdef DEBUG_SPECTROGRAM_REPAINT 1310 #ifdef DEBUG_SPECTROGRAM_REPAINT
1300 std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl; 1311 std::cerr << "SpectrogramLayer::paint(): About to lock" << std::endl;