changeset 12:59520cd6abac

Debug output, and some actual debugging... getting there.
author Chris Cannam
date Thu, 06 Oct 2011 15:21:03 +0100
parents 7169eb47b1bc
children 0d4048bfadbb
files Agent.cpp Agent.h AgentList.h BeatRootProcessor.h Induction.h Makefile
diffstat 6 files changed, 93 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/Agent.cpp	Fri Sep 30 23:11:14 2011 +0100
+++ b/Agent.cpp	Thu Oct 06 15:21:03 2011 +0100
@@ -34,20 +34,35 @@
 bool Agent::considerAsBeat(Event e, AgentList &a) {
     double err;
     if (beatTime < 0) {	// first event
+#ifdef DEBUG_BEATROOT
+        std::cerr << "Ag#" << idNumber << ": accepting first event trivially at " << e.time << std::endl;
+#endif
 	accept(e, 0, 1);
 	return true;
     } else {			// subsequent events
         EventList::iterator last = events.end();
         --last;
 	if (e.time - last->time > expiryTime) {
+#ifdef DEBUG_BEATROOT
+            std::cerr << "Ag#" << idNumber << ": time " << e.time 
+                      << " too late relative to " << last->time << " (expiry "
+                      << expiryTime << "), giving up" << std::endl;
+#endif
 	    phaseScore = -1.0;	// flag agent to be deleted
 	    return false;
 	}
 	double beats = nearbyint((e.time - beatTime) / beatInterval);
 	err = e.time - beatTime - beats * beatInterval;
+#ifdef DEBUG_BEATROOT
+        std::cerr << "Ag#" << idNumber << ": time " << e.time << ", err " << err << " for beats " << beats << std::endl;
+#endif
 	if ((beats > 0) && (-preMargin <= err) && (err <= postMargin)) {
-	    if (fabs(err) > innerMargin)	// Create new agent that skips this
-		a.add(Agent(*this));	//  event (avoids large phase jump)
+	    if (fabs(err) > innerMargin) {	// Create new agent that skips this
+#ifdef DEBUG_BEATROOT
+                std::cerr << "Ag#" << idNumber << ": creating another new agent" << std::endl;
+#endif
+		a.add(clone());	//  event (avoids large phase jump)
+            }
 	    accept(e, err, (int)beats);
 	    return true;
 	}
--- a/Agent.h	Fri Sep 30 23:11:14 2011 +0100
+++ b/Agent.h	Thu Oct 06 15:21:03 2011 +0100
@@ -20,6 +20,10 @@
 
 #include <cmath>
 
+#ifdef DEBUG_BEATROOT
+#include <iostream>
+#endif
+
 class AgentList;
 
 /** Agent is the central class for beat tracking.
@@ -116,30 +120,6 @@
      *  @param ibi The beat period (inter-beat interval) of the Agent's tempo hypothesis.
      */
     Agent(double ibi) {
-	init(ibi);
-    } // constructor
-
-    /** Copy constructor.
-     *  @param clone The Agent to duplicate. */
-    Agent(const Agent &clone) {
-	idNumber = idCounter++;
-	phaseScore = clone.phaseScore;
-	tempoScore = clone.tempoScore;
-	topScoreTime = clone.topScoreTime;
-	beatCount = clone.beatCount;
-	beatInterval = clone.beatInterval;
-	initialBeatInterval = clone.initialBeatInterval;
-	beatTime = clone.beatTime;
-	events = EventList(clone.events);
-	postMargin = clone.postMargin;
-	preMargin = clone.preMargin;
-    } // copy constructor
-
-protected:
-    /** Initialise all the fields of this Agent.
-     *  @param ibi The initial tempo hypothesis of the Agent.
-     */
-    void init(double ibi) {
 	innerMargin = INNER_MARGIN;
 	correctionFactor = DEFAULT_CORRECTION_FACTOR;
 	expiryTime = DEFAULT_EXPIRY_TIME;
@@ -154,10 +134,15 @@
 	topScoreTime = 0.0;
 	beatCount = 0;
 	beatTime = -1.0;
-	events.clear();
-    } // init()
+    } // constructor
 
+    Agent clone() const {
+        Agent a(*this);
+        a.idCounter++;
+        return a;
+    }
 
+protected:
     double threshold(double value, double min, double max) {
 	if (value < min)
 	    return min;
@@ -187,6 +172,12 @@
 		(1.0 - memFactor) * conFactor * e.salience;
 	} else
 	    phaseScore += conFactor * e.salience;
+#ifdef DEBUG_BEATROOT
+        std::cerr << "Ag#" << idNumber << ": " << beatInterval << std::endl;
+        std::cerr << "  Beat" << beatCount << "  Time=" << beatTime
+                  << "  Score=" << tempoScore << ":P" << phaseScore << ":"
+                  << topScoreTime << std::endl;
+#endif
     } // accept()
 
     /** The given Event is tested for a possible beat time. The following situations can occur:
--- a/AgentList.h	Fri Sep 30 23:11:14 2011 +0100
+++ b/AgentList.h	Thu Oct 06 15:21:03 2011 +0100
@@ -21,6 +21,10 @@
 
 #include <algorithm>
 
+#ifdef DEBUG_BEATROOT
+#include <iostream>
+#endif
+
 /** Class for maintaining the set of all Agents involved in beat tracking a piece of music.
  */
 class AgentList
@@ -38,7 +42,13 @@
     bool empty() const { return list.empty(); }
     Container::iterator begin() { return list.begin(); }
     Container::iterator end() { return list.end(); }
