musicality 0.3.0 → 0.5.0

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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +8 -1
  3. data/bin/midify +3 -4
  4. data/examples/composition/auto_counterpoint.rb +53 -0
  5. data/examples/composition/part_generator.rb +51 -0
  6. data/examples/composition/scale_exercise.rb +41 -0
  7. data/examples/{hip.rb → notation/hip.rb} +1 -1
  8. data/examples/{missed_connection.rb → notation/missed_connection.rb} +1 -1
  9. data/examples/{song1.rb → notation/song1.rb} +1 -1
  10. data/examples/{song2.rb → notation/song2.rb} +1 -1
  11. data/lib/musicality.rb +34 -4
  12. data/lib/musicality/composition/generation/counterpoint_generator.rb +153 -0
  13. data/lib/musicality/composition/generation/random_rhythm_generator.rb +39 -0
  14. data/lib/musicality/composition/model/pitch_class.rb +33 -0
  15. data/lib/musicality/composition/model/pitch_classes.rb +22 -0
  16. data/lib/musicality/composition/model/scale.rb +34 -0
  17. data/lib/musicality/composition/model/scale_class.rb +37 -0
  18. data/lib/musicality/composition/model/scale_classes.rb +91 -0
  19. data/lib/musicality/composition/note_generation.rb +31 -0
  20. data/lib/musicality/composition/transposition.rb +8 -0
  21. data/lib/musicality/composition/util/adding_sequence.rb +24 -0
  22. data/lib/musicality/composition/util/biinfinite_sequence.rb +130 -0
  23. data/lib/musicality/composition/util/compound_sequence.rb +44 -0
  24. data/lib/musicality/composition/util/probabilities.rb +20 -0
  25. data/lib/musicality/composition/util/random_sampler.rb +26 -0
  26. data/lib/musicality/composition/util/repeating_sequence.rb +24 -0
  27. data/lib/musicality/errors.rb +2 -0
  28. data/lib/musicality/notation/conversion/score_conversion.rb +1 -1
  29. data/lib/musicality/notation/conversion/score_converter.rb +3 -3
  30. data/lib/musicality/notation/model/link.rb +26 -24
  31. data/lib/musicality/notation/model/links.rb +11 -0
  32. data/lib/musicality/notation/model/note.rb +14 -15
  33. data/lib/musicality/notation/model/part.rb +3 -3
  34. data/lib/musicality/notation/model/pitch.rb +8 -0
  35. data/lib/musicality/notation/model/score.rb +70 -44
  36. data/lib/musicality/notation/model/symbols.rb +22 -0
  37. data/lib/musicality/notation/packing/score_packing.rb +2 -3
  38. data/lib/musicality/notation/parsing/articulation_parsing.rb +4 -4
  39. data/lib/musicality/notation/parsing/articulation_parsing.treetop +2 -2
  40. data/lib/musicality/notation/parsing/link_nodes.rb +2 -14
  41. data/lib/musicality/notation/parsing/link_parsing.rb +9 -107
  42. data/lib/musicality/notation/parsing/link_parsing.treetop +4 -12
  43. data/lib/musicality/notation/parsing/note_node.rb +23 -21
  44. data/lib/musicality/notation/parsing/note_parsing.rb +70 -70
  45. data/lib/musicality/notation/parsing/note_parsing.treetop +6 -3
  46. data/lib/musicality/notation/parsing/pitch_node.rb +4 -2
  47. data/lib/musicality/performance/conversion/score_collator.rb +3 -3
  48. data/lib/musicality/performance/midi/midi_util.rb +13 -6
  49. data/lib/musicality/performance/midi/score_sequencing.rb +17 -0
  50. data/lib/musicality/printing/lilypond/errors.rb +5 -0
  51. data/lib/musicality/printing/lilypond/meter_engraving.rb +11 -0
  52. data/lib/musicality/printing/lilypond/note_engraving.rb +53 -0
  53. data/lib/musicality/printing/lilypond/part_engraver.rb +12 -0
  54. data/lib/musicality/printing/lilypond/pitch_engraving.rb +30 -0
  55. data/lib/musicality/printing/lilypond/score_engraver.rb +78 -0
  56. data/lib/musicality/version.rb +1 -1
  57. data/spec/composition/generation/random_rhythm_generator_spec.rb +50 -0
  58. data/spec/composition/model/pitch_class_spec.rb +75 -0
  59. data/spec/composition/model/pitch_classes_spec.rb +24 -0
  60. data/spec/composition/model/scale_class_spec.rb +98 -0
  61. data/spec/composition/model/scale_spec.rb +110 -0
  62. data/spec/composition/note_generation_spec.rb +113 -0
  63. data/spec/composition/transposition_spec.rb +17 -0
  64. data/spec/composition/util/adding_sequence_spec.rb +176 -0
  65. data/spec/composition/util/compound_sequence_spec.rb +50 -0
  66. data/spec/composition/util/probabilities_spec.rb +39 -0
  67. data/spec/composition/util/random_sampler_spec.rb +47 -0
  68. data/spec/composition/util/repeating_sequence_spec.rb +151 -0
  69. data/spec/notation/conversion/score_conversion_spec.rb +3 -3
  70. data/spec/notation/conversion/score_converter_spec.rb +24 -24
  71. data/spec/notation/model/link_spec.rb +27 -25
  72. data/spec/notation/model/note_spec.rb +9 -6
  73. data/spec/notation/model/pitch_spec.rb +24 -1
  74. data/spec/notation/model/score_spec.rb +57 -16
  75. data/spec/notation/packing/score_packing_spec.rb +134 -206
  76. data/spec/notation/parsing/articulation_parsing_spec.rb +1 -8
  77. data/spec/notation/parsing/convenience_methods_spec.rb +1 -1
  78. data/spec/notation/parsing/link_nodes_spec.rb +3 -4
  79. data/spec/notation/parsing/link_parsing_spec.rb +10 -4
  80. data/spec/notation/parsing/note_node_spec.rb +8 -7
  81. data/spec/notation/parsing/note_parsing_spec.rb +9 -12
  82. data/spec/performance/conversion/score_collator_spec.rb +14 -14
  83. data/spec/performance/midi/midi_util_spec.rb +26 -0
  84. data/spec/performance/midi/score_sequencer_spec.rb +1 -1
  85. metadata +57 -12
  86. data/lib/musicality/notation/model/program.rb +0 -53
  87. data/lib/musicality/notation/packing/program_packing.rb +0 -16
  88. data/spec/notation/model/program_spec.rb +0 -50
  89. data/spec/notation/packing/program_packing_spec.rb +0 -33
