Mercurial > hg > svcore
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 } |