lygre 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,222 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'spec_helper'
4
+
5
+ # the GabcParser is described through the file format
6
+ # it should be able to parse
7
+ describe 'gabc' do
8
+
9
+ describe 'valid gabc file must contain a header delimiter' do
10
+
11
+ it 'file with just the header delimiter is valid' do
12
+ "%%\n".should compile
13
+ end
14
+
15
+ it 'file without header delimiter is invalid' do
16
+ src = ""
17
+ src.should_not compile
18
+ end
19
+ end
20
+
21
+ describe 'header contains' do
22
+
23
+ describe 'whitespace' do
24
+ it '- any number of empty lines' do
25
+ src = "\n\n\n\n%%\n"
26
+ src.should compile
27
+ end
28
+
29
+ it '- spaces and tabs' do
30
+ src = " \n\t\n%%\n"
31
+ src.should compile
32
+ end
33
+ end
34
+
35
+ describe 'header fields' do
36
+ it '- e.g. "name"' do
37
+ src = "name: incipit;\n%%\n"
38
+ src.should compile
39
+ end
40
+
41
+ it 'whose identifiers may include dashes' do
42
+ src = "office-part: introitus/...;\n%%\n"
43
+ src.should compile
44
+ end
45
+
46
+ it '- a lot of them' do
47
+ src = load_example 'header.gabc'
48
+ src.should compile
49
+ end
50
+ end
51
+
52
+ describe 'comments' do
53
+ it ', which may occupy a whole line' do
54
+ src = "% comment\n%%\n"
55
+ src.should compile
56
+ end
57
+
58
+ it 'following whitespace' do
59
+ src = " % comm' comm' comment\n%%\n"
60
+ src.should compile
61
+ end
62
+
63
+ it 'following header fields' do
64
+ src = "name: incipit; % what a beautiful name!\n%%\n"
65
+ src.should compile
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ describe 'body contains' do
72
+
73
+ describe 'whitespace' do
74
+ it '- any number of empty lines' do
75
+ "%%\n\n\n\n\n".should compile
76
+ end
77
+
78
+ it '- spaces and tabs' do
79
+ "%%\n \n\t\n".should compile
80
+ end
81
+ end
82
+
83
+ describe 'clef' do
84
+ it 'c clef on the 3rd line' do
85
+ "%%\n(c3)".should compile
86
+ end
87
+
88
+ it 'c clef on the 1st line' do
89
+ "%%\n(c1)".should compile
90
+ end
91
+
92
+ it 'c clef with bemol' do
93
+ "%%\n(cb3)".should compile
94
+ end
95
+
96
+ it 'f clef on the 3rd line' do
97
+ "%%\n(f3)".should compile
98
+ end
99
+ end
100
+
101
+ describe 'music' do
102
+ it 'some simple notes' do
103
+ "%%\n(a) (h) (g) ".should compile
104
+ end
105
+
106
+ it 'all possible notes' do
107
+ "%%\n (a) (b) (c) (d) (e) (f) (g) (h) (i) (j) (k) (l) (m)".should compile
108
+ end
109
+
110
+ it 'empty music chunk is also valid' do
111
+ "%%\n ()".should compile
112
+ end
113
+
114
+ describe 'one-note neumes without and with shape modifiers' do
115
+ it { "%%\n (g)".should compile }
116
+ it { "%%\n (G) (G~) (G>)".should compile }
117
+ it { "%%\n (g~) (g<) (g>)".should compile }
118
+ it { "%%\n (go) (go~) (go<)".should compile }
119
+ it { "%%\n (gw) (gv) (gs) (gs<)".should compile }
120
+ it { "%%\n (-f)".should compile }
121
+ it { "%%\n (gqi)".should compile }
122
+ it { "%%\n (gWi)".should compile }
123
+ it { "%%\n (gr) (gR) (gr0)".should compile }
124
+ end
125
+
126
+ describe 'repetitions' do
127
+ it { "%%\n (gvv)".should compile }
128
+ it { "%%\n (gsss)".should compile }
129
+ end
130
+
131
+ describe 'rhythmic signs' do
132
+ it { "%%\n (g.)".should compile }
133
+ it { "%%\n (g..)".should compile }
134
+ it { "%%\n (g_)".should compile }
135
+ it { "%%\n (g')".should compile }
136
+ it { "%%\n (g_0)".should compile }
137
+ it { "%%\n (g__0)".should compile }
138
+ it { "%%\n (g_')".should compile }
139
+ it { "%%\n (g_h_)".should compile }
140
+ end
141
+
142
+ describe 'accents' do
143
+ it { "%%\n (gr1)".should compile }
144
+ it { "%%\n (gr0r1)".should compile } # linea punctum cavum + accent
145
+ it { "%%\n (gr2) (gr3) (gr4) (gr5)".should compile }
146
+ end
147
+
148
+ describe 'composed neumes' do
149
+ it { "%%\n (ghg)".should compile }
150
+ it { "%%\n (hvGFE)".should compile }
151
+ it { "%%\n (hghe)".should compile }
152
+ end
153
+
154
+ describe 'alterations' do
155
+ it { "%%\n (gxg)".should compile }
156
+ it { "%%\n (gyg)".should compile }
157
+ it { "%%\n (g#g)".should compile }
158
+ end
159
+
160
+ describe 'spaces' do
161
+ it { "%%\n (h/h)".should compile }
162
+ it { "%%\n (h//h)".should compile }
163
+ it { "%%\n (h h)".should compile }
164
+ it 'unbreakable space' do
165
+ "%%\n (h! h)".should compile
166
+ end
167
+ it 'prevent note linking' do
168
+ "%%\n (gh!i)".should compile
169
+ end
170
+ end
171
+
172
+ describe 'divisiones' do
173
+ it { "%%\n (,) (`) (;) (:) (::)".should compile }
174
+ it { "%%\n (;1) (;2) (;3) (;4) (;5) (;6)".should compile }
175
+ it { "%%\n (:') (,_)".should compile }
176
+ end
177
+
178
+ describe 'forced line-breaks' do
179
+ it { "%%\n (ez)".should compile }
180
+ it { "%%\n (eZ)".should compile }
181
+ end
182
+
183
+ describe 'custos, guide' do
184
+ it { "%%\n (z0)".should compile }
185
+ it { "%%\n (h) (g) (::) (h+)".should compile }
186
+ end
187
+
188
+ describe 'choral signs' do
189
+ it { "%%\n (g[cs:sign]h)".should compile }
190
+ end
191
+
192
+ describe 'braces' do
193
+ it { "%%\n (g[ob:1;6mm])".should compile }
194
+ it { "%%\n (g[ob:0;7mm])".should compile }
195
+ it { "%%\n (g[ocb:1;6mm])".should compile }
196
+ it { "%%\n (g[ocba:1;6mm])".should compile }
197
+ end
198
+
199
+ describe 'real-life examples that once failed' do
200
+ it { "%%\n ad(IV./hig)".should compile }
201
+ end
202
+ end
203
+
204
+ describe 'lyrics' do
205
+ it 'simple word with simple notes' do
206
+ "%%\n or(h)bis(h)".should compile
207
+ end
208
+
209
+ describe 'special characters' do
210
+ it { "%%\n <sp>R/</sp>() re(g)spon(f)sum(e)".should compile }
211
+ it { "%%\n tu(h)<sp>'ae</sp>(h)".should compile }
212
+ end
213
+
214
+ describe 'formatting' do
215
+ it { "%%\n <b>tu</b>(h)ae(h)".should compile }
216
+ it { "%%\n po(h)<i>pu</i>(h)<i>li</i>(h)".should compile }
217
+ it { "%%\n <sc>can. i</sc>()".should compile }
218
+ end
219
+ end
220
+
221
+ end
222
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GabcParser do
6
+
7
+ before :each do
8
+ # beginning of the Populus Sion example
9
+ @src = "name: Populus Sion;\n%%\n
10
+ (c3) Pó(eh/hi)pu(h)lus(h) Si(hi)on,(hgh.) *(;)
11
+ ec(hihi)ce(e.) Dó(e.f!gwh/hi)mi(h)nus(h) vé(hi)ni(ig/ih)et.(h.) (::)"
12
+ @parser = GabcParser.new
13
+ end
14
+
15
+ describe '#parse' do
16
+ it 'returns ScoreNode' do
17
+ @parser.parse(@src).should be_kind_of Gabc::ScoreNode
18
+ end
19
+ end
20
+
21
+ describe 'lyrics_syllable rule' do
22
+ it 'does not accept space' do
23
+ @parser.parse(' ', root: :lyrics_syllable).should be_nil
24
+ end
25
+
26
+ it 'does not accept string beginning with space' do
27
+ @parser.parse(' aa', root: :lyrics_syllable).should be_nil
28
+ end
29
+
30
+ it 'accepts ascii characters' do
31
+ @parser.parse('aa', root: :lyrics_syllable).should be_true
32
+ end
33
+
34
+ it 'accepts characters with accents' do
35
+ @parser.parse('áéíóúý', root: :lyrics_syllable).should be_true
36
+ end
37
+ end
38
+
39
+ describe 'regular_word_character rule' do
40
+ it 'does not accept space' do
41
+ @parser.parse(' ', root: :regular_word_character).should be_nil
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: UTF-8
2
+
3
+ describe GabcPitchReader do
4
+
5
+ describe '.new' do
6
+ it 'takes clef type and position' do
7
+ pr = GabcPitchReader.new(:c, 3)
8
+ pr.clef.should eq :c
9
+ pr.clef_position.should eq 3
10
+
11
+ pr = GabcPitchReader.new(:f, 3)
12
+ pr.clef.should eq :f
13
+ end
14
+ end
15
+
16
+ describe '#base returns absolute pitch of the lowest writable note (a)' do
17
+ #it { GabcPitchReader.new(:c, 4).base.should eq NoteFactory["a"] }
18
+ #it { GabcPitchReader.new(:f, 2).base.should eq NoteFactory["a"] }
19
+
20
+ #it { GabcPitchReader.new(:c, 1).base.should eq NoteFactory["g'"] }
21
+ #it { GabcPitchReader.new(:f, 1).base.should eq NoteFactory["c'"] }
22
+ end
23
+ end
24
+
25
+ describe NoteFactory do
26
+
27
+ before :all do
28
+ @f = NoteFactory
29
+ end
30
+
31
+ describe '.create' do
32
+ it { @f.create("c'").value.should eq 60 }
33
+ it { @f.create("c''").value.should eq 72 }
34
+ it { @f.create("c'''").value.should eq 84 }
35
+
36
+ it { @f.create("c").value.should eq 48 }
37
+ it { @f.create("c,").value.should eq 36 }
38
+ it { @f.create("c,,").value.should eq 24 }
39
+
40
+ it { @f.create("c").value.should eq 48 }
41
+ it { @f.create("d").value.should eq 50 }
42
+ it { @f.create("e").value.should eq 52 }
43
+ it { @f.create("f").value.should eq 53 }
44
+ it { @f.create("g").value.should eq 55 }
45
+ it { @f.create("a").value.should eq 57 }
46
+ it { @f.create("b").value.should eq 59 }
47
+
48
+ it { expect { @f.create("x") }.to raise_exception ArgumentError }
49
+ it { expect { @f.create("c*") }.to raise_exception ArgumentError }
50
+ end
51
+
52
+ describe '.lily_abs_pitch' do
53
+ it 'operates exactly reverse to .create' do
54
+ %w{ c d g c' f' a' b' g'' d''' c, c,, c,,, d, e, e,, b, }.each do |lypitch|
55
+ @f.lily_abs_pitch(@f[lypitch]).should eq lypitch
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '[]' do
61
+ it { @f["c'"].value.should eq 60 }
62
+ it { @f["c''"].value.should eq 72 }
63
+ end
64
+ end
65
+
66
+ describe 'monkey-patched RBMusicTheory' do
67
+
68
+ before :each do
69
+ @f = NoteFactory
70
+ @s = @f["c''"].major_scale
71
+ end
72
+
73
+ describe 'Note#diatonic_steps' do
74
+ it { @f["c'"].diatonic_steps(1).should eq @f["d'"] }
75
+ it { @f["c'"].diatonic_steps(0).should eq @f["c'"] }
76
+ it { @f["c'"].diatonic_steps(7).should eq @f["c''"] }
77
+ it { @f["c'"].diatonic_steps(8).should eq @f["d''"] }
78
+ it { @f["c'"].diatonic_steps(-2).should eq @f["a"] }
79
+ it { @f["c''"].diatonic_steps(-9).should eq @f["a"] }
80
+ it { @f["c'''"].diatonic_steps(-9).should eq @f["a'"] }
81
+ it { @f["c,"].diatonic_steps(-9).should eq @f["a,,,"] }
82
+ it { @f["c,"].diatonic_steps(-10).should eq @f["g,,,"] }
83
+ end
84
+
85
+ describe 'Note#degree_in' do
86
+ it { @f["c''"].degree_in(@s).should eq 1 }
87
+ it { @f["d''"].degree_in(@s).should eq 2 }
88
+
89
+ it { @f["c'''"].degree_in(@s).should eq 8 }
90
+ it { @f["e'''"].degree_in(@s).should eq 10 }
91
+ it { @f["b'"].degree_in(@s).should eq 0 }
92
+ it { @f["a'"].degree_in(@s).should eq -1 }
93
+ it { @f["a"].degree_in(@s).should eq -8 }
94
+
95
+ it 'behaves consistently with Scale#degree' do
96
+ [2, 8, -1, -12].each do |deg|
97
+ @s.degree(deg).degree_in(@s).should eq deg
98
+ end
99
+ end
100
+ end
101
+
102
+ describe 'Scale#degree' do
103
+ describe 'for positive degrees it behaves as expected' do
104
+ it { @s.degree(1).should eq @f["c''"] }
105
+ it { @s.degree(2).should eq @f["d''"] }
106
+ it { @s.degree(8).should eq @f["c'''"] }
107
+ end
108
+
109
+ describe 'and then there is zero and negative numbers' do
110
+ it { @s.degree(0).should eq @f["b'"] }
111
+ it { @s.degree(-1).should eq @f["a'"] }
112
+ it { @s.degree(-8).should eq @f["a"] }
113
+ it { @s.degree(-15).should eq @f["a,"] }
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,143 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'spec_helper'
4
+
5
+ # GabcScore is the parsing result returned by GabcParser
6
+
7
+ describe GabcScore do
8
+
9
+ before :each do
10
+ # beginning of the Populus Sion example
11
+ @src = "name: Populus Sion;\n%%\n
12
+ (c3) Pó(eh/hi)pu(h)lus(h) Si(hi)on,(hgh.) *(;)
13
+ ec(hihi)ce(e.) Dó(e.f!gwh/hi)mi(h)nus(h) vé(hi)ni(ig/ih)et.(h.) (::)"
14
+ @parser = GabcParser.new
15
+ end
16
+
17
+ describe 'creation' do
18
+ it 'is returned by ScoreNode#create_score' do
19
+ @parser.parse(@src).create_score.should be_a GabcScore
20
+ end
21
+ end
22
+
23
+ describe '#header' do
24
+ before :each do
25
+ @score = @parser.parse(@src).create_score
26
+ end
27
+
28
+ it 'is a Hash' do
29
+ @score.header.should be_kind_of Hash
30
+ end
31
+
32
+ it 'contains the field specified in the score' do
33
+ @score.header.should have_key 'name'
34
+ end
35
+
36
+ it 'contains the field value' do
37
+ @score.header['name'].should eq 'Populus Sion'
38
+ end
39
+
40
+ it 'may be empty' do
41
+ src = "%%\n"
42
+ score = @parser.parse(src).create_score
43
+ score.header.should be_empty
44
+ end
45
+ end
46
+
47
+ describe '#music' do
48
+ before :each do
49
+ @score = @parser.parse(@src).create_score
50
+ end
51
+
52
+ it 'is GabcMusic' do
53
+ @score.music.should be_kind_of GabcMusic
54
+ end
55
+ end
56
+ end
57
+
58
+ describe GabcMusic do
59
+
60
+ before :each do
61
+ # beginning of the Populus Sion example
62
+ @src = "name: Populus Sion;\n%%\n
63
+ (c3) Pó(eh/hi)pu(h)lus(h) Si(hi)on,(hgh.) *(;)
64
+ ec(hihi)ce(e.) Dó(e.f!gwh/hi)mi(h)nus(h) vé(hi)ni(ig/ih)et.(h.) (::)"
65
+ @parser = GabcParser.new
66
+ @music = @parser.parse(@src).create_score.music
67
+ end
68
+
69
+ describe '#clef' do
70
+ subject { @music.clef }
71
+ it { should be_a GabcClef }
72
+ end
73
+
74
+ describe '#words' do
75
+ subject { @music.words }
76
+ it { should be_a Array }
77
+ it { should_not be_empty }
78
+ it { should contain_a GabcWord }
79
+ end
80
+ end
81
+
82
+ describe GabcClef do
83
+
84
+ before :each do
85
+ # beginning of the Populus Sion example
86
+ @src = "name: Populus Sion;\n%%\n
87
+ (c3) Pó(eh/hi)pu(h)lus(h) Si(hi)on,(hgh.) *(;)
88
+ ec(hihi)ce(e.) Dó(e.f!gwh/hi)mi(h)nus(h) vé(hi)ni(ig/ih)et.(h.) (::)"
89
+ @parser = GabcParser.new
90
+ @music = @parser.parse(@src).create_score.music
91
+ @clef = @music.clef
92
+ end
93
+
94
+ it 'should return key from the score' do
95
+ @clef.to_s.should eq 'c3'
96
+ end
97
+
98
+ it 'has no bemol' do
99
+ @clef.bemol.should be_false
100
+ end
101
+
102
+ describe 'has bemol' do
103
+ before :each do
104
+ src = "%%\n(cb3)"
105
+ @music = @parser.parse(src).create_score.music
106
+ end
107
+
108
+ it { @music.clef.bemol.should be_true }
109
+ it { @music.clef.to_s.should eq 'cb3' }
110
+ end
111
+ end
112
+
113
+ describe GabcWord do
114
+ before :each do
115
+ # beginning of the Populus Sion example
116
+ @src = "name: Populus Sion;\n%%\n
117
+ (c3) Pó(eh/hi)pu(h)lus(h) Si(hi)on,(hgh.) *(;)
118
+ ec(hihi)ce(e.) Dó(e.f!gwh/hi)mi(h)nus(h) vé(hi)ni(ig/ih)et.(h.) (::)"
119
+ @parser = GabcParser.new
120
+ @music = @parser.parse(@src).create_score.music
121
+ @word = @music.words.first
122
+ end
123
+
124
+ describe 'a simple word' do
125
+ subject { @word }
126
+ it { should_not be_empty }
127
+ it { should contain_a GabcSyllable }
128
+ end
129
+
130
+ describe 'lyrics' do
131
+ it { @word.size.should eq 3 }
132
+ it { @word.first.lyrics.should eq 'Pó' }
133
+ it { @word[1].lyrics.should eq 'pu' }
134
+ it { @music.words[1].first.lyrics.should eq 'Si' }
135
+ it { @music.words[-2].last.lyrics.should eq 'et.' }
136
+ it { @music.words.last.last.lyrics.should eq '' }
137
+ end
138
+
139
+ describe 'notes' do
140
+ it { @word.first.notes.should_not be_empty }
141
+ it { @word.first.notes.first.pitch.should eq :e }
142
+ end
143
+ end