64 cerr <<
"ERROR: FFTModel: Window increment ratio " 65 << windowIncrement <<
" / " 67 <<
" must be a power of two" << endl;
68 assert(!(xratio & 0x1));
76 cerr <<
"ERROR: FFTModel: FFT size ratio " 78 <<
" must be a power of two" << endl;
79 assert(!(yratio & 0x1));
95 cerr <<
"FFTModel[" <<
this <<
"]::sourceModelAboutToBeDeleted(" <<
m_sourceModel <<
")" << endl;
130 dynamic_cast<const AggregateWaveModel *>(model);
132 if (aggregate && channel < aggregate->getComponentCount()) {
171 Profiler profiler(
"FFTModel::getColumn",
false);
182 float *magnitudes = (
float *)alloca(h *
sizeof(
float));
187 for (
int y = 0; y < h; ++y) {
188 result.push_back(magnitudes[y]);
192 for (
int i = 0; i < h; ++i) result.push_back(0.f);
203 QString name = tr(
"%1 Hz").arg((n * sr) / ((
getHeight()-1) * 2));
210 if (!
isOK())
return false;
215 frequency = (float(y) * sampleRate) / fftSize;
217 if (x+1 >=
getWidth())
return false;
233 float expectedPhase = oldPhase + (2.0 * M_PI * y * incr) / fftSize;
235 float phaseError =
princargf(newPhase - expectedPhase);
243 (sampleRate * (expectedPhase + phaseError - oldPhase)) /
252 Profiler profiler(
"FFTModel::getPeaks");
255 if (!
isOK())
return peaks;
257 if (ymax == 0 || ymax >
getHeight() - 1) {
263 if (minbin > 0) minbin = minbin - 1;
265 if (maxbin <
getHeight() - 1) maxbin = maxbin + 1;
266 const int n = maxbin - minbin + 1;
270 float *values = (
float *)alloca(n *
sizeof(
float));
273 for (
int bin = ymin; bin <= ymax; ++bin) {
274 if (bin == minbin || bin == maxbin)
continue;
275 if (values[bin - minbin] > values[bin - minbin - 1] &&
276 values[bin - minbin] > values[bin - minbin + 1]) {
286 for (
int i = 0; i < values.size(); ++i) mean += values[i];
287 if (values.size() >0) mean /= values.size();
296 std::deque<float> window;
297 std::vector<int> inrange;
301 int halfWin = medianWinSize/2;
304 if (ymin > halfWin) binmin = ymin - halfWin;
308 if (ymax + halfWin < values.size()) binmax = ymax + halfWin;
309 else binmax = values.size()-1;
313 for (
int bin = binmin; bin <= binmax; ++bin) {
315 float value = values[bin];
317 window.push_back(value);
321 halfWin = medianWinSize/2;
323 while ((
int)window.size() > medianWinSize) {
327 int actualSize = window.size();
330 if (ymax + halfWin < values.size()) binmax = ymax + halfWin;
331 else binmax = values.size()-1;
334 std::deque<float> sorted(window);
335 std::sort(sorted.begin(), sorted.end());
336 float median = sorted[int(sorted.size() * dist)];
339 if (bin > actualSize/2) centrebin = bin - actualSize/2;
341 while (centrebin > prevcentre || bin == binmin) {
343 if (centrebin > prevcentre) ++prevcentre;
345 float centre = values[prevcentre];
347 if (centre > median) {
348 inrange.push_back(centrebin);
351 if (centre <= median || centrebin+1 == values.size()) {
352 if (!inrange.empty()) {
355 for (
int i = 0; i < (int)inrange.size(); ++i) {
356 if (i == 0 || values[inrange[i]] > peakval) {
357 peakval = values[inrange[i]];
358 peakbin = inrange[i];
362 if (peakbin >= ymin && peakbin <= ymax) {
363 peaks.insert(peakbin);
368 if (bin == binmin)
break;
377 int bin,
float &percentile)
const 381 if (bin == 0)
return 3;
384 float binfreq = (float(sampleRate) * bin) / fftSize;
387 int hibin = lrintf((hifreq * fftSize) / sampleRate);
388 int medianWinSize = hibin - bin;
389 if (medianWinSize < 3) medianWinSize = 3;
391 percentile = 0.5 + (binfreq / sampleRate);
393 return medianWinSize;
400 Profiler profiler(
"FFTModel::getPeakFrequencies");
403 if (!
isOK())
return peaks;
415 std::vector<float> phases;
416 for (PeakLocationSet::iterator i = locations.begin();
417 i != locations.end(); ++i) {
422 for (PeakLocationSet::iterator i = locations.begin();
423 i != locations.end(); ++i) {
424 float oldPhase = phases[phaseIndex];
426 float expectedPhase = oldPhase + (2.0 * M_PI * *i * incr) / fftSize;
427 float phaseError =
princargf(newPhase - expectedPhase);
429 (sampleRate * (expectedPhase + phaseError - oldPhase))
433 peaks[*i] = frequency;
448 m_server(model.m_server),
449 m_xshift(model.m_xshift),
450 m_yshift(model.m_yshift)
virtual int getWidth() const
Return the number of columns of bins in the model.
virtual int getSampleRate() const
Return the frame rate in frames per second.
virtual bool estimateStableFrequency(int x, int y, float &frequency)
Calculate an estimated frequency for a stable signal in this bin, using phase unwrapping.
FFTDataServer * getServer(const DenseTimeValueModel *, int, WindowType, int, int, int, bool, StorageAdviser::Criteria, int)
RangeSummarisableTimeValueModel * model
An implementation of DenseThreeDimensionalModel that makes FFT data derived from a DenseTimeValueMode...
const DenseTimeValueModel * getModel() const
ModelChannelSpec getComponent(int c) const
Any bin exceeding its immediate neighbours.
int getWindowIncrement() const
bool getMagnitudesAt(int x, float *values, int minbin=0, int count=0, int step=1)
virtual Model * clone() const
Return a copy of this model.
bool getMagnitudesAt(int x, float *values, int minbin=0, int count=0)
virtual void setSourceModel(Model *model)
Set the source model for this model.
float getPhaseAt(int x, int y)
FFTModel(const DenseTimeValueModel *model, int channel, WindowType windowType, int windowSize, int windowIncrement, int fftSize, bool polar, StorageAdviser::Criteria criteria=StorageAdviser::NoCriteria, int fillFromColumn=0)
Construct an FFT model derived from the given DenseTimeValueModel, with the given window parameters a...
virtual int getSampleRate() const =0
Return the frame rate in frames per second.
Model is the base class for all data models that represent any sort of data on a time scale based on ...
static void modelAboutToBeDeleted(Model *)
int getPeakPickWindowSize(PeakPickType type, int sampleRate, int bin, float &percentile) const
virtual Column getColumn(int x) const
Get data from the given column of bin values.
static void claimInstance(FFTDataServer *)
static float getFrequencyForPitch(int midiPitch, float centsOffset=0, float concertA=0.0)
Return the frequency at the given MIDI pitch plus centsOffset cents (1/100ths of a semitone).
static void releaseInstance(FFTDataServer *)
virtual int getResolution() const
Return the number of sample frames covered by each column of bins.
Base class for models containing dense two-dimensional data (value against time).
virtual bool isOK() const
Return true if the model was constructed successfully.
void sourceModelAboutToBeDeleted()
virtual QString getBinName(int n) const
Get the name of a given bin (i.e.
Peaks picked using sliding median window.
virtual int getHeight() const
Return the number of bins in each column.
virtual PeakSet getPeakFrequencies(PeakPickType type, int x, int ymin=0, int ymax=0)
Return locations and estimated stable frequencies of peak bins.
std::map< int, float > PeakSet
virtual PeakLocationSet getPeaks(PeakPickType type, int x, int ymin=0, int ymax=0)
Return locations of peak bins in the range [ymin,ymax].
std::set< int > PeakLocationSet
static FFTDataServer * getFuzzyInstance(const DenseTimeValueModel *model, int channel, WindowType windowType, int windowSize, int windowIncrement, int fftSize, bool polar, StorageAdviser::Criteria criteria=StorageAdviser::NoCriteria, int fillFromColumn=0)
Profile point instance class.