Add note name parser to convert to midi note number
authorNil Geisweiller <ngeiswei@gmail.com>
Fri, 12 May 2017 18:27:56 +0000 (21:27 +0300)
committerRobin Gareus <robin@gareus.org>
Sun, 14 May 2017 16:13:07 +0000 (18:13 +0200)
Supports i18n, is case and whitespace insensitive for more resilent parsing.

libs/ardour/ardour/parameter_descriptor.h
libs/ardour/parameter_descriptor.cc

index 9a8c559d6e5c04049d965b44d8a3c3dc6e9f154f..978bd3d04260b8da8d30e546357dbe6af6ea1f98 100644 (file)
@@ -43,7 +43,13 @@ struct LIBARDOUR_API ParameterDescriptor : public Evoral::ParameterDescriptor
                HZ,         ///< Frequency in Hertz
        };
 
-       static std::string midi_note_name (uint8_t);
+       static std::string midi_note_name (uint8_t, bool translate=true);
+
+       /** Dual of midi_note_name, convert a note name into its midi note number. */
+       typedef std::map<std::string, uint8_t> NameNumMap;
+       static std::string normalize_note_name(const std::string& name);
+       static NameNumMap build_midi_name2num();
+       static uint8_t midi_note_num (const std::string& name);
 
        ParameterDescriptor(const Evoral::Parameter& parameter);
 
index 660abbc6161b801c20ef954fddf7dc4125761744..16c618dec62c2c1fede78f5c02e23a94ac609d5d 100644 (file)
@@ -17,6 +17,8 @@
     675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include <boost/algorithm/string.hpp>
+
 #include "ardour/amp.h"
 #include "ardour/dB.h"
 #include "ardour/parameter_descriptor.h"
@@ -190,7 +192,7 @@ ParameterDescriptor::update_steps()
 }
 
 std::string
-ParameterDescriptor::midi_note_name (const uint8_t b)
+ParameterDescriptor::midi_note_name (const uint8_t b, bool translate)
 {
        char buf[16];
        if (b > 127) {
@@ -198,6 +200,10 @@ ParameterDescriptor::midi_note_name (const uint8_t b)
                return buf;
        }
 
+       static const char* en_notes[] = {
+               "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"
+       };
+
        static const char* notes[] = {
                S_("Note|C"),
                S_("Note|C#"),
@@ -215,8 +221,40 @@ ParameterDescriptor::midi_note_name (const uint8_t b)
 
        /* MIDI note 0 is in octave -1 (in scientific pitch notation) */
        const int octave = b / 12 - 1;
-       snprintf (buf, sizeof (buf), "%s%d", notes[b % 12], octave);
+       const size_t p = b % 12;
+       snprintf (buf, sizeof (buf), "%s%d", translate ? notes[p] : en_notes[p], octave);
        return buf;
 }
 
+std::string
+ParameterDescriptor::normalize_note_name(const std::string& name)
+{
+       // Remove whitespaces and convert to lower case for a more resilient parser
+       return boost::to_lower_copy(boost::erase_all_copy(name, " "));
+};
+
+ParameterDescriptor::NameNumMap
+ParameterDescriptor::build_midi_name2num()
+{
+       NameNumMap name2num;
+       for (uint8_t num = 0; num < 128; num++) {
+               name2num[normalize_note_name(midi_note_name(num))] = num;
+       }
+       return name2num;
+}
+
+uint8_t
+ParameterDescriptor::midi_note_num (const std::string& name)
+{
+       static NameNumMap name2num = build_midi_name2num();
+
+       uint8_t num = -1;                       // -1 (or 255) is returned in case of failure
+
+       NameNumMap::const_iterator it = name2num.find(normalize_note_name(name));
+       if (it != name2num.end())
+               num = it->second;
+
+       return num;
+}
+
 } // namespace ARDOUR