Showing the changes to python (3 of 3 files). Show all
Unified · Split
| @@ -1,5 +1,6 @@ | |||
| 1 | import numpy | 1 | import numpy |
| 2 | from _aubio import * | 2 | from _aubio import * |
| 3 | from midiconv import * | ||
| 3 | 4 | ||
| 4 | class fvec(numpy.ndarray): | 5 | class fvec(numpy.ndarray): |
| 5 | 6 | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | # -*- encoding: utf8 -*- | ||
| 2 | |||
| 3 | def note2midi(note): | ||
| 4 | " convert a note name to a midi note value " | ||
| 5 | # from C-2 to G8, though we do accept everything in the upper octave | ||
| 6 | _valid_notenames = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11} | ||
| 7 | _valid_modifiers = {None: 0, u'♮': 0, '#': +1, u'♯': +1, u'\udd2a': +2, 'b': -1, u'♭': -1, u'\ufffd': -2} | ||
| 8 | _valid_octaves = range(-1, 10) | ||
| 9 | if not (1 < len(note) < 5): | ||
| 10 | raise ValueError, "string of 2 to 4 characters expected, got %d (%s)" % (len(note), note) | ||
| 11 | notename, modifier, octave = [None]*3 | ||
| 12 | |||
| 13 | if len(note) == 4: | ||
| 14 | notename, modifier, octave_sign, octave = note | ||
| 15 | octave = octave_sign + octave | ||
| 16 | elif len(note) == 3: | ||
| 17 | notename, modifier, octave = note | ||
| 18 | if modifier == '-': | ||
| 19 | octave = modifier + octave | ||
| 20 | modifier = None | ||
| 21 | else: | ||
| 22 | notename, octave = note | ||
| 23 | |||
| 24 | notename = notename.upper() | ||
| 25 | octave = int(octave) | ||
| 26 | |||
| 27 | if notename not in _valid_notenames: | ||
| 28 | raise ValueError, "%s is not a valid note name" % notename | ||
| 29 | if modifier not in _valid_modifiers: | ||
| 30 | raise ValueError, "only # and b are acceptable modifiers, not %s" % modifier | ||
| 31 | if octave not in _valid_octaves: | ||
| 32 | raise ValueError, "%s is not a valid octave" % octave | ||
| 33 | |||
| 34 | midi = 12 + octave * 12 + _valid_notenames[notename] + _valid_modifiers[modifier] | ||
| 35 | if midi > 127: | ||
| 36 | raise ValueError, "%s is outside of the range C-2 to G8" % note | ||
| 37 | return midi | ||
| @@ -0,0 +1,54 @@ | |||
| 1 | # -*- encoding: utf8 -*- | ||
| 2 | |||
| 3 | from aubio import note2midi | ||
| 4 | import unittest | ||
| 5 | |||
| 6 | list_of_known_notes = ( | ||
| 7 | ( 'C-1', 0 ), | ||
| 8 | ( 'C#-1', 1 ), | ||
| 9 | ( 'd2', 38 ), | ||
| 10 | ( 'C3', 48 ), | ||
| 11 | ( 'B3', 59 ), | ||
| 12 | ( 'B#3', 60 ), | ||
| 13 | ( 'A4', 69 ), | ||
| 14 | ( 'A#4', 70 ), | ||
| 15 | ( 'G8', 115 ), | ||
| 16 | ( u'G♯8', 116 ), | ||
| 17 | ( u'G♭9', 126 ), | ||
| 18 | ( 'G9', 127 ), | ||
| 19 | ( u'G\udd2a2', 45 ), | ||
| 20 | ( u'B\ufffd2', 45 ), | ||
| 21 | ( u'A♮2', 45 ), | ||
| 22 | ) | ||
| 23 | |||
| 24 | class TestNote2MidiGoodValues(unittest.TestCase): | ||
| 25 | |||
| 26 | def test_note2midi_known_values(self): | ||
| 27 | " known values are correctly converted " | ||
| 28 | for note, midi in list_of_known_notes: | ||
| 29 | self.assertEqual ( note2midi(note), midi ) | ||
| 30 | |||
| 31 | class TestNote2MidiWrongValues(unittest.TestCase): | ||
| 32 | |||
| 33 | def test_note2midi_missing_octave(self): | ||
| 34 | " fails when passed only one character" | ||
| 35 | self.assertRaises(ValueError, note2midi, 'C') | ||
| 36 | |||
| 37 | def test_note2midi_wrong_modifier(self): | ||
| 38 | " fails when passed an invalid note name" | ||
| 39 | self.assertRaises(ValueError, note2midi, 'C.1') | ||
| 40 | |||
| 41 | def test_note2midi_wronge_midifier_again(self): | ||
| 42 | " fails when passed a wrong modifier" | ||
| 43 | self.assertRaises(ValueError, note2midi, 'CB-3') | ||
| 44 | |||
| 45 | def test_note2midi_wrong_octave(self): | ||
| 46 | " fails when passed a wrong octave" | ||
| 47 | self.assertRaises(ValueError, note2midi, 'CBc') | ||
| 48 | |||
| 49 | def test_note2midi_out_of_range(self): | ||
| 50 | " fails when passed a non-existing note" | ||
| 51 | self.assertRaises(ValueError, note2midi, 'A9') | ||
| 52 | |||
| 53 | if __name__ == '__main__': | ||
| 54 | unittest.main() | ||