From 3fbfef0eb17e9c0b5c9ba32c2d20543a84a34093 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Tue, 3 Oct 2017 11:42:59 -0400 Subject: [PATCH] Plot Spectrum, Change Pitch localize pitch names; Unicode sharp/flat --- src/PitchName.cpp | 176 +++++++++++++++++++----------------- src/PitchName.h | 11 ++- src/effects/ChangePitch.cpp | 14 +-- 3 files changed, 103 insertions(+), 98 deletions(-) diff --git a/src/PitchName.cpp b/src/PitchName.cpp index 29c42f334..ef8e62872 100644 --- a/src/PitchName.cpp +++ b/src/PitchName.cpp @@ -20,6 +20,7 @@ #include #include +#include "Audacity.h" #include "PitchName.h" @@ -54,96 +55,105 @@ int PitchOctave(const double dMIDInote) } -static wxChar gPitchName[10]; -static wxChar * pPitchName; - -wxChar * PitchName(const double dMIDInote, const bool bWantFlats /* = false */) +wxString PitchName(const double dMIDInote, const PitchNameChoice choice) { - pPitchName = gPitchName; + static const wxString 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"), + }; - switch (PitchIndex(dMIDInote)) { - case 0: - *pPitchName++ = wxT('C'); - break; - case 1: - if (bWantFlats) { - *pPitchName++ = wxT('D'); - *pPitchName++ = wxT('b'); - } else { - *pPitchName++ = wxT('C'); - *pPitchName++ = wxT('#'); - } - break; - case 2: - *pPitchName++ = wxT('D'); - break; - case 3: - if (bWantFlats) { - *pPitchName++ = wxT('E'); - *pPitchName++ = wxT('b'); - } else { - *pPitchName++ = wxT('D'); - *pPitchName++ = wxT('#'); - } - break; - case 4: - *pPitchName++ = wxT('E'); - break; - case 5: - *pPitchName++ = wxT('F'); - break; - case 6: - if (bWantFlats) { - *pPitchName++ = wxT('G'); - *pPitchName++ = wxT('b'); - } else { - *pPitchName++ = wxT('F'); - *pPitchName++ = wxT('#'); - } - break; - case 7: - *pPitchName++ = wxT('G'); - break; - case 8: - if (bWantFlats) { - *pPitchName++ = wxT('A'); - *pPitchName++ = wxT('b'); - } else { - *pPitchName++ = wxT('G'); - *pPitchName++ = wxT('#'); - } - break; - case 9: - *pPitchName++ = wxT('A'); - break; - case 10: - if (bWantFlats) { - *pPitchName++ = wxT('B'); - *pPitchName++ = wxT('b'); - } else { - *pPitchName++ = wxT('A'); - *pPitchName++ = wxT('#'); - } - break; - case 11: - *pPitchName++ = wxT('B'); - break; + static const wxString 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 wxString 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 wxString *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; } - *pPitchName = wxT('\0'); - - return gPitchName; + return table[PitchIndex(dMIDInote)]; } -wxChar * PitchName_Absolute(const double dMIDInote, const bool bWantFlats /* = false */) +wxString PitchName_Absolute(const double dMIDInote, const PitchNameChoice choice) { - PitchName(dMIDInote, bWantFlats); - - // PitchName sets pPitchName to the next available char in gPitchName, - // so it's ready to append the register number. - wxSnprintf(pPitchName, 8, wxT("%d"), PitchOctave(dMIDInote)); - - return gPitchName; + // The format string is not localized. Should it be? + return wxString::Format( + wxT("%s%d"), PitchName(dMIDInote, choice), PitchOctave(dMIDInote) ); } double PitchToMIDInote(const unsigned int nPitchIndex, const int nPitchOctave) diff --git a/src/PitchName.h b/src/PitchName.h index bd117c50e..84ddad315 100644 --- a/src/PitchName.h +++ b/src/PitchName.h @@ -40,15 +40,20 @@ unsigned int PitchIndex(const double dMIDInote); // MIDI note number 0 is C-1 in Scientific pitch notation. int PitchOctave(const double dMIDInote); +enum class PitchNameChoice { Sharps, Flats, Both }; + // PitchName takes dMIDInote (per result from // FreqToMIDInote) and returns a standard pitch/note name [C, C#, etc.). -// Sharps are the default, unless, bWantFlats is true. -wxChar * PitchName(const double dMIDInote, const bool bWantFlats = false); +wxString PitchName( + const double dMIDInote, + const PitchNameChoice choice = PitchNameChoice::Sharps ); // PitchName_Absolute does the same thing as PitchName, but appends // the octave number, e.g., instead of "C" it will return "C4" // if the dMIDInote corresonds to middle C, i.e., is 60. -wxChar * PitchName_Absolute(const double dMIDInote, const bool bWantFlats = false); +wxString PitchName_Absolute( + const double dMIDInote, + const PitchNameChoice choice = PitchNameChoice::Sharps); double PitchToMIDInote(const unsigned int nPitchIndex, const int nPitchOctave); diff --git a/src/effects/ChangePitch.cpp b/src/effects/ChangePitch.cpp index fa4c33df8..c1a52f4b6 100644 --- a/src/effects/ChangePitch.cpp +++ b/src/effects/ChangePitch.cpp @@ -228,18 +228,8 @@ void EffectChangePitch::PopulateOrExchange(ShuttleGui & S) DeduceFrequencies(); // Set frequency-related control values based on sample. wxArrayString pitch; - pitch.Add(wxT("C")); - pitch.Add(wxT("C#/Db")); - pitch.Add(wxT("D")); - pitch.Add(wxT("D#/Eb")); - pitch.Add(wxT("E")); - pitch.Add(wxT("F")); - pitch.Add(wxT("F#/Gb")); - pitch.Add(wxT("G")); - pitch.Add(wxT("G#/Ab")); - pitch.Add(wxT("A")); - pitch.Add(wxT("A#/Bb")); - pitch.Add(wxT("B")); + for (int ii = 0; ii < 12; ++ii) + pitch.Add( PitchName( ii, PitchNameChoice::Both ) ); S.SetBorder(5);