comparison data/fft/FFTDataServer.cpp @ 264:260032c26c4f

* don't store fft values scaled by fftsize/2; that's a special requirement for the spectrogram, and other applications will not expect it -- make the spectrogram do that scaling itself * add a higher-resolution memory cache (still polar, though) as an alternative to the 16-bit compact cache * don't use the memory cache if we want rectangular coords (unless the disc cache is totally infeasible) as conversion slows it down anyway * avoid redundant rectangular -> polar -> rectangular conversion when storing values in a rectangular-mode disc cache
author Chris Cannam
date Fri, 01 Jun 2007 13:56:35 +0000
parents dc46851837d6
children 8bbc9e336475
comparison
equal deleted inserted replaced
263:71dfc6ab3b54 264:260032c26c4f
532 // and "feature extraction" criteria for rectangular ones. 532 // and "feature extraction" criteria for rectangular ones.
533 533
534 StorageAdviser::Criteria criteria; 534 StorageAdviser::Criteria criteria;
535 if (m_polar) { 535 if (m_polar) {
536 criteria = StorageAdviser::Criteria 536 criteria = StorageAdviser::Criteria
537 (StorageAdviser::SpeedCritical | StorageAdviser::LongRetentionLikely); 537 (StorageAdviser::SpeedCritical |
538 StorageAdviser::LongRetentionLikely);
538 } else { 539 } else {
539 criteria = StorageAdviser::Criteria(StorageAdviser::PrecisionCritical); 540 criteria = StorageAdviser::Criteria
541 (StorageAdviser::PrecisionCritical);
540 } 542 }
541 543
542 int cells = m_width * m_height; 544 int cells = m_width * m_height;
543 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb 545 int minimumSize = (cells / 1024) * sizeof(uint16_t); // kb
544 int maximumSize = (cells / 1024) * sizeof(float); // kb 546 int maximumSize = (cells / 1024) * sizeof(float); // kb
564 566
565 recommendation = 567 recommendation =
566 StorageAdviser::recommend(criteria, minimumSize, maximumSize); 568 StorageAdviser::recommend(criteria, minimumSize, maximumSize);
567 } 569 }
568 570
569 // std::cerr << "Recommendation was: " << recommendation << std::endl; 571 std::cerr << "Recommendation was: " << recommendation << std::endl;
570 572
571 m_memoryCache = ((recommendation & StorageAdviser::UseMemory) || 573 m_memoryCache = false;
572 (recommendation & StorageAdviser::PreferMemory)); 574
575 if (recommendation & StorageAdviser::UseMemory) {
576
577 // can't use disc, must use memory
578
579 m_memoryCache = true;
580
581 } else if (recommendation & StorageAdviser::PreferMemory) {
582
583 // if memory is recommended, we use it if we're using polar
584 // coordinates; but we don't have a native rectangular memory
585 // cache, so we might as well use disc if we want rectangular
586 // coordinates rather than have all the bother of converting
587 // every time
588
589 if (m_polar) m_memoryCache = true;
590 }
573 591
574 m_compactCache = (recommendation & StorageAdviser::ConserveSpace); 592 m_compactCache = (recommendation & StorageAdviser::ConserveSpace);
575 593
576 #ifdef DEBUG_FFT_SERVER 594 #ifdef DEBUG_FFT_SERVER
577 std::cerr << "Width " << m_width << ", cache width " << m_cacheWidth << " (size " << m_cacheWidth * columnSize << ")" << std::endl; 595 std::cerr << "Width " << m_width << ", cache width " << m_cacheWidth << " (size " << m_cacheWidth * columnSize << ")" << std::endl;
761 if (c * m_cacheWidth + width > m_width) { 779 if (c * m_cacheWidth + width > m_width) {
762 width = m_width - c * m_cacheWidth; 780 width = m_width - c * m_cacheWidth;
763 } 781 }
764 782
765 try { 783 try {
766 784
767 if (m_memoryCache) { 785 if (m_memoryCache) {
768 786
769 cache = new FFTMemoryCache(); 787 cache = new FFTMemoryCache
788 (m_compactCache ? FFTMemoryCache::Compact :
789 FFTMemoryCache::Polar);
770 790
771 } else if (m_compactCache) { 791 } else if (m_compactCache) {
772 792
773 cache = new FFTFileCache(name, MatrixFile::ReadWrite, 793 cache = new FFTFileCache
774 FFTFileCache::Compact); 794 (name,
795 MatrixFile::ReadWrite,
796 FFTFileCache::Compact);
775 797
776 } else { 798 } else {
777 799
778 cache = new FFTFileCache(name, MatrixFile::ReadWrite, 800 cache = new FFTFileCache
779 m_polar ? FFTFileCache::Polar : 801 (name,
780 FFTFileCache::Rectangular); 802 MatrixFile::ReadWrite,
803 m_polar ? FFTFileCache::Polar :
804 FFTFileCache::Rectangular);
781 } 805 }
782 806
783 cache->resize(width, m_height); 807 cache->resize(width, m_height);
784 cache->reset(); 808 cache->reset();
785 809
930 #ifdef DEBUG_FFT_SERVER 954 #ifdef DEBUG_FFT_SERVER
931 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl; 955 std::cerr << "FFTDataServer::getValuesAt(" << x << ", " << y << "): filling" << std::endl;
932 #endif 956 #endif
933 fillColumn(x); 957 fillColumn(x);
934 } 958 }
935 float magnitude = cache->getMagnitudeAt(col, y); 959
936 float phase = cache->getPhaseAt(col, y); 960 cache->getValuesAt(col, y, real, imaginary);
937 real = magnitude * cosf(phase);
938 imaginary = magnitude * sinf(phase);
939 } 961 }
940 962
941 bool 963 bool
942 FFTDataServer::isColumnReady(size_t x) 964 FFTDataServer::isColumnReady(size_t x)
943 { 965 {
1053 1075
1054 fftsample factor = 0.0; 1076 fftsample factor = 0.0;
1055 1077
1056 for (size_t i = 0; i <= m_fftSize/2; ++i) { 1078 for (size_t i = 0; i <= m_fftSize/2; ++i) {
1057 1079
1058 fftsample mag = sqrtf(m_fftOutput[i][0] * m_fftOutput[i][0] + 1080 m_workbuffer[i] = m_fftOutput[i][0];
1059 m_fftOutput[i][1] * m_fftOutput[i][1]); 1081 m_workbuffer[i + m_fftSize/2 + 1] = m_fftOutput[i][1];
1060 mag /= m_windowSize / 2;
1061
1062 if (mag > factor) factor = mag;
1063
1064 fftsample phase = atan2f(m_fftOutput[i][1], m_fftOutput[i][0]);
1065 phase = princargf(phase);
1066
1067 m_workbuffer[i] = mag;
1068 m_workbuffer[i + m_fftSize/2+1] = phase;
1069 } 1082 }
1070 1083
1071 cache->setColumnAt(col, 1084 cache->setColumnAt(col,
1072 m_workbuffer, 1085 m_workbuffer,
1073 m_workbuffer + m_fftSize/2+1, 1086 m_workbuffer + m_fftSize/2+1);
1074 factor);
1075 1087
1076 if (m_suspended) { 1088 if (m_suspended) {
1077 // std::cerr << "FFTDataServer::fillColumn(" << x << "): calling resume" << std::endl; 1089 // std::cerr << "FFTDataServer::fillColumn(" << x << "): calling resume" << std::endl;
1078 // resume(); 1090 // resume();
1079 } 1091 }