audacia/src/PitchName.cpp

170 lines
6.0 KiB
C++

/**********************************************************************
Audacity: A Digital Audio Editor
Audacity(R) is copyright (c) 1999-2012 Audacity Team.
License: GPL v2. 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 <math.h>
#include <stdio.h>
#include "Internat.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));
}