1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
/**********************************************************************
Audacity: A Digital Audio Editor
Audacity(R) is copyright (c) 1999-2012 Audacity Team.
License: GPL v2 or later. See License.txt.
PitchName.cpp
Vaughan Johnson and Dominic Mazzoni.
******************************************************************//**
\file PitchName.cpp
\brief Utilities for converting from frequency to pitch
and from pitch to absolute (e.g., C4 for middle C)
or nominal (A through G#) pitch name.
*//*******************************************************************/
#include "PitchName.h"
#include "Internat.h"
#include <math.h>
double FreqToMIDInote(const double freq)
{
// Make the calculation relative to A440 (A4), note number 69.
return (69.0 + (12.0 * (log(freq / 440.0) / log(2.0))));
}
double MIDInoteToFreq(const double dMIDInote)
{
return (440.0 * pow(2.0, (dMIDInote - 69.0) / 12.0));
}
unsigned int PitchIndex(const double dMIDInote)
{
// MIDI numbers can be negative. Round in the right direction.
double dRound = (dMIDInote < 0.0) ? -0.5 : 0.5;
int nPitchIndex = ((int)(dMIDInote + dRound) % 12);
// Because of the modulo, we know we're within 12 of positive, if dMIDInote is negative.
if (nPitchIndex < 0)
nPitchIndex += 12;
return nPitchIndex;
}
int PitchOctave(const double dMIDInote)
{
double dRound = (dMIDInote < 0.0) ? -0.5 : 0.5;
return ((int)((dMIDInote + dRound) / 12.0) - 1);
}
TranslatableString PitchName(const double dMIDInote, const PitchNameChoice choice)
{
static const TranslatableString sharpnames[12] = {
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("C"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("C\u266f"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("D"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("D\u266f"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("E"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("F"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("F\u266f"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("G"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("G\u266f"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("A"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("A\u266f"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("B"),
};
static const TranslatableString flatnames[12] = {
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("C"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("D\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("D"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("E\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("E"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("F"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("G\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("G"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("A\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("A"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("B\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("B"),
};
static const TranslatableString bothnames[12] = {
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("C"),
/* i18n-hint: Two, alternate names of a musical note in the 12-tone chromatic scale */
XO("C\u266f/D\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("D"),
/* i18n-hint: Two, alternate names of a musical note in the 12-tone chromatic scale */
XO("D\u266f/E\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("E"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("F"),
/* i18n-hint: Two, alternate names of a musical note in the 12-tone chromatic scale */
XO("F\u266f/G\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("G"),
/* i18n-hint: Two, alternate names of a musical note in the 12-tone chromatic scale */
XO("G\u266f/A\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("A"),
/* i18n-hint: Two, alternate names of a musical note in the 12-tone chromatic scale */
XO("A\u266f/B\u266d"),
/* i18n-hint: Name of a musical note in the 12-tone chromatic scale */
XO("B"),
};
const TranslatableString *table = nullptr;
switch ( choice ) {
case PitchNameChoice::Sharps: table = sharpnames; break;
case PitchNameChoice::Flats: table = flatnames; break;
case PitchNameChoice::Both: table = bothnames; break;
default: wxASSERT(false); break;
}
return table[PitchIndex(dMIDInote)];
}
TranslatableString PitchName_Absolute(const double dMIDInote, const PitchNameChoice choice)
{
// The format string is not localized. Should it be?
return Verbatim( wxT("%s%d") )
.Format( PitchName(dMIDInote, choice), PitchOctave(dMIDInote) );
}
double PitchToMIDInote(const unsigned int nPitchIndex, const int nPitchOctave)
{
return ((double)nPitchIndex + (((double)nPitchOctave + 1.0) * 12.0));
}
double PitchToFreq(const unsigned int nPitchIndex, const int nPitchOctave)
{
return MIDInoteToFreq(PitchToMIDInote(nPitchIndex, nPitchOctave));
}
|