@@ -0,0 +1,22 @@
1
+ module Musicality
2
+
3
+ ARTICULATION_SYMBOLS = {
4
+ Articulations::SLUR => "(",
5
+ Articulations::LEGATO => "[",
6
+ Articulations::TENUTO => "_",
7
+ Articulations::PORTATO => "%",
8
+ Articulations::STACCATO => ".",
9
+ Articulations::STACCATISSIMO => "'"
10
+ }
11
+
12
+ LINK_SYMBOLS = {
13
+ Links::TIE => "=",
14
+ Links::GLISSANDO => "~",
15
+ Links::PORTAMENTO => "|",
16
+ Links::SLUR => ARTICULATION_SYMBOLS[Articulations::SLUR],
17
+ Links::LEGATO => ARTICULATION_SYMBOLS[Articulations::LEGATO],
18
+ }
19
+
20
+ ACCENT_SYMBOL = "!"
21
+
22
+ end
@@ -84,7 +84,7 @@ class Score
84
84
  [ name, part.pack ]
85
85
  end
86
86
  ]
87
- packed_prog = program.pack
87
+ packed_prog = @program.map {|seg| seg.to_s }
88
88
 
89
89
  { "type" => self.class.to_s.split("::")[-1],
90
90
  "program" => packed_prog,
@@ -96,8 +96,7 @@ class Score
96
96
  unpacked_parts = Hash[ packing["parts"].map do |name,packed|
97
97
  [name, Part.unpack(packed)]
98
98
  end ]
99
-
100
- unpacked_prog = Program.unpack packing["program"]
99
+ unpacked_prog = packing["program"].map {|str| Segment.parse(str) }
101
100
 
102
101
  new(program: unpacked_prog,
103
102
  parts: unpacked_parts
@@ -84,12 +84,12 @@ module Articulation
84
84
  return cached
85
85
  end
86
86
 
87
- if (match_len = has_terminal?("=", false, index))
87
+ if (match_len = has_terminal?("(", false, index))
88
88
  r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
89
89
  r0.extend(Slur0)
90
90
  @index += match_len
91
91
  else
92
- terminal_parse_failure("=")
92
+ terminal_parse_failure("(")
93
93
  r0 = nil
94
94
  end
95
95
 
@@ -115,12 +115,12 @@ module Articulation
115
115
  return cached
116
116
  end
117
117
 
118
- if (match_len = has_terminal?("|", false, index))
118
+ if (match_len = has_terminal?("[", false, index))
119
119
  r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
120
120
  r0.extend(Legato0)
121
121
  @index += match_len
122
122
  else
123
- terminal_parse_failure("|")
123
+ terminal_parse_failure("[")
124
124
  r0 = nil
125
125
  end
126
126
 
@@ -7,7 +7,7 @@ grammar Articulation
7
7
  end
8
8
 
9
9
  rule slur
10
- "=" {
10
+ "(" {
11
11
  def to_articulation
12
12
  Musicality::Articulations::SLUR
13
13
  end
@@ -15,7 +15,7 @@ grammar Articulation
15
15
  end
16
16
 
17
17
  rule legato
18
- "|" {
18
+ "[" {
19
19
  def to_articulation
20
20
  Musicality::Articulations::LEGATO
21
21
  end
@@ -1,28 +1,16 @@
1
1
  module Musicality
2
2
  module Parsing
3
3
  class LinkNode < Treetop::Runtime::SyntaxNode; end
4
-
5
- class SlurNode < LinkNode
6
- def to_link
7
- Musicality::Link::Slur.new(target.to_pitch)
8
- end
9
- end
10
-
11
- class LegatoNode < LinkNode
12
- def to_link
13
- Musicality::Link::Legato.new(target.to_pitch)
14
- end
15
- end
16
4
 
17
5
  class GlissandoNode < LinkNode
18
6
  def to_link
19
- Musicality::Link::Glissando.new(target.to_pitch)
7
+ Musicality::Link::Glissando.new(pitch.to_pitch)
20
8
  end
21
9
  end
22
10
 
23
11
  class PortamentoNode < LinkNode
24
12
  def to_link
25
- Musicality::Link::Portamento.new(target.to_pitch)
13
+ Musicality::Link::Portamento.new(pitch.to_pitch)
26
14
  end
27
15
  end
28
16
 
@@ -25,35 +25,23 @@ module Link
25
25
  end
26
26
 
27
27
  i0 = index
28
- r1 = _nt_slur_link
28
+ r1 = _nt_tie
29
29
  if r1
30
30
  r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
31
31
  r0 = r1
32
32
  else
33
- r2 = _nt_tie
33
+ r2 = _nt_glissando
34
34
  if r2
35
35
  r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
36
36
  r0 = r2
37
37
  else
38
- r3 = _nt_legato_link
38
+ r3 = _nt_portamento
39
39
  if r3
40
40
  r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
41
41
  r0 = r3
42
42
  else
43
- r4 = _nt_glissando
44
- if r4
45
- r4 = SyntaxNode.new(input, (index-1)...index) if r4 == true
46
- r0 = r4
47
- else
48
- r5 = _nt_portamento
49
- if r5
50
- r5 = SyntaxNode.new(input, (index-1)...index) if r5 == true
51
- r0 = r5
52
- else
53
- @index = i0
54
- r0 = nil
55
- end
56
- end
43
+ @index = i0
44
+ r0 = nil
57
45
  end
58
46
  end
59
47
  end
@@ -63,49 +51,6 @@ module Link
63
51
  r0
64
52
  end
65
53
 
66
- module SlurLink0
67
- def target
68
- elements[1]
69
- end
70
- end
71
-
72
- def _nt_slur_link
73
- start_index = index
74
- if node_cache[:slur_link].has_key?(index)
75
- cached = node_cache[:slur_link][index]
76
- if cached
77
- node_cache[:slur_link][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
78
- @index = cached.interval.end
79
- end
80
- return cached
81
- end
82
-
83
- i0, s0 = index, []
84
- if (match_len = has_terminal?("=", false, index))
85
- r1 = true
86
- @index += match_len
87
- else
88
- terminal_parse_failure("=")
89
- r1 = nil
90
- end
91
- s0 << r1
92
- if r1
93
- r2 = _nt_pitch
94
- s0 << r2
95
- end
96
- if s0.last
97
- r0 = instantiate_node(SlurNode,input, i0...index, s0)
98
- r0.extend(SlurLink0)
99
- else
100
- @index = i0
101
- r0 = nil
102
- end
103
-
104
- node_cache[:slur_link][start_index] = r0
105
-
106
- r0
107
- end
108
-
109
54
  def _nt_tie
110
55
  start_index = index
111
56
  if node_cache[:tie].has_key?(index)
@@ -130,51 +75,8 @@ module Link
130
75
  r0
131
76
  end
132
77
 
133
- module LegatoLink0
134
- def target
135
- elements[1]
136
- end
137
- end
138
-
139
- def _nt_legato_link
140
- start_index = index
141
- if node_cache[:legato_link].has_key?(index)
142
- cached = node_cache[:legato_link][index]
143
- if cached
144
- node_cache[:legato_link][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
145
- @index = cached.interval.end
146
- end
147
- return cached
148
- end
149
-
150
- i0, s0 = index, []
151
- if (match_len = has_terminal?("|", false, index))
152
- r1 = true
153
- @index += match_len
154
- else
155
- terminal_parse_failure("|")
156
- r1 = nil
157
- end
158
- s0 << r1
159
- if r1
160
- r2 = _nt_pitch
161
- s0 << r2
162
- end
163
- if s0.last
164
- r0 = instantiate_node(LegatoNode,input, i0...index, s0)
165
- r0.extend(LegatoLink0)
166
- else
167
- @index = i0
168
- r0 = nil
169
- end
170
-
171
- node_cache[:legato_link][start_index] = r0
172
-
173
- r0
174
- end
175
-
176
78
  module Glissando0
177
- def target
79
+ def pitch
178
80
  elements[1]
179
81
  end
180
82
  end
@@ -217,7 +119,7 @@ module Link
217
119
  end
218
120
 
219
121
  module Portamento0
220
- def target
122
+ def pitch
221
123
  elements[1]
222
124
  end
223
125
  end
@@ -234,11 +136,11 @@ module Link
234
136
  end
235
137
 
236
138
  i0, s0 = index, []
237
- if (match_len = has_terminal?("/", false, index))
139
+ if (match_len = has_terminal?("|", false, index))
238
140
  r1 = true
239
141
  @index += match_len
240
142
  else
241
- terminal_parse_failure("/")
143
+ terminal_parse_failure("|")
242
144
  r1 = nil
243
145
  end
244
146
  s0 << r1
@@ -3,29 +3,21 @@ module Parsing
3
3
 
4
4
  grammar Link
5
5
  include Pitch
6
-
6
+
7
7
  rule link
8
- slur_link / tie / legato_link / glissando / portamento
8
+ tie / glissando / portamento
9
9
  end
10
10
 
11
- rule slur_link
12
- "=" target:pitch <SlurNode>
13
- end
14
-
15
11
  rule tie
16
12
  "=" <TieNode>
17
13
  end
18
14
 
19
- rule legato_link
20
- "|" target:pitch <LegatoNode>
21
- end
22
-
23
15
  rule glissando
24
- "~" target:pitch <GlissandoNode>
16
+ "~" pitch <GlissandoNode>
25
17
  end
26
18
 
27
19
  rule portamento
28
- "/" target:pitch <PortamentoNode>
20
+ "|" pitch <PortamentoNode>
29
21
  end
30
22
  end
31
23
 
@@ -6,34 +6,36 @@ module Parsing
6
6
  end
7
7
 
8
8
  def to_note
9
+ if more.empty?
10
+ return Musicality::Note.new(duration.to_r)
11
+ end
12
+
9
13
  pitches = []
10
14
  links = {}
11
-
12
- unless pitch_links.empty?
13
- first = pitch_links.first
14
- more = pitch_links.more
15
-
16
- pitches.push first.pitch.to_pitch
17
- unless first.the_link.empty?
18
- links[pitches[-1]] = first.the_link.to_link
19
- end
20
-
21
- more.elements.each do |x|
22
- pitches.push x.pl.pitch.to_pitch
23
- unless x.pl.the_link.empty?
24
- links[pitches[-1]] = x.pl.the_link.to_link
25
- end
15
+
16
+ first_pl = more.first_pl
17
+ more_pl = more.more_pl
18
+
19
+ pitches.push first_pl.pitch.to_pitch
20
+ unless first_pl.the_link.empty?
21
+ links[pitches[-1]] = first_pl.the_link.to_link
22
+ end
23
+
24
+ more_pl.elements.each do |x|
25
+ pitches.push x.pl.pitch.to_pitch
26
+ unless x.pl.the_link.empty?
27
+ links[pitches[-1]] = x.pl.the_link.to_link
26
28
  end
27
29
  end
28
30
 
29
31
  artic = Musicality::Articulations::NORMAL
30
- unless art.empty?
31
- artic = art.to_articulation
32
+ unless more.art.empty?
33
+ artic = more.art.to_articulation
32
34
  end
33
-
34
- accent_flag = acc.empty? ? false : true
35
- Musicality::Note.new(duration.to_r,
36
- pitches, links: links, articulation: artic, accented: accent_flag)
35
+
36
+ accent_flag = !more.acc.empty?
37
+ Musicality::Note.new(duration.to_r, pitches,
38
+ links: links, articulation: artic, accented: accent_flag)
37
39
  end
38
40
  end
39
41
  end
@@ -26,13 +26,21 @@ module Note
26
26
  end
27
27
 
28
28
  module Note1
29
- def first
29
+ def first_pl
30
30
  elements[0]
31
31
  end
32
32
 
33
- def more
33
+ def more_pl
34
34
  elements[1]
35
35
  end
36
+
37
+ def art
38
+ elements[2]
39
+ end
40
+
41
+ def acc
42
+ elements[3]
43
+ end
36
44
  end
37
45
 
38
46
  module Note2
@@ -40,17 +48,9 @@ module Note
40
48
  elements[0]
41
49
  end
42
50
 
43
- def art
51
+ def more
44
52
  elements[1]
45
53
  end
46
-
47
- def pitch_links
48
- elements[2]
49
- end
50
-
51
- def acc
52
- elements[3]
53
- end
54
54
  end
55
55
 
56
56
  def _nt_note
@@ -68,72 +68,72 @@ module Note
68
68
  r1 = _nt_duration
69
69
  s0 << r1
70
70
  if r1
71
- r3 = _nt_articulation
72
- if r3
73
- r2 = r3
74
- else
75
- r2 = instantiate_node(SyntaxNode,input, index...index)
76
- end
77
- s0 << r2
78
- if r2
79
- i5, s5 = index, []
80
- r6 = _nt_pitch_link
81
- s5 << r6
82
- if r6
83
- s7, i7 = [], index
84
- loop do
85
- i8, s8 = index, []
86
- if (match_len = has_terminal?(",", false, index))
87
- r9 = true
88
- @index += match_len
89
- else
90
- terminal_parse_failure(",")
91
- r9 = nil
92
- end
93
- s8 << r9
94
- if r9
95
- r10 = _nt_pitch_link
96
- s8 << r10
97
- end
98
- if s8.last
99
- r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
100
- r8.extend(Note0)
101
- else
102
- @index = i8
103
- r8 = nil
104
- end
105
- if r8
106
- s7 << r8
107
- else
108
- break
109
- end
71
+ i3, s3 = index, []
72
+ r4 = _nt_pitch_link
73
+ s3 << r4
74
+ if r4
75
+ s5, i5 = [], index
76
+ loop do
77
+ i6, s6 = index, []
78
+ if (match_len = has_terminal?(",", false, index))
79
+ r7 = true
80
+ @index += match_len
81
+ else
82
+ terminal_parse_failure(",")
83
+ r7 = nil
84
+ end
85
+ s6 << r7
86
+ if r7
87
+ r8 = _nt_pitch_link
88
+ s6 << r8
89
+ end
90
+ if s6.last
91
+ r6 = instantiate_node(SyntaxNode,input, i6...index, s6)
92
+ r6.extend(Note0)
93
+ else
94
+ @index = i6
95
+ r6 = nil
96
+ end
97
+ if r6
98
+ s5 << r6
99
+ else
100
+ break
110
101
  end
111
- r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
112
- s5 << r7
113
- end
114
- if s5.last
115
- r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
116
- r5.extend(Note1)
117
- else
118
- @index = i5
119
- r5 = nil
120
102
  end
103
+ r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
104
+ s3 << r5
121
105
  if r5
122
- r4 = r5
123
- else
124
- r4 = instantiate_node(SyntaxNode,input, index...index)
125
- end
126
- s0 << r4
127
- if r4
128
- r12 = _nt_accent
129
- if r12
130
- r11 = r12
106
+ r10 = _nt_articulation
107
+ if r10
108
+ r9 = r10
131
109
  else
132
- r11 = instantiate_node(SyntaxNode,input, index...index)
110
+ r9 = instantiate_node(SyntaxNode,input, index...index)
111
+ end
112
+ s3 << r9
113
+ if r9
114
+ r12 = _nt_accent
115
+ if r12
116
+ r11 = r12
117
+ else
118
+ r11 = instantiate_node(SyntaxNode,input, index...index)
119
+ end
120
+ s3 << r11
133
121
  end
134
- s0 << r11
135
122
  end
136
123
  end
124
+ if s3.last
125
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
126
+ r3.extend(Note1)
127
+ else
128
+ @index = i3
129
+ r3 = nil
130
+ end
131
+ if r3
132
+ r2 = r3
133
+ else
134
+ r2 = instantiate_node(SyntaxNode,input, index...index)
135
+ end
136
+ s0 << r2
137
137
  end
138
138
  if s0.last
139
139
  r0 = instantiate_node(NoteNode,input, i0...index, s0)