ref: 3aad0b1b1ba6dd4b88b4905e78bc80da83ee23b8
parent: d554321c6c3b7648bbf4e44e35c55999683ea74e
author: Paul Brossier <piem@piem.org>
date: Fri Dec 2 23:03:47 EST 2016
python/lib/aubio/midiconv.py: improve unicode handling, skip UnicodeEncodeError on python 2.x
--- a/python/lib/aubio/midiconv.py
+++ b/python/lib/aubio/midiconv.py
@@ -15,11 +15,13 @@
def note2midi(note):
" convert note name to midi note number, e.g. [C-1, G9] -> [0, 127] "
_valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
- _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2,
- u'\U0001D12A': +2,
- 'b': -1, u'♭': -1, u'\ufffd': -2,
- u'\U0001D12B': -2,
- }
+ _valid_modifiers = {
+ u'𝄫': -2, # double flat
+ u'♭': -1, 'b': -1, '\u266d': -1, # simple flat
+ u'♮': 0, '\u266e': 0, None: 0, # natural
+ '#': +1, u'♯': +1, '\u266f': +1, # sharp
+ u'𝄪': +2, # double sharp
+ }
_valid_octaves = range(-1, 10)
if not isinstance(note, str_instances):
raise TypeError("a string is required, got %s (%s)" % (note, str(type(note))))
--- a/python/tests/test_note2midi.py
+++ b/python/tests/test_note2midi.py
@@ -14,21 +14,36 @@
( 'C3', 48 ),
( 'B3', 59 ),
( 'B#3', 60 ),
- ( 'C\u266f4', 61 ),
- ( 'C\U0001D12A4', 62 ),
- ( 'E\U0001D12B4', 62 ),
+ ( 'C♯4', 61 ),
( 'A4', 69 ),
( 'A#4', 70 ),
+ ( 'A♯4', 70 ),
+ ( 'A\u266f4', 70 ),
( 'Bb4', 70 ),
( 'B♭4', 70 ),
+ ( 'B\u266d4', 70 ),
( 'G8', 115 ),
( 'G♯8', 116 ),
( 'G9', 127 ),
- ( 'G\udd2a2', 45 ),
- ( 'B\ufffd2', 45 ),
( 'A♮2', 45 ),
)
+list_of_known_notes_with_unicode_issues = (
+ ('C𝄪4', 62 ),
+ ('E𝄫4', 62 ),
+ )
+
+list_of_unknown_notes = (
+ ( 'G\udd2a2' ),
+ ( 'B\ufffd2' ),
+ ( 'B\u266e\u266e2' ),
+ ( 'B\u266f\u266d3' ),
+ ( 'B33' ),
+ ( 'C.3' ),
+ ( 'A' ),
+ ( '2' ),
+ )
+
class note2midi_good_values(unittest.TestCase):
@params(*list_of_known_notes)
@@ -36,6 +51,21 @@
" known values are correctly converted "
self.assertEqual ( note2midi(note), midi )
+ @params(*list_of_known_notes_with_unicode_issues)
+ def test_note2midi_known_values_with_unicode_issues(self, note, midi):
+ " known values are correctly converted, unless decoding is expected to fail"
+ try:
+ self.assertEqual ( note2midi(note), midi )
+ except UnicodeEncodeError as e:
+ import sys
+ strfmt = "len(u'\\U0001D12A') != 1, excpected decoding failure | {:s} | {:s} {:s}"
+ strres = strfmt.format(e, sys.platform, sys.version)
+ # happens with: darwin 2.7.10, windows 2.7.12
+ if len('\U0001D12A') != 1 and sys.version[0] == '2':
+ self.skipTest(strres + " | upgrade to Python 3 to fix")
+ else:
+ raise
+
class note2midi_wrong_values(unittest.TestCase):
def test_note2midi_missing_octave(self):
@@ -70,6 +100,14 @@
" fails when passed a non-string value "
self.assertRaises(TypeError, note2midi, 123)
+ def test_note2midi_wrong_data_too_long(self):
+ " fails when passed a note with a note name longer than expected"
+ self.assertRaises(ValueError, note2midi, 'CB+-3')
+
+ @params(*list_of_unknown_notes)
+ def test_note2midi_unknown_values(self, note):
+ " unknown values throw out an error "
+ self.assertRaises(ValueError, note2midi, note)
class freq2note_simple_test(unittest.TestCase):