-    void push_back(const Agent &a) { list.push_back(a); }
+    size_t size() { return list.size(); }
+    void push_back(const Agent &a) {
+        list.push_back(a);
+#ifdef DEBUG_BEATROOT
+        std::cerr << "  Added Ag#" << a.idNumber << ", have " << list.size() << " agent(s)" << std::endl;
+#endif
+    }
 
     /** Flag for choice between sum and average beat salience values for Agent scores.
      *  The use of summed saliences favours faster tempi or lower metrical levels. */
@@ -61,7 +71,7 @@
      *  @param sort Flag indicating whether the list is sorted or not
      */
     void add(Agent newAgent, bool sort){
-	list.push_back(newAgent);
+        push_back(newAgent);
 	if (sort) this->sort();
     } // add()/2
 
@@ -105,13 +115,24 @@
 		}
 	    }
 	}
+        int removed = 0;
 	for (iterator itr = begin(); itr != end(); ) {
 	    if (itr->phaseScore < 0.0) {
+                ++removed;
 		list.erase(itr);
 	    } else {
 		++itr;
 	    }
 	}
+#ifdef DEBUG_BEATROOT
+        if (removed > 0) {
+            std::cerr << "removeDuplicates: removed " << removed << ", have "
+                      << list.size() << " agent(s) remaining" << std::endl;
+        }
+        for (int i = 0; i <list.size(); ++i) {
+            std::cerr << "agent " << i  << ": time " << list[i].beatTime << std::endl;
+        }
+#endif
     } // removeDuplicates()
 
 public:
@@ -136,26 +157,33 @@
 		break;
 	    bool created = phaseGiven;
 	    double prevBeatInterval = -1.0;
-	    // cc: Duplicate our list of agents, and scan through
-	    // the (now immutable) copy.  This means we can safely
-	    // add agents to our own list while scanning without
-	    // disrupting our scan.
+	    // cc: Duplicate our list of agents, and scan through the
+	    // copy.  This means we can safely add agents to our own
+	    // list while scanning without disrupting our scan.  Each
+	    // agent needs to be re-added to our own list explicitly
+	    // (since it is modified by e.g. considerAsBeat)
 	    Container currentAgents = list;
+            list.clear();
 	    for (Container::iterator ai = currentAgents.begin();
 		 ai != currentAgents.end(); ++ai) {
 		Agent currentAgent = *ai;
 		if (currentAgent.beatInterval != prevBeatInterval) {
 		    if ((prevBeatInterval>=0) && !created && (ev.time<5.0)) {
+#ifdef DEBUG_BEATROOT
+                        std::cerr << "Creating a new agent" << std::endl;
+#endif
 			// Create new agent with different phase
 			Agent newAgent(prevBeatInterval);
-			// This may add an agent to our list
+			// This may add another agent to our list as well
 			newAgent.considerAsBeat(ev, *this);
+                        add(newAgent);
 		    }
 		    prevBeatInterval = currentAgent.beatInterval;
 		    created = phaseGiven;
 		}
 		if (currentAgent.considerAsBeat(ev, *this))
 		    created = true;
+                add(currentAgent);
 	    } // loop for each agent
 	    removeDuplicates();
 	} // loop for each event
@@ -177,6 +205,14 @@
 		best = conf;
 	    }
 	}
+#ifdef DEBUG_BEATROOT
+        if (bestAg) {
+            std::cerr << "Best agent: Ag#" << bestAg->idNumber << std::endl;
+            std::cerr << "  Av-salience = " << best << std::endl;
+        } else {
+            std::cerr << "No surviving agent - beat tracking failed" << std::endl;
+        }
+#endif
 	return bestAg;
     } // bestAgent()
 
--- a/BeatRootProcessor.h	Fri Sep 30 23:11:14 2011 +0100
+++ b/BeatRootProcessor.h	Thu Oct 06 15:21:03 2011 +0100
@@ -23,6 +23,10 @@
 #include <vector>
 #include <cmath>
 
+#ifdef DEBUG_BEATROOT
+#include <iostream>
+#endif
+
 using std::vector;
 
 class BeatRootProcessor
@@ -143,6 +147,10 @@
             onsetList.push_back(e);
         }
 
+#ifdef DEBUG_BEATROOT
+        std::cerr << "Onsets: " << onsetList.size() << std::endl;
+#endif
+
         return BeatTracker::beatTrack(onsetList);
 
     } // processFile()
--- a/Induction.h	Fri Sep 30 23:11:14 2011 +0100
+++ b/Induction.h	Thu Oct 06 15:21:03 2011 +0100
@@ -22,6 +22,10 @@
 
 #include <vector>
 
+#ifdef DEBUG_BEATROOT
+#include <iostream>
+#endif
+
 using std::vector;
 
 /** Performs tempo induction by finding clusters of similar
@@ -227,6 +231,9 @@
 		a.push_back(Agent(beat));
 	    }
 	}
+#ifdef DEBUG_BEATROOT
+        std::cerr << "Induction complete, returning " << a.size() << " agent(s)" << std::endl;
+#endif
 	return a;
     } // beatInduction()
 
--- a/Makefile	Fri Sep 30 23:11:14 2011 +0100
+++ b/Makefile	Thu Oct 06 15:21:03 2011 +0100
@@ -1,5 +1,5 @@
 
-CXXFLAGS	:= -g
+CXXFLAGS	:= -g -DDEBUG_BEATROOT
 
 OBJECTS	:= BeatRootProcessor.o BeatRootVampPlugin.o Peaks.o Agent.o AgentList.o Induction.o