changeset 373:0a44caddd9fe

* Add pitch range in octaves, semitones and cents to the measurement rect as well as in Hz * Avoid crash when adding time ruler This commit contains a lot of debug output (will be slow)
author Chris Cannam
date Wed, 06 Feb 2008 16:21:29 +0000
parents d31b4ccb7ddb
children 7cc6b7b0d819
files base/Pitch.cpp base/Pitch.h
diffstat 2 files changed, 84 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/base/Pitch.cpp	Wed Feb 06 14:15:09 2008 +0000
+++ b/base/Pitch.cpp	Wed Feb 06 16:21:29 2008 +0000
@@ -52,6 +52,37 @@
     return midiPitch;
 }
 
+int
+Pitch::getPitchForFrequencyDifference(float frequencyA,
+                                      float frequencyB,
+                                      float *centsOffsetReturn,
+                                      float concertA)
+{
+    if (concertA <= 0.0) {
+        concertA = Preferences::getInstance()->getTuningFrequency();
+    }
+
+    if (frequencyA > frequencyB) {
+        std::swap(frequencyA, frequencyB);
+    }
+
+    float pA = 12.0 * (log(frequencyA / (concertA / 2.0)) / log(2.0)) + 57.0;
+    float pB = 12.0 * (log(frequencyB / (concertA / 2.0)) / log(2.0)) + 57.0;
+
+    float p = pB - pA;
+
+    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",
@@ -101,6 +132,34 @@
     return getPitchLabel(midiPitch, centsOffset, useFlats);
 }
 
+QString
+Pitch::getLabelForPitchRange(int semis, float cents)
+{
+    int ic = lrintf(cents);
+
+    if (ic == 0) {
+        if (semis >= 12) {
+            return QString("%1'%2").arg(semis/12).arg(semis - 12*(semis/12));
+        } else {
+            return QString("%1").arg(semis);
+        }
+    } else {
+        if (ic > 0) {
+            if (semis >= 12) {
+                return QString("%1'%2+%3c").arg(semis/12).arg(semis - 12*(semis/12)).arg(ic);
+            } else {
+                return QString("%1+%3c").arg(semis).arg(ic);
+            }
+        } else {
+            if (semis >= 12) {
+                return QString("%1'%2%3c").arg(semis/12).arg(semis - 12*(semis/12)).arg(ic);
+            } else {
+                return QString("%1%3c").arg(semis).arg(ic);
+            }
+        }
+    }
+}
+
 bool
 Pitch::isFrequencyInMidiRange(float frequency,
                               float concertA)
--- a/base/Pitch.h	Wed Feb 06 14:15:09 2008 +0000
+++ b/base/Pitch.h	Wed Feb 06 16:21:29 2008 +0000
@@ -51,6 +51,25 @@
 				    float concertA = 0.0);
 
     /**
+     * Return the nearest MIDI pitch range to the given frequency
+     * range, that is, the difference in MIDI pitch values between the
+     * higher and lower frequencies.
+     *
+     * If centsOffsetReturn is non-NULL, return in *centsOffsetReturn
+     * the number of cents (1/100ths of a semitone) difference between
+     * the given frequency difference and the returned MIDI pitch
+     * range.  The cents offset will be in the range [-50,50).
+     * 
+     * If concertA is non-zero, use that as the reference frequency
+     * for the A at MIDI pitch 69; otherwise use the tuning frequency
+     * specified in the application preferences (default 440Hz).
+     */
+    static int getPitchForFrequencyDifference(float frequencyA,
+                                              float frequencyB,
+                                              float *centsOffsetReturn = 0,
+                                              float concertA = 0.0);
+
+    /**
      * Return a string describing the given MIDI pitch, with optional
      * cents offset.  This consists of the note name, octave number
      * (with MIDI pitch 0 having octave number -2), and optional
@@ -82,6 +101,12 @@
 					     bool useFlats = false);
 
     /**
+     * Return a string describing the given pitch range in octaves,
+     * semitones and cents.  This is in the form e.g. "1'2+4c".
+     */
+    static QString getLabelForPitchRange(int semis, float cents = 0);
+
+    /**
      * Return true if the given frequency falls within the range of
      * MIDI note pitches, plus or minus half a semitone.  This is
      * equivalent to testing whether getPitchForFrequency returns a