# HG changeset patch # User Chris Cannam # Date 1202314889 0 # Node ID 0a44caddd9fea42f63af251ea12a02d7ee0356a1 # Parent d31b4ccb7ddb98695ca13e8435db12d3d981dfb2 * 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) diff -r d31b4ccb7ddb -r 0a44caddd9fe base/Pitch.cpp --- 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) diff -r d31b4ccb7ddb -r 0a44caddd9fe base/Pitch.h --- 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