lygre 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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