Chris@537: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
Chris@537: 
Chris@537: /*
Chris@537:     Sonic Visualiser
Chris@537:     An audio file viewer and annotation editor.
Chris@537:     Centre for Digital Music, Queen Mary, University of London.
Chris@537:     This file copyright 2006-2009 Chris Cannam and QMUL.
Chris@537:     
Chris@537:     This program is free software; you can redistribute it and/or
Chris@537:     modify it under the terms of the GNU General Public License as
Chris@537:     published by the Free Software Foundation; either version 2 of the
Chris@537:     License, or (at your option) any later version.  See the file
Chris@537:     COPYING included with this distribution for more information.
Chris@537: */
Chris@537: 
Chris@537: #ifndef _FFT_FILE_CACHE_READER_H_
Chris@537: #define _FFT_FILE_CACHE_READER_H_
Chris@537: 
Chris@537: #include "data/fileio/MatrixFile.h"
Chris@537: #include "FFTCacheReader.h"
Chris@537: #include "FFTCacheStorageType.h"
Chris@537: 
Chris@537: class FFTFileCacheWriter;
Chris@537: 
Chris@537: class FFTFileCacheReader : public FFTCacheReader
Chris@537: {
Chris@537: public:
Chris@537:     FFTFileCacheReader(FFTFileCacheWriter *);
Chris@537:     ~FFTFileCacheReader();
Chris@537: 
Chris@537:     size_t getWidth() const;
Chris@537:     size_t getHeight() const;
Chris@537: 	
Chris@537:     float getMagnitudeAt(size_t x, size_t y) const;
Chris@537:     float getNormalizedMagnitudeAt(size_t x, size_t y) const;
Chris@537:     float getMaximumMagnitudeAt(size_t x) const;
Chris@537:     float getPhaseAt(size_t x, size_t y) const;
Chris@537: 
Chris@537:     void getValuesAt(size_t x, size_t y, float &real, float &imag) const;
Chris@537:     void getMagnitudesAt(size_t x, float *values, size_t minbin, size_t count, size_t step) const;
Chris@537: 
Chris@537:     bool haveSetColumnAt(size_t x) const;
Chris@537: 
Chris@537:     static size_t getCacheSize(size_t width, size_t height,
Chris@537:                                FFTCache::StorageType type);
Chris@537: 
Chris@537:     FFTCache::StorageType getStorageType() const { return m_storageType; }
Chris@537: 
Chris@537: protected:
Chris@537:     mutable char *m_readbuf;
Chris@537:     mutable size_t m_readbufCol;
Chris@537:     mutable size_t m_readbufWidth;
Chris@555:     mutable bool m_readbufGood;
Chris@537: 
Chris@537:     float getFromReadBufStandard(size_t x, size_t y) const {
Chris@537:         float v;
Chris@537:         if (m_readbuf &&
Chris@537:             (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
Chris@537:             v = ((float *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y];
Chris@537:             return v;
Chris@537:         } else {
Chris@537:             populateReadBuf(x);
Chris@537:             v = getFromReadBufStandard(x, y);
Chris@537:             return v;
Chris@537:         }
Chris@537:     }
Chris@537: 
Chris@537:     float getFromReadBufCompactUnsigned(size_t x, size_t y) const {
Chris@537:         float v;
Chris@537:         if (m_readbuf &&
Chris@537:             (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
Chris@537:             v = ((uint16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y];
Chris@537:             return v;
Chris@537:         } else {
Chris@537:             populateReadBuf(x);
Chris@537:             v = getFromReadBufCompactUnsigned(x, y);
Chris@537:             return v;
Chris@537:         }
Chris@537:     }
Chris@537: 
Chris@537:     float getFromReadBufCompactSigned(size_t x, size_t y) const {
Chris@537:         float v;
Chris@537:         if (m_readbuf &&
Chris@537:             (m_readbufCol == x || (m_readbufWidth > 1 && m_readbufCol+1 == x))) {
Chris@537:             v = ((int16_t *)m_readbuf)[(x - m_readbufCol) * m_mfc->getHeight() + y];
Chris@537:             return v;
Chris@537:         } else {
Chris@537:             populateReadBuf(x);
Chris@537:             v = getFromReadBufCompactSigned(x, y);
Chris@537:             return v;
Chris@537:         }
Chris@537:     }
Chris@537: 
Chris@537:     void populateReadBuf(size_t x) const;
Chris@537: 
Chris@537:     float getNormalizationFactor(size_t col) const {
Chris@537:         size_t h = m_mfc->getHeight();
Chris@537:         if (h < m_factorSize) return 0;
Chris@537:         if (m_storageType != FFTCache::Compact) {
Chris@537:             return getFromReadBufStandard(col, h - 1);
Chris@537:         } else {
Chris@537:             union {
Chris@537:                 float f;
Chris@537:                 uint16_t u[2];
Chris@537:             } factor;
Chris@537:             if (!m_readbuf ||
Chris@537:                 !(m_readbufCol == col ||
Chris@537:                   (m_readbufWidth > 1 && m_readbufCol+1 == col))) {
Chris@537:                 populateReadBuf(col);
Chris@537:             }
Chris@537:             size_t ix = (col - m_readbufCol) * m_mfc->getHeight() + h;
Chris@537:             factor.u[0] = ((uint16_t *)m_readbuf)[ix - 2];
Chris@537:             factor.u[1] = ((uint16_t *)m_readbuf)[ix - 1];
Chris@537:             return factor.f;
Chris@537:         }
Chris@537:     }
Chris@537:  
Chris@537:     FFTCache::StorageType m_storageType;
Chris@537:     size_t m_factorSize;
Chris@537:     MatrixFile *m_mfc;
Chris@537: };
Chris@537: 
Chris@537: #endif