1 | #! /usr/bin/env python |
---|
2 | # -*- coding: utf-8 -*- |
---|
3 | |
---|
4 | from __future__ import unicode_literals |
---|
5 | |
---|
6 | from aubio import note2midi, freq2note, note2freq, float_type |
---|
7 | from nose2.tools import params |
---|
8 | import unittest |
---|
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 ), |
---|
17 | ( 'C♯4', 61 ), |
---|
18 | ( 'A4', 69 ), |
---|
19 | ( 'A#4', 70 ), |
---|
20 | ( 'A♯4', 70 ), |
---|
21 | ( 'A\u266f4', 70 ), |
---|
22 | ( 'Bb4', 70 ), |
---|
23 | ( 'B♭4', 70 ), |
---|
24 | ( 'B\u266d4', 70 ), |
---|
25 | ( 'G8', 115 ), |
---|
26 | ( 'G♯8', 116 ), |
---|
27 | ( 'G9', 127 ), |
---|
28 | ( 'A♮2', 45 ), |
---|
29 | ) |
---|
30 | |
---|
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 | |
---|
47 | class note2midi_good_values(unittest.TestCase): |
---|
48 | |
---|
49 | @params(*list_of_known_notes) |
---|
50 | def test_note2midi_known_values(self, note, midi): |
---|
51 | " known values are correctly converted " |
---|
52 | self.assertEqual ( note2midi(note), midi ) |
---|
53 | |
---|
54 | @params(*list_of_known_notes_with_unicode_issues) |
---|
55 | def test_note2midi_known_values_with_unicode_issues(self, note, midi): |
---|
56 | " known values are correctly converted, unless decoding is expected to fail" |
---|
57 | try: |
---|
58 | self.assertEqual ( note2midi(note), midi ) |
---|
59 | except UnicodeEncodeError as e: |
---|
60 | import sys |
---|
61 | strfmt = "len(u'\\U0001D12A') != 1, excpected decoding failure | {:s} | {:s} {:s}" |
---|
62 | strres = strfmt.format(e, sys.platform, sys.version) |
---|
63 | # happens with: darwin 2.7.10, windows 2.7.12 |
---|
64 | if len('\U0001D12A') != 1 and sys.version[0] == '2': |
---|
65 | self.skipTest(strres + " | upgrade to Python 3 to fix") |
---|
66 | else: |
---|
67 | raise |
---|
68 | |
---|
69 | class note2midi_wrong_values(unittest.TestCase): |
---|
70 | |
---|
71 | def test_note2midi_missing_octave(self): |
---|
72 | " fails when passed only one character" |
---|
73 | self.assertRaises(ValueError, note2midi, 'C') |
---|
74 | |
---|
75 | def test_note2midi_wrong_modifier(self): |
---|
76 | " fails when passed a note with an invalid modifier " |
---|
77 | self.assertRaises(ValueError, note2midi, 'C.1') |
---|
78 | |
---|
79 | def test_note2midi_another_wrong_modifier_again(self): |
---|
80 | " fails when passed a note with a invalid note name " |
---|
81 | self.assertRaises(ValueError, note2midi, 'CB-3') |
---|
82 | |
---|
83 | def test_note2midi_wrong_octave(self): |
---|
84 | " fails when passed a wrong octave number " |
---|
85 | self.assertRaises(ValueError, note2midi, 'CBc') |
---|
86 | |
---|
87 | def test_note2midi_out_of_range(self): |
---|
88 | " fails when passed a note out of range" |
---|
89 | self.assertRaises(ValueError, note2midi, 'A9') |
---|
90 | |
---|
91 | def test_note2midi_wrong_note_name(self): |
---|
92 | " fails when passed a note with a wrong name" |
---|
93 | self.assertRaises(ValueError, note2midi, 'W9') |
---|
94 | |
---|
95 | def test_note2midi_low_octave(self): |
---|
96 | " fails when passed a note with a too low octave" |
---|
97 | self.assertRaises(ValueError, note2midi, 'C-9') |
---|
98 | |
---|
99 | def test_note2midi_wrong_data_type(self): |
---|
100 | " fails when passed a non-string value " |
---|
101 | self.assertRaises(TypeError, note2midi, 123) |
---|
102 | |
---|
103 | def test_note2midi_wrong_data_too_long(self): |
---|
104 | " fails when passed a note with a note name longer than expected" |
---|
105 | self.assertRaises(ValueError, note2midi, 'CB+-3') |
---|
106 | |
---|
107 | @params(*list_of_unknown_notes) |
---|
108 | def test_note2midi_unknown_values(self, note): |
---|
109 | " unknown values throw out an error " |
---|
110 | self.assertRaises(ValueError, note2midi, note) |
---|
111 | |
---|
112 | class freq2note_simple_test(unittest.TestCase): |
---|
113 | |
---|
114 | def test_freq2note_above(self): |
---|
115 | " make sure freq2note(441) == A4 " |
---|
116 | self.assertEqual("A4", freq2note(441)) |
---|
117 | |
---|
118 | def test_freq2note_under(self): |
---|
119 | " make sure freq2note(439) == A4 " |
---|
120 | self.assertEqual("A4", freq2note(439)) |
---|
121 | |
---|
122 | class note2freq_simple_test(unittest.TestCase): |
---|
123 | |
---|
124 | def test_note2freq(self): |
---|
125 | " make sure note2freq('A3') == 220" |
---|
126 | self.assertEqual(220, note2freq("A3")) |
---|
127 | |
---|
128 | def test_note2freq_under(self): |
---|
129 | " make sure note2freq(A4) == 440" |
---|
130 | if float_type == 'float32': |
---|
131 | self.assertEqual(440, note2freq("A4")) |
---|
132 | else: |
---|
133 | self.assertLess(abs(note2freq("A4")-440), 1.e-12) |
---|
134 | |
---|
135 | if __name__ == '__main__': |
---|
136 | import nose2 |
---|
137 | nose2.main() |
---|