# HG changeset patch
# User Chris Cannam
# Date 1317420522 -3600
# Node ID 1c1e98cd1b2e536f62d8d11bbb8de2e135d1cdcd
# Parent 4f6626f9ffac7c550a7963bad7ff8d2f0f404692
Fixes so as to run and, in theory, return results without crashing -- still doesn't actually produce meaningful data though
diff -r 4f6626f9ffac -r 1c1e98cd1b2e AgentList.h
--- a/AgentList.h Fri Sep 30 15:39:17 2011 +0100
+++ b/AgentList.h Fri Sep 30 23:08:42 2011 +0100
@@ -88,7 +88,7 @@
if (itr->phaseScore < 0.0) // already flagged for deletion
continue;
iterator itr2 = itr;
- for (++itr2; itr != end(); ++itr) {
+ for (++itr2; itr2 != end(); ++itr2) {
if (itr2->beatInterval - itr->beatInterval > DEFAULT_BI)
break;
if (fabs(itr->beatTime - itr2->beatTime) > DEFAULT_BT)
@@ -168,6 +168,7 @@
double best = -1.0;
Agent *bestAg = 0;
for (iterator itr = begin(); itr != end(); ++itr) {
+ if (itr->events.empty()) continue;
double startTime = itr->events.begin()->time;
double conf = (itr->phaseScore + itr->tempoScore) /
(useAverageSalience? (double)itr->beatCount: 1.0);
diff -r 4f6626f9ffac -r 1c1e98cd1b2e BeatRootProcessor.cpp
--- a/BeatRootProcessor.cpp Fri Sep 30 15:39:17 2011 +0100
+++ b/BeatRootProcessor.cpp Fri Sep 30 23:08:42 2011 +0100
@@ -18,15 +18,3 @@
bool
BeatRootProcessor::silent = true;
-double
-BeatRootProcessor::silenceThreshold = 0.0004;
-
-double
-BeatRootProcessor::rangeThreshold = 10;
-
-int
-BeatRootProcessor::normaliseMode = 2;
-
-//int
-//BeatRootProcessor::energyOversampleFactor = 2;
-
diff -r 4f6626f9ffac -r 1c1e98cd1b2e BeatRootProcessor.h
--- a/BeatRootProcessor.h Fri Sep 30 15:39:17 2011 +0100
+++ b/BeatRootProcessor.h Fri Sep 30 23:08:42 2011 +0100
@@ -51,15 +51,6 @@
/** The size of an FFT frame in samples (see fftTime
) */
int fftSize;
- /** The number of overlapping frames of audio data which have been read. */
- int frameCount;
-
- /** RMS amplitude of the current frame. */
- double frameRMS;
-
- /** Long term average frame energy (in frequency domain representation). */
- double ltAverage;
-
/** Spectral flux onset detection function, indexed by frame. */
vector spectralFlux;
@@ -79,16 +70,7 @@
/** The magnitude spectrum of the most recent frame. Used for
* calculating the spectral flux. */
vector prevFrame;
-
- /** The magnitude spectrum of the current frame. */
- vector newFrame;
- /** The magnitude spectra of all frames, used for plotting the spectrogram. */
- vector > frames; //!!! do we need this? much cheaper to lose it if we don't
-
- /** The RMS energy of all frames. */
-// vector energy; //!!! unused in beat tracking?
-
/** The estimated onset times from peak-picking the onset
* detection function(s). */
vector onsets;
@@ -99,38 +81,12 @@
/** Flag for suppressing all standard output messages except results. */
static bool silent;
- /** RMS frame energy below this value results in the frame being
- * set to zero, so that normalisation does not have undesired
- * side-effects. */
- static double silenceThreshold; //!!!??? energy of what? should not be static?
-
- /** For dynamic range compression, this value is added to the log
- * magnitude in each frequency bin and any remaining negative
- * values are then set to zero.
- */
- static double rangeThreshold; //!!! sim
-
- /** Determines method of normalisation. Values can be:
- * - 0: no normalisation
- * - 1: normalisation by current frame energy
- * - 2: normalisation by exponential average of frame energy
- *
- */
- static int normaliseMode;
-
- /** Ratio between rate of sampling the signal energy (for the
- * amplitude envelope) and the hop size */
-// static int energyOversampleFactor; //!!! not used?
-
public:
/** Constructor: note that streams are not opened until the input
* file is set (see setInputFile()
). */
BeatRootProcessor(float sr) :
sampleRate(sr) {
- frameRMS = 0;
- ltAverage = 0;
- frameCount = 0;
hopSize = 0;
fftSize = 0;
hopTime = 0.010;
@@ -143,15 +99,60 @@
init();
}
+ /** Processes a frame of frequency-domain audio data by mapping
+ * the frequency bins into a part-linear part-logarithmic array,
+ * then computing the spectral flux then (optionally) normalising
+ * and calculating onsets.
+ */
+ void processFrame(const float *const *inputBuffers) {
+ double flux = 0;
+ for (int i = 0; i <= fftSize/2; i++) {
+ double mag = sqrt(inputBuffers[0][i*2] * inputBuffers[0][i*2] +
+ inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]);
+ if (mag > prevFrame[i]) flux += mag - prevFrame[i];
+ prevFrame[i] = mag;
+ }
+
+ spectralFlux.push_back(flux);
+
+ } // processFrame()
+
+ /** Tracks beats once all frames have been processed by processFrame
+ */
+ EventList beatTrack() {
+
+ double hop = hopTime;
+ Peaks::normalise(spectralFlux);
+ vector peaks = Peaks::findPeaks(spectralFlux, (int)lrint(0.06 / hop), 0.35, 0.84, true);
+ onsets.clear();
+ onsets.resize(peaks.size(), 0);
+ vector::iterator it = peaks.begin();
+ onsetList.clear();
+ double minSalience = Peaks::min(spectralFlux);
+ for (int i = 0; i < onsets.size(); i++) {
+ int index = *it;
+ ++it;
+ onsets[i] = index * hop;
+ Event e = BeatTracker::newBeat(onsets[i], 0);
+// if (debug)
+// System.err.printf("Onset: %8.3f %8.3f %8.3f\n",
+// onsets[i], energy[index], slope[index]);
+// e.salience = slope[index]; // or combination of energy + slope??
+ // Note that salience must be non-negative or the beat tracking system fails!
+ e.salience = spectralFlux[index] - minSalience;
+ onsetList.push_back(e);
+ }
+
+ return BeatTracker::beatTrack(onsetList);
+
+ } // processFile()
+
protected:
/** Allocates memory for arrays, based on parameter settings */
void init() {
makeFreqMap(fftSize, sampleRate);
prevFrame.clear();
- for (int i = 0; i < freqMapSize; i++) prevFrame.push_back(0);
- frameCount = 0;
- frameRMS = 0;
- ltAverage = 0;
+ for (int i = 0; i <= fftSize/2; i++) prevFrame.push_back(0);
spectralFlux.clear();
} // init()
@@ -180,136 +181,6 @@
freqMapSize = freqMap[i-1] + 1;
} // makeFreqMap()
- /** Processes a frame of frequency-domain audio data by mapping
- * the frequency bins into a part-linear part-logarithmic array,
- * then computing the spectral flux then (optionally) normalising
- * and calculating onsets.
- */
- void processFrame(const float *const *inputBuffers) {
- newFrame.clear();
- for (int i = 0; i < freqMapSize; i++) {
- newFrame.push_back(0);
- }
- double flux = 0;
- for (int i = 0; i <= fftSize/2; i++) {
- double mag = sqrt(inputBuffers[0][i*2] * inputBuffers[0][i*2] +
- inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]);
- if (mag > prevFrame[i]) flux += mag - prevFrame[i];
- prevFrame[i] = mag;
- newFrame[freqMap[i]] += mag;
- }
- spectralFlux.push_back(flux);
- frames.push_back(newFrame);
-// for (int i = 0; i < freqMapSize; i++)
-// [frameCount][i] = newFrame[i];
-/*
- int index = cbIndex - (fftSize - hopSize);
- if (index < 0)
- index += fftSize;
- int sz = (fftSize - hopSize) / energyOversampleFactor;
- for (int j = 0; j < energyOversampleFactor; j++) {
- double newEnergy = 0;
- for (int i = 0; i < sz; i++) {
- newEnergy += circBuffer[index] * circBuffer[index];
- if (++index == fftSize)
- index = 0;
- }
- energy[frameCount * energyOversampleFactor + j] =
- newEnergy / sz <= 1e-6? 0: log(newEnergy / sz) + 13.816;
- }*/
-
- double decay = frameCount >= 200? 0.99:
- (frameCount < 100? 0: (frameCount - 100) / 100.0);
-
- //!!! uh-oh -- frameRMS has not been calculated (it came from time-domain signal) -- will always appear silent
-
- if (ltAverage == 0)
- ltAverage = frameRMS;
- else
- ltAverage = ltAverage * decay + frameRMS * (1.0 - decay);
- if (frameRMS <= silenceThreshold)
- for (int i = 0; i < freqMapSize; i++)
- frames[frameCount][i] = 0;
- else {
- if (normaliseMode == 1)
- for (int i = 0; i < freqMapSize; i++)
- frames[frameCount][i] /= frameRMS;
- else if (normaliseMode == 2)
- for (int i = 0; i < freqMapSize; i++)
- frames[frameCount][i] /= ltAverage;
- for (int i = 0; i < freqMapSize; i++) {
- frames[frameCount][i] = log(frames[frameCount][i]) + rangeThreshold;
- if (frames[frameCount][i] < 0)
- frames[frameCount][i] = 0;
- }
- }
-// weightedPhaseDeviation();
-// if (debug)
-// System.err.printf("PhaseDev: t=%7.3f phDev=%7.3f RMS=%7.3f\n",
-// frameCount * hopTime,
-// phaseDeviation[frameCount],
-// frameRMS);
- frameCount++;
- } // processFrame()
-
- /** Processes a complete file of audio data. */
- void processFile() {
-/*
- while (pcmInputStream != null) {
- // Profile.start(0);
- processFrame();
- // Profile.log(0);
- if (Thread.currentThread().isInterrupted()) {
- System.err.println("info: INTERRUPTED in processFile()");
- return;
- }
- }
-*/
-// double[] x1 = new double[phaseDeviation.length];
-// for (int i = 0; i < x1.length; i++) {
-// x1[i] = i * hopTime;
-// phaseDeviation[i] = (phaseDeviation[i] - 0.4) * 100;
-// }
-// double[] x2 = new double[energy.length];
-// for (int i = 0; i < x2.length; i++)
-// x2[i] = i * hopTime / energyOversampleFactor;
-// // plot.clear();
-// plot.addPlot(x1, phaseDeviation, Color.green, 7);
-// plot.addPlot(x2, energy, Color.red, 7);
-// plot.setTitle("Test phase deviation");
-// plot.fitAxes();
-
-// double[] slope = new double[energy.length];
-// double hop = hopTime / energyOversampleFactor;
-// Peaks.getSlope(energy, hop, 15, slope);
-// vector peaks = Peaks.findPeaks(slope, (int)lrint(0.06 / hop), 10);
-
- double hop = hopTime;
- Peaks::normalise(spectralFlux);
- vector peaks = Peaks::findPeaks(spectralFlux, (int)lrint(0.06 / hop), 0.35, 0.84, true);
- onsets.clear();
- onsets.resize(peaks.size(), 0);
- vector::iterator it = peaks.begin();
- onsetList.clear();
- double minSalience = Peaks::min(spectralFlux);
- for (int i = 0; i < onsets.size(); i++) {
- int index = *it;
- ++it;
- onsets[i] = index * hop;
- Event e = BeatTracker::newBeat(onsets[i], 0);
-// if (debug)
-// System.err.printf("Onset: %8.3f %8.3f %8.3f\n",
-// onsets[i], energy[index], slope[index]);
-// e.salience = slope[index]; // or combination of energy + slope??
- // Note that salience must be non-negative or the beat tracking system fails!
- e.salience = spectralFlux[index] - minSalience;
- onsetList.push_back(e);
- }
-
- //!!! This onsetList is then fed in to BeatTrackDisplay::beatTrack
-
- } // processFile()
-
}; // class AudioProcessor
diff -r 4f6626f9ffac -r 1c1e98cd1b2e BeatRootVampPlugin.cpp
--- a/BeatRootVampPlugin.cpp Fri Sep 30 15:39:17 2011 +0100
+++ b/BeatRootVampPlugin.cpp Fri Sep 30 23:08:42 2011 +0100
@@ -16,6 +16,9 @@
#include "BeatRootVampPlugin.h"
#include "BeatRootProcessor.h"
+#include "Event.h"
+
+#include
#include
BeatRootVampPlugin::BeatRootVampPlugin(float inputSampleRate) :
@@ -197,14 +200,29 @@
BeatRootVampPlugin::FeatureSet
BeatRootVampPlugin::process(const float *const *inputBuffers, Vamp::RealTime timestamp)
{
- // Do actual work!
+ m_processor->processFrame(inputBuffers);
return FeatureSet();
}
BeatRootVampPlugin::FeatureSet
BeatRootVampPlugin::getRemainingFeatures()
{
- return FeatureSet();
+ EventList el = m_processor->beatTrack();
+
+ Feature f;
+ f.hasTimestamp = true;
+ f.hasDuration = false;
+ f.label = "";
+ f.values.clear();
+
+ FeatureSet fs;
+
+ for (int i = 0; i < el.size(); ++i) {
+ f.timestamp = Vamp::RealTime::frame2RealTime(el[i].time, m_inputSampleRate);
+ fs[0].push_back(f);
+ }
+
+ return fs;
}