changeset 19:a7ed14263fe4

* Add Chromagram plugin, and make a number of fixes to the dense 3d model and colour 3d plot class to accommodate it * Add pitch-conversion methods in base/Pitch * Commit previously overlooked Command.cpp
author Chris Cannam
date Wed, 01 Feb 2006 14:49:49 +0000
parents 4563a72c1d8b
children 742e6882e187
files base/Command.cpp base/Pitch.cpp base/Pitch.h base/View.cpp plugin/FeatureExtractionPlugin.h plugin/FeatureExtractionPluginFactory.cpp transform/FeatureExtractionPluginTransform.cpp
diffstat 7 files changed, 188 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/Command.cpp	Wed Feb 01 14:49:49 2006 +0000
@@ -0,0 +1,59 @@
+/* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    A waveform viewer and audio annotation editor.
+    Chris Cannam, Queen Mary University of London, 2005-2006
+    
+    This is experimental software.  Not for distribution.
+*/
+
+#include "Command.h"
+
+MacroCommand::MacroCommand(QString name) :
+    m_name(name)
+{
+}
+
+MacroCommand::~MacroCommand()
+{
+    for (size_t i = 0; i < m_commands.size(); ++i) {
+	delete m_commands[i];
+    }
+}
+
+void
+MacroCommand::addCommand(Command *command)
+{
+    m_commands.push_back(command);
+}
+
+void
+MacroCommand::deleteCommand(Command *command)
+{
+    for (std::vector<Command *>::iterator i = m_commands.begin();
+	 i != m_commands.end(); ++i) {
+
+	if (*i == command) {
+	    m_commands.erase(i);
+	    delete command;
+	    return;
+	}
+    }
+}
+
+void
+MacroCommand::execute()
+{
+    for (size_t i = 0; i < m_commands.size(); ++i) {
+	m_commands[i]->execute();
+    }
+}
+
+void
+MacroCommand::unexecute()
+{
+    for (size_t i = 0; i < m_commands.size(); ++i) {
+	m_commands[m_commands.size() - i - 1]->unexecute();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/Pitch.cpp	Wed Feb 01 14:49:49 2006 +0000
@@ -0,0 +1,79 @@
+/* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    A waveform viewer and audio annotation editor.
+    Chris Cannam, Queen Mary University of London, 2005-2006
+    
+    This is experimental software.  Not for distribution.
+*/
+
+#include "Pitch.h"
+
+#include <cmath>
+
+float
+Pitch::getFrequencyForPitch(int midiPitch,
+			    float centsOffset,
+			    float concertA)
+{
+    float p = float(midiPitch) + (centsOffset / 100);
+    return concertA * powf(2.0, (p - 69.0) / 12.0);
+}
+
+int
+Pitch::getPitchForFrequency(float frequency,
+			    float *centsOffsetReturn,
+			    float concertA)
+{
+    float p = 12.0 * (log(frequency / (concertA / 2.0)) / log(2.0)) + 57.0;
+
+    int midiPitch = int(p + 0.00001);
+    float centsOffset = (p - midiPitch) * 100.0;
+
+    if (centsOffset >= 50.0) {
+	midiPitch = midiPitch + 1;
+	centsOffset = -(100.0 - centsOffset);
+    }
+    
+    if (centsOffsetReturn) *centsOffsetReturn = centsOffset;
+    return midiPitch;
+}
+
+static QString notes[] = {
+    "C%1",  "C#%1", "D%1",  "D#%1",
+    "E%1",  "F%1",  "F#%1", "G%1",
+    "G#%1", "A%1",  "A#%1", "B%1"
+};
+
+QString
+Pitch::getPitchLabel(int midiPitch,
+		     float centsOffset)
+{
+    int octave = -2;
+
+    if (midiPitch < 0) {
+	while (midiPitch < 0) {
+	    midiPitch += 12;
+	    --octave;
+	}
+    } else {
+	octave = midiPitch / 12 - 2;
+    }
+
+    QString plain = notes[midiPitch % 12].arg(octave);
+
+    int ic = lrintf(centsOffset);
+    if (ic == 0) return plain;
+    else if (ic > 0) return QString("%1+%2c").arg(plain).arg(ic);
+    else return QString("%1%2c").arg(plain).arg(ic);
+}
+
+QString
+Pitch::getPitchLabelForFrequency(float frequency,
+				 float concertA)
+{
+    float centsOffset = 0.0;
+    int midiPitch = getPitchForFrequency(frequency, &centsOffset, concertA);
+    return getPitchLabel(midiPitch, centsOffset);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/base/Pitch.h	Wed Feb 01 14:49:49 2006 +0000
@@ -0,0 +1,34 @@
+/* -*- c-basic-offset: 4 -*-  vi:set ts=8 sts=4 sw=4: */
+
+/*
+    A waveform viewer and audio annotation editor.
+    Chris Cannam, Queen Mary University of London, 2005-2006
+    
+    This is experimental software.  Not for distribution.
+*/
+
+#ifndef _PITCH_H_
+#define _PITCH_H_
+
+#include <QString>
+
+class Pitch
+{
+public:
+    static float getFrequencyForPitch(int midiPitch,
+				      float centsOffset = 0,
+				      float concertA = 440.0);
+
+    static int getPitchForFrequency(float frequency,
+				    float *centsOffsetReturn = 0,
+				    float concertA = 440.0);
+
+    static QString getPitchLabel(int midiPitch,
+				 float centsOffset = 0);
+
+    static QString getPitchLabelForFrequency(float frequency,
+					     float concertA = 440.0);
+};
+
+
+#endif
--- a/base/View.cpp	Tue Jan 31 17:19:45 2006 +0000
+++ b/base/View.cpp	Wed Feb 01 14:49:49 2006 +0000
@@ -808,8 +808,6 @@
 void
 View::checkProgress(void *object)
 {
-//    std::cerr << "View::checkProgress(" << object << ")" << std::endl;
-
     if (!m_showProgress) return;
 
     int ph = height();
--- a/plugin/FeatureExtractionPlugin.h	Tue Jan 31 17:19:45 2006 +0000
+++ b/plugin/FeatureExtractionPlugin.h	Wed Feb 01 14:49:49 2006 +0000
@@ -149,6 +149,12 @@
 	size_t valueCount;
 
 	/**
+	 * The names of each of the values, if appropriate.  This is
+	 * always optional.
+	 */
+	std::vector<std::string> valueNames;
+
+	/**
 	 * True if the results in the output have a fixed numeric
 	 * range (minimum and maximum values).  Undefined if
 	 * valueCount is zero.
--- a/plugin/FeatureExtractionPluginFactory.cpp	Tue Jan 31 17:19:45 2006 +0000
+++ b/plugin/FeatureExtractionPluginFactory.cpp	Wed Feb 01 14:49:49 2006 +0000
@@ -11,6 +11,7 @@
 #include "PluginIdentifier.h"
 
 #include "plugins/BeatDetect.h" //!!!
+#include "plugins/ChromagramPlugin.h" //!!!
 #include "plugins/ZeroCrossing.h" //!!!
 
 #include <iostream>
@@ -64,6 +65,7 @@
 {
     std::vector<QString> rv;
     rv.push_back("sv:_builtin:beats"); //!!!
+    rv.push_back("sv:_builtin:chromagram"); //!!!
     rv.push_back("sv:_builtin:zerocrossing"); //!!!
     return rv;
 }
@@ -89,6 +91,10 @@
 	return new BeatDetector(inputSampleRate); //!!!
     }
 
+    if (label == "chromagram") {
+	return new ChromagramPlugin(inputSampleRate); //!!!
+    }
+
     if (label == "zerocrossing") {
 	return new ZeroCrossing(inputSampleRate); //!!!
     }
--- a/transform/FeatureExtractionPluginTransform.cpp	Tue Jan 31 17:19:45 2006 +0000
+++ b/transform/FeatureExtractionPluginTransform.cpp	Wed Feb 01 14:49:49 2006 +0000
@@ -124,7 +124,7 @@
     } else {
 	
 	m_output = new DenseThreeDimensionalModel(modelRate, modelResolution,
-						  valueCount);
+						  valueCount, false);
     }
 }
 
@@ -335,7 +335,9 @@
 
     } else {
 
-	//!!! Can't actually do this with the 3D model (yet?)
+	DenseThreeDimensionalModel *model = getOutput<DenseThreeDimensionalModel>();
+	if (!model) return;
+	model->setCompletion(completion);
     }
 }