void FrequencyPlot::update(int w, int h) { m_image.load(w, h, 1); m_rect = {10, 10, (w | 1) - 40, (h | 1) - 20}; m_width_rcp = 1.0f / float(m_rect.width()); fill(&m_image, Color(0)); for(int x=0; x<m_rect.width(); x++) { if(!(x & 1)) { int xx = x + m_rect.x(); m_image(xx, m_rect.y())[0] = m_image(xx, m_rect.bottom() - 1)[0] = 255; } } float maxfreqlog = log10(maxFreq()); m_min_freq_log = log10(minFreq()); m_freq_range_log = maxfreqlog - m_min_freq_log; m_freq_range_log_rcp = 1.0f / m_freq_range_log; int n = 1; float f = 1.0f; float df = 1.0f; for(;;) { if(f >= minFreq()) { if(f >= maxFreq()) break; int x = (log10(f) - m_min_freq_log) * m_freq_range_log_rcp * m_rect.width(); paintLineAt(x + m_rect.x(), n == 1 ? 127 : 63); } n++; f += df; if(n == 10) { n = 1; df *= 10; } } paintLineAt(m_rect.x(), 255); paintLineAt(m_rect.right()-1, 255); }
bool FFTFeatures::computeFeatures(const VectorFloat &inputVector){ if( !initialized ){ errorLog << "computeFeatures(const VectorFloat &inputVector) - Not initialized!" << std::endl; return false; } //The input vector should be the magnitude data from an FFT if( inputVector.getSize() != fftWindowSize*numChannelsInFFTSignal ){ errorLog << "computeFeatures(const VectorFloat &inputVector) - The size of the inputVector (" << inputVector.getSize() << ") does not match the expected size! Verify that the FFT module that generated this inputVector has a window size of " << fftWindowSize << " and the number of input channels is: " << numChannelsInFFTSignal << ". Also verify that only the magnitude values are being computed (and not the phase)." << std::endl; return false; } featureDataReady = false; UINT featureIndex = 0; IndexedDouble maxFreq(0,0); Vector< IndexedDouble > fftMagData(fftWindowSize); for(UINT i=0; i<numChannelsInFFTSignal; i++){ Float spectrumSum = 0; maxFreq.value = 0; maxFreq.index = 0; centroidFeature = 0; for(UINT n=0; n<fftWindowSize; n++){ //Find the max freq if( inputVector[i*fftWindowSize + n] > maxFreq.value ){ maxFreq.value = inputVector[i*fftWindowSize + n]; maxFreq.index = n; } centroidFeature += (n+1) * inputVector[i*fftWindowSize + n]; spectrumSum += inputVector[i*fftWindowSize + n]; //Copy the magnitude data so we can sort it later if needed fftMagData[n].value = inputVector[i*fftWindowSize + n]; fftMagData[n].index = n; } maxFreqFeature = maxFreq.index; maxFreqSpectrumRatio = spectrumSum > 0 ? maxFreq.value/spectrumSum : 0; centroidFeature = spectrumSum > 0 ? centroidFeature/spectrumSum : 0; if( computeMaxFreqFeature ){ featureVector[ featureIndex++ ] = maxFreqFeature; } if( computeMaxFreqSpectrumRatio ){ featureVector[ featureIndex++ ] = maxFreqSpectrumRatio; } if( computeCentroidFeature ){ featureVector[ featureIndex++ ] = centroidFeature; } if( computeTopNFreqFeatures ){ sort(fftMagData.begin(),fftMagData.end(),sortIndexDoubleDecendingValue); for(UINT n=0; n<N; n++){ topNFreqFeatures[n] = fftMagData[n].index; } for(UINT n=0; n<N; n++){ featureVector[ featureIndex++ ] = topNFreqFeatures[n]; } } } //Flag that the features are ready featureDataReady = true; return true; }