[7d89e61] | 1 | #! /usr/bin/env python |
---|
| 2 | # -*- coding: utf-8 -*- |
---|
[33102ab] | 3 | |
---|
[9b7f238] | 4 | from __future__ import unicode_literals |
---|
| 5 | |
---|
[27ed546] | 6 | from aubio import note2midi, freq2note, note2freq, float_type |
---|
[86deeed] | 7 | from numpy.testing import TestCase |
---|
[00fcc5d] | 8 | from _tools import parametrize, assert_raises, skipTest |
---|
[33102ab] | 9 | |
---|
| 10 | list_of_known_notes = ( |
---|
| 11 | ( 'C-1', 0 ), |
---|
| 12 | ( 'C#-1', 1 ), |
---|
| 13 | ( 'd2', 38 ), |
---|
| 14 | ( 'C3', 48 ), |
---|
| 15 | ( 'B3', 59 ), |
---|
| 16 | ( 'B#3', 60 ), |
---|
[3aad0b1] | 17 | ( 'C♯4', 61 ), |
---|
[33102ab] | 18 | ( 'A4', 69 ), |
---|
| 19 | ( 'A#4', 70 ), |
---|
[3aad0b1] | 20 | ( 'A♯4', 70 ), |
---|
| 21 | ( 'A\u266f4', 70 ), |
---|
[f552e9e] | 22 | ( 'Bb4', 70 ), |
---|
[9b7f238] | 23 | ( 'B♭4', 70 ), |
---|
[3aad0b1] | 24 | ( 'B\u266d4', 70 ), |
---|
[33102ab] | 25 | ( 'G8', 115 ), |
---|
[9b7f238] | 26 | ( 'G♯8', 116 ), |
---|
[33102ab] | 27 | ( 'G9', 127 ), |
---|
[9b7f238] | 28 | ( 'A♮2', 45 ), |
---|
[33102ab] | 29 | ) |
---|
| 30 | |
---|
[3aad0b1] | 31 | list_of_known_notes_with_unicode_issues = ( |
---|
| 32 | ('C𝄪4', 62 ), |
---|
| 33 | ('E𝄫4', 62 ), |
---|
| 34 | ) |
---|
| 35 | |
---|
| 36 | list_of_unknown_notes = ( |
---|
| 37 | ( 'G\udd2a2' ), |
---|
| 38 | ( 'B\ufffd2' ), |
---|
| 39 | ( 'B\u266e\u266e2' ), |
---|
| 40 | ( 'B\u266f\u266d3' ), |
---|
| 41 | ( 'B33' ), |
---|
| 42 | ( 'C.3' ), |
---|
| 43 | ( 'A' ), |
---|
| 44 | ( '2' ), |
---|
| 45 | ) |
---|
| 46 | |
---|
[8607a74] | 47 | class Test_note2midi_good_values(object): |
---|
[33102ab] | 48 | |
---|
[86deeed] | 49 | @parametrize('note, midi', list_of_known_notes) |
---|
[d554321] | 50 | def test_note2midi_known_values(self, note, midi): |
---|
[33102ab] | 51 | " known values are correctly converted " |
---|
[86deeed] | 52 | assert note2midi(note) == midi |
---|
[33102ab] | 53 | |
---|
[86deeed] | 54 | @parametrize('note, midi', list_of_known_notes_with_unicode_issues) |
---|
[3aad0b1] | 55 | def test_note2midi_known_values_with_unicode_issues(self, note, midi): |
---|
[00fcc5d] | 56 | " difficult values are correctly converted unless expected failure " |
---|
[3aad0b1] | 57 | try: |
---|
[86deeed] | 58 | assert note2midi(note) == midi |
---|
[3aad0b1] | 59 | except UnicodeEncodeError as e: |
---|
[00fcc5d] | 60 | # platforms with decoding failures include: |
---|
| 61 | # - osx: python <= 2.7.10 |
---|
| 62 | # - win: python <= 2.7.12 |
---|
[3aad0b1] | 63 | import sys |
---|
[00fcc5d] | 64 | strmsg = "len(u'\\U0001D12A') != 1, expected decoding failure" |
---|
| 65 | strmsg += " | upgrade to Python 3 to fix" |
---|
| 66 | strmsg += " | {:s} | {:s} {:s}" |
---|
[3aad0b1] | 67 | if len('\U0001D12A') != 1 and sys.version[0] == '2': |
---|
[00fcc5d] | 68 | skipTest(strmsg.format(repr(e), sys.platform, sys.version)) |
---|
[3aad0b1] | 69 | else: |
---|
| 70 | raise |
---|
| 71 | |
---|
[86deeed] | 72 | class note2midi_wrong_values(TestCase): |
---|
[33102ab] | 73 | |
---|
| 74 | def test_note2midi_missing_octave(self): |
---|
| 75 | " fails when passed only one character" |
---|
| 76 | self.assertRaises(ValueError, note2midi, 'C') |
---|
| 77 | |
---|
| 78 | def test_note2midi_wrong_modifier(self): |
---|
[f552e9e] | 79 | " fails when passed a note with an invalid modifier " |
---|
[33102ab] | 80 | self.assertRaises(ValueError, note2midi, 'C.1') |
---|
| 81 | |
---|
[f552e9e] | 82 | def test_note2midi_another_wrong_modifier_again(self): |
---|
| 83 | " fails when passed a note with a invalid note name " |
---|
[33102ab] | 84 | self.assertRaises(ValueError, note2midi, 'CB-3') |
---|
| 85 | |
---|
| 86 | def test_note2midi_wrong_octave(self): |
---|
[f552e9e] | 87 | " fails when passed a wrong octave number " |
---|
[33102ab] | 88 | self.assertRaises(ValueError, note2midi, 'CBc') |
---|
| 89 | |
---|
| 90 | def test_note2midi_out_of_range(self): |
---|
[6db7600] | 91 | " fails when passed a note out of range" |
---|
[33102ab] | 92 | self.assertRaises(ValueError, note2midi, 'A9') |
---|
| 93 | |
---|
[6db7600] | 94 | def test_note2midi_wrong_note_name(self): |
---|
| 95 | " fails when passed a note with a wrong name" |
---|
| 96 | self.assertRaises(ValueError, note2midi, 'W9') |
---|
| 97 | |
---|
[0b6d23d] | 98 | def test_note2midi_low_octave(self): |
---|
| 99 | " fails when passed a note with a too low octave" |
---|
[6db7600] | 100 | self.assertRaises(ValueError, note2midi, 'C-9') |
---|
| 101 | |
---|
[f552e9e] | 102 | def test_note2midi_wrong_data_type(self): |
---|
| 103 | " fails when passed a non-string value " |
---|
| 104 | self.assertRaises(TypeError, note2midi, 123) |
---|
| 105 | |
---|
[3aad0b1] | 106 | def test_note2midi_wrong_data_too_long(self): |
---|
| 107 | " fails when passed a note with a note name longer than expected" |
---|
| 108 | self.assertRaises(ValueError, note2midi, 'CB+-3') |
---|
| 109 | |
---|
[8607a74] | 110 | class Test_note2midi_unknown_values(object): |
---|
[86deeed] | 111 | |
---|
| 112 | @parametrize('note', list_of_unknown_notes) |
---|
[3aad0b1] | 113 | def test_note2midi_unknown_values(self, note): |
---|
| 114 | " unknown values throw out an error " |
---|
[86deeed] | 115 | assert_raises(ValueError, note2midi, note) |
---|
[6db7600] | 116 | |
---|
[86deeed] | 117 | class freq2note_simple_test(TestCase): |
---|
[6db7600] | 118 | |
---|
[4afeac2] | 119 | def test_freq2note_above(self): |
---|
[6db7600] | 120 | " make sure freq2note(441) == A4 " |
---|
[376d5e9] | 121 | self.assertEqual("A4", freq2note(441)) |
---|
[6db7600] | 122 | |
---|
[4afeac2] | 123 | def test_freq2note_under(self): |
---|
| 124 | " make sure freq2note(439) == A4 " |
---|
| 125 | self.assertEqual("A4", freq2note(439)) |
---|
| 126 | |
---|
[86deeed] | 127 | class note2freq_simple_test(TestCase): |
---|
[e9a4402] | 128 | |
---|
| 129 | def test_note2freq(self): |
---|
| 130 | " make sure note2freq('A3') == 220" |
---|
| 131 | self.assertEqual(220, note2freq("A3")) |
---|
| 132 | |
---|
| 133 | def test_note2freq_under(self): |
---|
| 134 | " make sure note2freq(A4) == 440" |
---|
[27ed546] | 135 | if float_type == 'float32': |
---|
| 136 | self.assertEqual(440, note2freq("A4")) |
---|
| 137 | else: |
---|
| 138 | self.assertLess(abs(note2freq("A4")-440), 1.e-12) |
---|
[e9a4402] | 139 | |
---|
[33102ab] | 140 | if __name__ == '__main__': |
---|
[7fd92ca] | 141 | from _tools import run_module_suite |
---|
| 142 | run_module_suite() |
---|