| Chris@152 | 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */ | 
| Chris@152 | 2 | 
| Chris@152 | 3 /* | 
| Chris@152 | 4     Sonic Visualiser | 
| Chris@152 | 5     An audio file viewer and annotation editor. | 
| Chris@152 | 6     Centre for Digital Music, Queen Mary, University of London. | 
| Chris@152 | 7     This file copyright 2006 Chris Cannam. | 
| Chris@152 | 8 | 
| Chris@152 | 9     This program is free software; you can redistribute it and/or | 
| Chris@152 | 10     modify it under the terms of the GNU General Public License as | 
| Chris@152 | 11     published by the Free Software Foundation; either version 2 of the | 
| Chris@152 | 12     License, or (at your option) any later version.  See the file | 
| Chris@152 | 13     COPYING included with this distribution for more information. | 
| Chris@152 | 14 */ | 
| Chris@152 | 15 | 
| Chris@152 | 16 #include "FFTCache.h" | 
| Chris@152 | 17 #include "system/System.h" | 
| Chris@152 | 18 | 
| Chris@152 | 19 #include <iostream> | 
| Chris@152 | 20 | 
| Chris@152 | 21 //!!! This class is a work in progress -- it does only as much as we | 
| Chris@152 | 22 // need for the current SpectrogramLayer.  Slated for substantial | 
| Chris@152 | 23 // refactoring and extension. | 
| Chris@152 | 24 | 
| Chris@152 | 25 FFTMemoryCache::FFTMemoryCache() : | 
| Chris@152 | 26     m_width(0), | 
| Chris@152 | 27     m_height(0), | 
| Chris@152 | 28     m_magnitude(0), | 
| Chris@152 | 29     m_phase(0), | 
| Chris@152 | 30     m_factor(0) | 
| Chris@152 | 31 { | 
| Chris@152 | 32 } | 
| Chris@152 | 33 | 
| Chris@152 | 34 FFTMemoryCache::~FFTMemoryCache() | 
| Chris@152 | 35 { | 
| Chris@152 | 36     std::cerr << "FFTMemoryCache[" << this << "]::~Cache" << std::endl; | 
| Chris@152 | 37 | 
| Chris@152 | 38     for (size_t i = 0; i < m_width; ++i) { | 
| Chris@152 | 39 	if (m_magnitude && m_magnitude[i]) free(m_magnitude[i]); | 
| Chris@152 | 40 	if (m_phase && m_phase[i]) free(m_phase[i]); | 
| Chris@152 | 41     } | 
| Chris@152 | 42 | 
| Chris@152 | 43     if (m_magnitude) free(m_magnitude); | 
| Chris@152 | 44     if (m_phase) free(m_phase); | 
| Chris@152 | 45     if (m_factor) free(m_factor); | 
| Chris@152 | 46 } | 
| Chris@152 | 47 | 
| Chris@152 | 48 void | 
| Chris@152 | 49 FFTMemoryCache::resize(size_t width, size_t height) | 
| Chris@152 | 50 { | 
| Chris@152 | 51     std::cerr << "FFTMemoryCache[" << this << "]::resize(" << width << "x" << height << " = " << width*height << ")" << std::endl; | 
| Chris@152 | 52 | 
| Chris@152 | 53     if (m_width == width && m_height == height) return; | 
| Chris@152 | 54 | 
| Chris@152 | 55     resize(m_magnitude, width, height); | 
| Chris@152 | 56     resize(m_phase, width, height); | 
| Chris@152 | 57 | 
| Chris@152 | 58     m_factor = (float *)realloc(m_factor, width * sizeof(float)); | 
| Chris@152 | 59 | 
| Chris@152 | 60     m_width = width; | 
| Chris@152 | 61     m_height = height; | 
| Chris@152 | 62 | 
| Chris@152 | 63     std::cerr << "done, width = " << m_width << " height = " << m_height << std::endl; | 
| Chris@152 | 64 } | 
| Chris@152 | 65 | 
| Chris@152 | 66 void | 
| Chris@152 | 67 FFTMemoryCache::resize(uint16_t **&array, size_t width, size_t height) | 
| Chris@152 | 68 { | 
| Chris@152 | 69     for (size_t i = width; i < m_width; ++i) { | 
| Chris@152 | 70 	free(array[i]); | 
| Chris@152 | 71     } | 
| Chris@152 | 72 | 
| Chris@152 | 73     if (width != m_width) { | 
| Chris@152 | 74 	array = (uint16_t **)realloc(array, width * sizeof(uint16_t *)); | 
| Chris@152 | 75 	if (!array) throw std::bad_alloc(); | 
| Chris@152 | 76 	MUNLOCK(array, width * sizeof(uint16_t *)); | 
| Chris@152 | 77     } | 
| Chris@152 | 78 | 
| Chris@152 | 79     for (size_t i = m_width; i < width; ++i) { | 
| Chris@152 | 80 	array[i] = 0; | 
| Chris@152 | 81     } | 
| Chris@152 | 82 | 
| Chris@152 | 83     for (size_t i = 0; i < width; ++i) { | 
| Chris@152 | 84 	array[i] = (uint16_t *)realloc(array[i], height * sizeof(uint16_t)); | 
| Chris@152 | 85 	if (!array[i]) throw std::bad_alloc(); | 
| Chris@152 | 86 	MUNLOCK(array[i], height * sizeof(uint16_t)); | 
| Chris@152 | 87     } | 
| Chris@152 | 88 } | 
| Chris@152 | 89 | 
| Chris@152 | 90 void | 
| Chris@152 | 91 FFTMemoryCache::reset() | 
| Chris@152 | 92 { | 
| Chris@152 | 93     for (size_t x = 0; x < m_width; ++x) { | 
| Chris@152 | 94 	for (size_t y = 0; y < m_height; ++y) { | 
| Chris@152 | 95 	    m_magnitude[x][y] = 0; | 
| Chris@152 | 96 	    m_phase[x][y] = 0; | 
| Chris@152 | 97 	} | 
| Chris@152 | 98 	m_factor[x] = 1.0; | 
| Chris@152 | 99     } | 
| Chris@152 | 100 } | 
| Chris@152 | 101 | 
| Chris@152 | 102 void | 
| Chris@152 | 103 FFTMemoryCache::setColumnAt(size_t x, float *reals, float *imags) | 
| Chris@152 | 104 { | 
| Chris@152 | 105     float max = 0.0; | 
| Chris@152 | 106 | 
| Chris@152 | 107     for (size_t y = 0; y < m_height; ++y) { | 
| Chris@152 | 108         float mag = sqrtf(reals[y] * reals[y] + imags[y] * imags[y]); | 
| Chris@152 | 109         float phase = atan2f(imags[y], reals[y]); | 
| Chris@152 | 110         phase = princargf(phase); | 
| Chris@152 | 111         reals[y] = mag; | 
| Chris@152 | 112         imags[y] = phase; | 
| Chris@152 | 113         if (mag > max) max = mag; | 
| Chris@152 | 114     } | 
| Chris@152 | 115 | 
| Chris@152 | 116     setColumnAt(x, reals, imags, max); | 
| Chris@152 | 117 } | 
| Chris@152 | 118 |