annotate base/Pitch.cpp @ 116:a08718723b20

* Add units repository, and unit property on time-value and note layers.
author Chris Cannam
date Thu, 11 May 2006 15:02:14 +0000
parents d397ea0a79f5
children 4f26f623a8bc
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@19 2
Chris@19 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@52 7 This file copyright 2006 Chris Cannam.
Chris@19 8
Chris@52 9 This program is free software; you can redistribute it and/or
Chris@52 10 modify it under the terms of the GNU General Public License as
Chris@52 11 published by the Free Software Foundation; either version 2 of the
Chris@52 12 License, or (at your option) any later version. See the file
Chris@52 13 COPYING included with this distribution for more information.
Chris@19 14 */
Chris@19 15
Chris@19 16 #include "Pitch.h"
Chris@19 17
Chris@19 18 #include <cmath>
Chris@19 19
Chris@19 20 float
Chris@19 21 Pitch::getFrequencyForPitch(int midiPitch,
Chris@19 22 float centsOffset,
Chris@19 23 float concertA)
Chris@19 24 {
Chris@19 25 float p = float(midiPitch) + (centsOffset / 100);
Chris@19 26 return concertA * powf(2.0, (p - 69.0) / 12.0);
Chris@19 27 }
Chris@19 28
Chris@19 29 int
Chris@19 30 Pitch::getPitchForFrequency(float frequency,
Chris@19 31 float *centsOffsetReturn,
Chris@19 32 float concertA)
Chris@19 33 {
Chris@19 34 float p = 12.0 * (log(frequency / (concertA / 2.0)) / log(2.0)) + 57.0;
Chris@19 35
Chris@19 36 int midiPitch = int(p + 0.00001);
Chris@19 37 float centsOffset = (p - midiPitch) * 100.0;
Chris@19 38
Chris@19 39 if (centsOffset >= 50.0) {
Chris@19 40 midiPitch = midiPitch + 1;
Chris@19 41 centsOffset = -(100.0 - centsOffset);
Chris@19 42 }
Chris@19 43
Chris@19 44 if (centsOffsetReturn) *centsOffsetReturn = centsOffset;
Chris@19 45 return midiPitch;
Chris@19 46 }
Chris@19 47
Chris@19 48 static QString notes[] = {
Chris@19 49 "C%1", "C#%1", "D%1", "D#%1",
Chris@19 50 "E%1", "F%1", "F#%1", "G%1",
Chris@19 51 "G#%1", "A%1", "A#%1", "B%1"
Chris@19 52 };
Chris@19 53
Chris@26 54 static QString flatNotes[] = {
Chris@26 55 "C%1", "Db%1", "D%1", "Eb%1",
Chris@26 56 "E%1", "F%1", "Gb%1", "G%1",
Chris@26 57 "Ab%1", "A%1", "Bb%1", "B%1"
Chris@26 58 };
Chris@26 59
Chris@19 60 QString
Chris@19 61 Pitch::getPitchLabel(int midiPitch,
Chris@26 62 float centsOffset,
Chris@26 63 bool useFlats)
Chris@19 64 {
Chris@19 65 int octave = -2;
Chris@19 66
Chris@19 67 if (midiPitch < 0) {
Chris@19 68 while (midiPitch < 0) {
Chris@19 69 midiPitch += 12;
Chris@19 70 --octave;
Chris@19 71 }
Chris@19 72 } else {
Chris@19 73 octave = midiPitch / 12 - 2;
Chris@19 74 }
Chris@19 75
Chris@26 76 QString plain = (useFlats ? flatNotes : notes)[midiPitch % 12].arg(octave);
Chris@19 77
Chris@19 78 int ic = lrintf(centsOffset);
Chris@19 79 if (ic == 0) return plain;
Chris@19 80 else if (ic > 0) return QString("%1+%2c").arg(plain).arg(ic);
Chris@19 81 else return QString("%1%2c").arg(plain).arg(ic);
Chris@19 82 }
Chris@19 83
Chris@19 84 QString
Chris@19 85 Pitch::getPitchLabelForFrequency(float frequency,
Chris@26 86 float concertA,
Chris@26 87 bool useFlats)
Chris@19 88 {
Chris@19 89 float centsOffset = 0.0;
Chris@19 90 int midiPitch = getPitchForFrequency(frequency, &centsOffset, concertA);
Chris@26 91 return getPitchLabel(midiPitch, centsOffset, useFlats);
Chris@19 92 }
Chris@19 93