musicality 0.8.0 → 0.9.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 (146) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +27 -1
  3. data/README.md +153 -10
  4. data/bin/collidify +102 -0
  5. data/bin/lilify +57 -29
  6. data/bin/midify +64 -24
  7. data/bin/musicality +39 -0
  8. data/examples/composition/auto_counterpoint.rb +4 -5
  9. data/examples/composition/part_generator.rb +8 -2
  10. data/examples/composition/scale_exercise.rb +1 -1
  11. data/examples/notation/notes.rb +27 -0
  12. data/examples/notation/parts.rb +51 -0
  13. data/examples/notation/scores.rb +38 -0
  14. data/examples/notation/twinkle.rb +34 -0
  15. data/examples/notation/twinkle.score +33 -0
  16. data/lib/musicality.rb +46 -11
  17. data/lib/musicality/composition/dsl/score_dsl.rb +2 -2
  18. data/lib/musicality/composition/dsl/score_methods.rb +10 -7
  19. data/lib/musicality/notation/conversion/change_conversion.rb +1 -1
  20. data/lib/musicality/notation/conversion/note_time_converter.rb +6 -23
  21. data/lib/musicality/notation/conversion/score_conversion.rb +15 -15
  22. data/lib/musicality/notation/conversion/score_converter.rb +50 -67
  23. data/lib/musicality/notation/model/articulations.rb +3 -2
  24. data/lib/musicality/notation/model/change.rb +15 -6
  25. data/lib/musicality/notation/model/dynamics.rb +11 -8
  26. data/lib/musicality/notation/model/instrument.rb +61 -0
  27. data/lib/musicality/notation/model/instruments.rb +111 -0
  28. data/lib/musicality/notation/model/key.rb +137 -0
  29. data/lib/musicality/notation/model/keys.rb +37 -0
  30. data/lib/musicality/notation/model/link.rb +6 -19
  31. data/lib/musicality/notation/model/mark.rb +43 -0
  32. data/lib/musicality/notation/model/marks.rb +11 -0
  33. data/lib/musicality/notation/model/meter.rb +4 -0
  34. data/lib/musicality/notation/model/note.rb +42 -28
  35. data/lib/musicality/notation/model/part.rb +18 -5
  36. data/lib/musicality/notation/model/pitch.rb +13 -4
  37. data/lib/musicality/notation/model/score.rb +104 -66
  38. data/lib/musicality/notation/model/symbols.rb +16 -11
  39. data/lib/musicality/notation/parsing/articulation_parsing.rb +38 -38
  40. data/lib/musicality/notation/parsing/articulation_parsing.treetop +14 -14
  41. data/lib/musicality/notation/parsing/link_parsing.rb +6 -6
  42. data/lib/musicality/notation/parsing/link_parsing.treetop +3 -3
  43. data/lib/musicality/notation/parsing/mark_parsing.rb +138 -0
  44. data/lib/musicality/notation/parsing/mark_parsing.treetop +31 -0
  45. data/lib/musicality/notation/parsing/note_node.rb +19 -12
  46. data/lib/musicality/notation/parsing/note_parsing.rb +218 -87
  47. data/lib/musicality/notation/parsing/note_parsing.treetop +9 -5
  48. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.rb +7 -2
  49. data/lib/musicality/notation/parsing/numbers/nonnegative_integer_parsing.treetop +1 -1
  50. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.rb +6 -4
  51. data/lib/musicality/notation/parsing/numbers/positive_integer_parsing.treetop +1 -1
  52. data/lib/musicality/notation/util/function.rb +41 -18
  53. data/lib/musicality/packable.rb +156 -0
  54. data/lib/musicality/performance/conversion/glissando_converter.rb +2 -2
  55. data/lib/musicality/performance/conversion/note_sequence_extractor.rb +223 -70
  56. data/lib/musicality/performance/conversion/portamento_converter.rb +5 -2
  57. data/lib/musicality/performance/conversion/score_collator.rb +70 -64
  58. data/lib/musicality/performance/midi/midi_events.rb +3 -3
  59. data/lib/musicality/performance/midi/midi_settings.rb +127 -0
  60. data/lib/musicality/performance/midi/midi_util.rb +8 -2
  61. data/lib/musicality/performance/midi/part_sequencer.rb +19 -18
  62. data/lib/musicality/performance/midi/score_sequencer.rb +13 -9
  63. data/lib/musicality/performance/midi/score_sequencing.rb +5 -5
  64. data/lib/musicality/performance/model/attack.rb +8 -0
  65. data/lib/musicality/performance/model/duration_functions.rb +23 -0
  66. data/lib/musicality/performance/model/note_sequence.rb +52 -95
  67. data/lib/musicality/performance/model/separation.rb +10 -0
  68. data/lib/musicality/performance/supercollider/add_actions.rb +13 -0
  69. data/lib/musicality/performance/supercollider/bundle.rb +18 -0
  70. data/lib/musicality/performance/supercollider/conductor.rb +125 -0
  71. data/lib/musicality/performance/supercollider/group.rb +71 -0
  72. data/lib/musicality/performance/supercollider/message.rb +26 -0
  73. data/lib/musicality/performance/supercollider/node.rb +122 -0
  74. data/lib/musicality/performance/supercollider/performer.rb +123 -0
  75. data/lib/musicality/performance/supercollider/score_conducting.rb +17 -0
  76. data/lib/musicality/performance/supercollider/server.rb +8 -0
  77. data/lib/musicality/performance/supercollider/synth.rb +43 -0
  78. data/lib/musicality/performance/supercollider/synthdef.rb +57 -0
  79. data/lib/musicality/performance/supercollider/synthdef_settings.rb +23 -0
  80. data/lib/musicality/performance/supercollider/synthdefs.rb +1654 -0
  81. data/lib/musicality/{composition/model/pitch_class.rb → pitch_class.rb} +1 -1
  82. data/lib/musicality/{composition/model/pitch_classes.rb → pitch_classes.rb} +9 -9
  83. data/lib/musicality/printing/lilypond/clef.rb +12 -0
  84. data/lib/musicality/printing/lilypond/key_engraving.rb +9 -0
  85. data/lib/musicality/printing/lilypond/lilypond_settings.rb +105 -0
  86. data/lib/musicality/printing/lilypond/meter_engraving.rb +1 -1
  87. data/lib/musicality/printing/lilypond/note_engraving.rb +112 -30
  88. data/lib/musicality/printing/lilypond/part_engraver.rb +114 -3
  89. data/lib/musicality/printing/lilypond/pitch_class_engraving.rb +22 -0
  90. data/lib/musicality/printing/lilypond/pitch_engraving.rb +2 -15
  91. data/lib/musicality/printing/lilypond/score_engraver.rb +44 -73
  92. data/lib/musicality/printing/lilypond/score_engraving.rb +3 -3
  93. data/lib/musicality/project/create_tasks.rb +31 -0
  94. data/lib/musicality/project/file_cleaner.rb +19 -0
  95. data/lib/musicality/project/file_raker.rb +107 -0
  96. data/lib/musicality/project/load_config.rb +43 -0
  97. data/lib/musicality/project/project.rb +64 -0
  98. data/lib/musicality/version.rb +1 -1
  99. data/musicality.gemspec +3 -0
  100. data/spec/composition/util/random_sampler_spec.rb +1 -1
  101. data/spec/notation/conversion/measure_note_map_spec.rb +1 -1
  102. data/spec/notation/conversion/note_time_converter_spec.rb +5 -85
  103. data/spec/notation/conversion/score_conversion_spec.rb +6 -41
  104. data/spec/notation/conversion/score_converter_spec.rb +19 -137
  105. data/spec/notation/model/change_spec.rb +55 -0
  106. data/spec/notation/model/key_spec.rb +171 -0
  107. data/spec/notation/model/link_spec.rb +34 -5
  108. data/spec/notation/model/meter_spec.rb +15 -0
  109. data/spec/notation/model/note_spec.rb +33 -27
  110. data/spec/notation/model/part_spec.rb +53 -4
  111. data/spec/notation/model/pitch_spec.rb +15 -0
  112. data/spec/notation/model/score_spec.rb +64 -72
  113. data/spec/notation/parsing/link_nodes_spec.rb +3 -3
  114. data/spec/notation/parsing/link_parsing_spec.rb +6 -6
  115. data/spec/notation/parsing/note_node_spec.rb +34 -9
  116. data/spec/notation/parsing/note_parsing_spec.rb +11 -9
  117. data/spec/notation/parsing/numbers/nonnegative_integer_spec.rb +4 -0
  118. data/spec/notation/parsing/pitch_node_spec.rb +0 -1
  119. data/spec/notation/util/value_computer_spec.rb +2 -2
  120. data/spec/performance/conversion/glissando_converter_spec.rb +9 -9
  121. data/spec/performance/conversion/note_sequence_extractor_spec.rb +48 -53
  122. data/spec/performance/conversion/portamento_converter_spec.rb +11 -9
  123. data/spec/performance/conversion/score_collator_spec.rb +59 -63
  124. data/spec/performance/midi/midi_util_spec.rb +22 -8
  125. data/spec/performance/midi/part_sequencer_spec.rb +2 -2
  126. data/spec/performance/midi/score_sequencer_spec.rb +12 -10
  127. data/spec/performance/midi/score_sequencing_spec.rb +2 -2
  128. data/spec/performance/model/note_sequence_spec.rb +41 -134
  129. data/spec/printing/note_engraving_spec.rb +204 -0
  130. data/spec/printing/score_engraver_spec.rb +40 -0
  131. data/spec/spec_helper.rb +1 -0
  132. metadata +69 -23
  133. data/examples/notation/hip.rb +0 -32
  134. data/examples/notation/missed_connection.rb +0 -26
  135. data/examples/notation/song1.rb +0 -33
  136. data/examples/notation/song2.rb +0 -32
  137. data/lib/musicality/notation/model/links.rb +0 -11
  138. data/lib/musicality/notation/packing/change_packing.rb +0 -56
  139. data/lib/musicality/notation/packing/part_packing.rb +0 -31
  140. data/lib/musicality/notation/packing/score_packing.rb +0 -123
  141. data/lib/musicality/performance/model/note_attacks.rb +0 -19
  142. data/lib/musicality/performance/util/note_linker.rb +0 -28
  143. data/spec/notation/packing/change_packing_spec.rb +0 -304
  144. data/spec/notation/packing/part_packing_spec.rb +0 -66
  145. data/spec/notation/packing/score_packing_spec.rb +0 -255
  146. data/spec/performance/util/note_linker_spec.rb +0 -68
@@ -1,17 +1,20 @@
1
- require 'yaml'
2
-
3
1
  module Musicality
4
2
 
5
3
  class Part
4
+ include Packable
6
5
  include Validatable
7
6
 
8
- attr_accessor :start_dynamic, :dynamic_changes, :notes
7
+ special_packing(:notes) {|notes| notes.map {|n| n.to_s }.join(" ") }
8
+ special_unpacking(:notes) {|notes_str| Note.split_parse(notes_str) }
9
+
10
+ attr_accessor :start_dynamic, :dynamic_changes, :notes, :settings
9
11
 
10
- def initialize start_dynamic, notes: [], dynamic_changes: {}
12
+ def initialize start_dynamic, notes: [], dynamic_changes: {}, settings: []
11
13
  @notes = notes
12
14
  @start_dynamic = start_dynamic
13
15
  @dynamic_changes = dynamic_changes
14
-
16
+ @settings = settings
17
+
15
18
  yield(self) if block_given?
16
19
  end
17
20
 
@@ -49,6 +52,16 @@ class Part
49
52
  raise RangeError, "dynamic change values #{outofrange} are not between 0 and 1"
50
53
  end
51
54
  end
55
+
56
+ def transpose interval
57
+ p = self.clone
58
+ p.notes.each {|n| n.transpose!(interval) }
59
+ return p
60
+ end
61
+
62
+ def find_settings settings_class
63
+ settings.find {|s| s.is_a? settings_class }
64
+ end
52
65
  end
53
66
 
54
67
  end
@@ -19,11 +19,13 @@ module Musicality
19
19
  #
20
20
  class Pitch
21
21
  include Comparable
22
+ include Packable
23
+
22
24
  attr_reader :octave, :semitone, :cent, :total_cents
23
25
 
24
26
  #The default number of semitones per octave is 12, corresponding to
25
27
  # the twelve-tone equal temperment tuning system.
26
- SEMITONES_PER_OCTAVE = 12
28
+ SEMITONES_PER_OCTAVE = PitchClass::MOD
27
29
  CENTS_PER_SEMITONE = 100
28
30
  CENTS_PER_OCTAVE = SEMITONES_PER_OCTAVE * CENTS_PER_SEMITONE
29
31
 
@@ -116,8 +118,12 @@ class Pitch
116
118
  Pitch.new(cent: @total_cents)
117
119
  end
118
120
 
119
- def to_s(sharpit = false)
120
- letter = case semitone
121
+ def natural?
122
+ [0,2,4,5,7,9,11].include?(semitone)
123
+ end
124
+
125
+ def self.pc_str semitone, sharpit
126
+ case semitone
121
127
  when 0 then "C"
122
128
  when 1 then sharpit ? "C#" : "Db"
123
129
  when 2 then "D"
@@ -131,7 +137,10 @@ class Pitch
131
137
  when 10 then sharpit ? "A#" : "Bb"
132
138
  when 11 then "B"
133
139
  end
134
-
140
+ end
141
+
142
+ def to_s(sharpit = false)
143
+ letter = Pitch.pc_str(semitone, sharpit)
135
144
  if @cent == 0
136
145
  return letter + octave.to_s
137
146
  elsif @cent > 0
@@ -1,8 +1,16 @@
1
1
  module Musicality
2
2
 
3
3
  class Score
4
+ include Packable
4
5
  include Validatable
5
- attr_accessor :parts, :program
6
+
7
+ special_packing(:program){|p| p.map {|range| range.to_s }}
8
+ special_unpacking(:program){|p| p.map {|str| parse_numeric_range(str) }}
9
+
10
+ special_packing(:sections){|s| Hash[ s.map {|name,range| [name,range.to_s] } ]}
11
+ special_unpacking(:sections){|s| Hash[ s.map {|name,str| [name,parse_numeric_range(str)] } ]}
12
+
13
+ attr_accessor :parts, :sections, :program, :start_key, :key_changes
6
14
  attr_writer :title, :composer
7
15
 
8
16
  def title value = nil
@@ -20,25 +28,33 @@ class Score
20
28
  @composer = value
21
29
  end
22
30
  end
23
-
24
- def initialize parts: {}, program: [], title: nil, composer: nil, sections: {}
31
+
32
+ def initialize parts: {}, program: [], title: nil, composer: nil, sections: {}, start_key: Keys::C_MAJOR, key_changes: {}
25
33
  @parts = parts
26
34
  @program = program
27
35
  @title = title
28
36
  @composer = composer
29
37
  @sections = sections
38
+ @start_key = start_key
39
+ @key_changes = key_changes
30
40
  yield(self) if block_given?
31
41
  end
32
42
 
33
43
  def validatables; @parts.values; end
34
- def check_methods; [:check_program, :check_parts ]; end
44
+ def check_methods
45
+ [:check_program, :check_parts, :check_start_key, :check_key_changes ]
46
+ end
35
47
 
36
48
  def clone
37
49
  Marshal.load(Marshal.dump(self))
38
50
  end
39
51
 
40
52
  def ==(other)
41
- return @parts == other.parts && @program == other.program
53
+ return self.class == other.class &&
54
+ @parts == other.parts && @program == other.program &&
55
+ @program == other.program && @sections == other.sections &&
56
+ @title == other.title && @composer == other.composer &&
57
+ @start_key == other.start_key && @key_changes == other.key_changes
42
58
  end
43
59
 
44
60
  def max_part_duration
@@ -55,72 +71,24 @@ class Score
55
71
  end
56
72
  alias duration seconds_long
57
73
  end
58
-
59
- class TempoBased < Score
60
- attr_accessor :start_tempo, :tempo_changes
74
+
75
+ # Tempo-based score with meter, bar lines, and a fixed pulse (beat).
76
+ # Offsets are measure-based, and tempo values are in beats-per-minute.
77
+ class Tempo < Score
78
+ attr_accessor :start_tempo, :tempo_changes, :start_meter, :meter_changes
61
79
 
62
80
  # See Score#initialize for remaining kwargs
63
- def initialize start_tempo, tempo_changes: {}, **kwargs
81
+ def initialize start_meter, start_tempo, tempo_changes: {}, meter_changes: {}, parts: {}, program: [], title: nil, composer: nil, sections: {}, start_key: Keys::C_MAJOR, key_changes: {}
64
82
  @start_tempo = start_tempo
65
83
  @tempo_changes = tempo_changes
66
- super(**kwargs)
67
- end
68
-
69
- def check_methods
70
- super() + [:check_start_tempo, :check_tempo_changes]
71
- end
72
-
73
- def ==(other)
74
- return super(other) && @start_tempo == other.start_tempo &&
75
- @tempo_changes == other.tempo_changes
76
- end
77
-
78
- def notes_long
79
- max_part_duration
80
- end
81
-
82
- private
83
-
84
- def check_start_tempo
85
- if @start_tempo <= 0
86
- raise NonPositiveError, "Start tempo (#{@start_tempo}) is not positive"
87
- end
88
- end
89
-
90
- def check_tempo_changes
91
- badtypes = @tempo_changes.select {|k,v| !v.end_value.is_a?(Numeric) }
92
- if badtypes.any?
93
- raise TypeError, "Found non-numeric tempo change values: #{badtypes}"
94
- end
95
-
96
- badvalues = @tempo_changes.select {|k,v| v.end_value <= 0 }
97
- if badvalues.any?
98
- raise NonPositiveError, "Found non-positive tempo changes values: #{badvalues}"
99
- end
100
- end
101
- end
102
-
103
- # Tempo-based score without meter, bar lines, or fixed pulse (beat).
104
- # Offsets are note-based, and tempo values are in quarter-notes-per-minute.
105
- class Unmeasured < Score::TempoBased
106
- alias duration notes_long
107
- end
108
-
109
- # Tempo-based score with meter, bar lines, and a fixed pulse (beat).
110
- # Offsets are measure-based, and tempo values are in beats-per-minute.
111
- class Measured < Score::TempoBased
112
- attr_accessor :start_meter, :meter_changes
113
-
114
- # See Score::TempoBased#initialize for remaining kwargs
115
- def initialize start_meter, start_tempo, meter_changes: {}, **kwargs
116
84
  @start_meter = start_meter
117
85
  @meter_changes = meter_changes
118
86
 
119
- super(start_tempo, **kwargs)
87
+ super(parts: parts, program: program, title: title, composer: composer, sections: sections, start_key: start_key, key_changes: key_changes)
120
88
  end
121
89
 
122
90
  def check_methods
123
- super() + [:check_start_meter, :check_meter_changes]
91
+ super() + [:check_start_tempo, :check_tempo_changes, :check_start_meter, :check_meter_changes]
124
92
  end
125
93
 
126
94
  def validatables
@@ -128,10 +96,17 @@ class Score
128
96
  end
129
97
 
130
98
  def ==(other)
131
- return super(other) && @start_meter == other.start_meter &&
132
- @meter_changes == other.meter_changes
99
+ return super(other) &&
100
+ @start_tempo == other.start_tempo &&
101
+ @tempo_changes == other.tempo_changes
102
+ @start_meter == other.start_meter &&
103
+ @meter_changes == other.meter_changes
133
104
  end
134
105
 
106
+ def notes_long
107
+ max_part_duration
108
+ end
109
+
135
110
  def measures_long note_dur = self.notes_long
136
111
  noff_end = note_dur
137
112
  noff_prev = 0.to_r
@@ -157,6 +132,24 @@ class Score
157
132
 
158
133
  private
159
134
 
135
+ def check_start_tempo
136
+ if @start_tempo <= 0
137
+ raise NonPositiveError, "Start tempo (#{@start_tempo}) is not positive"
138
+ end
139
+ end
140
+
141
+ def check_tempo_changes
142
+ badtypes = @tempo_changes.select {|k,v| !v.end_value.is_a?(Numeric) }
143
+ if badtypes.any?
144
+ raise TypeError, "Found non-numeric tempo change values: #{badtypes}"
145
+ end
146
+
147
+ badvalues = @tempo_changes.select {|k,v| v.end_value <= 0 }
148
+ if badvalues.any?
149
+ raise NonPositiveError, "Found non-positive tempo changes values: #{badvalues}"
150
+ end
151
+ end
152
+
160
153
  def check_start_meter
161
154
  unless @start_meter.is_a? Meter
162
155
  raise TypeError, "Start meter #{@start_meter} is not a Meter object"
@@ -166,14 +159,14 @@ class Score
166
159
  def check_meter_changes
167
160
  badtypes = @meter_changes.select {|k,v| !v.end_value.is_a?(Meter) }
168
161
  if badtypes.any?
169
- raise TypeError, "Found meter change values that are not Meter objects: #{nonmeter_values}"
162
+ raise TypeError, "Found meter change values that are not Meter objects: #{badtypes}"
170
163
  end
171
-
164
+
172
165
  badoffsets = @meter_changes.select {|k,v| k != k.to_i }
173
166
  if badoffsets.any?
174
167
  raise NonIntegerError, "Found meter changes at non-integer offsets: #{badoffsets}"
175
168
  end
176
-
169
+
177
170
  nonzero_duration = @meter_changes.select {|k,v| !v.is_a?(Change::Immediate) }
178
171
  if nonzero_duration.any?
179
172
  raise NonZeroError, "Found meter changes that are not immediate: #{nonzero_duration}"
@@ -206,6 +199,51 @@ class Score
206
199
  raise TypeError, "Non-Part part value(s) found: #{non_parts}"
207
200
  end
208
201
  end
202
+
203
+ def check_start_key
204
+ unless @start_key.is_a? Key
205
+ raise TypeError, "Start key #{@start_key} is not a Key object"
206
+ end
207
+ end
208
+
209
+ def check_key_changes
210
+ badtypes = @key_changes.select {|k,v| !v.end_value.is_a?(Key) }
211
+ if badtypes.any?
212
+ raise TypeError, "Found key change values that are not Key objects: #{badtypes}"
213
+ end
214
+
215
+ badoffsets = @key_changes.select {|k,v| k != k.to_i }
216
+ if badoffsets.any?
217
+ raise NonIntegerError, "Found key changes at non-integer offsets: #{badoffsets}"
218
+ end
219
+
220
+ nonzero_duration = @key_changes.select {|k,v| !v.is_a?(Change::Immediate) }
221
+ if nonzero_duration.any?
222
+ raise NonZeroError, "Found key changes that are not immediate: #{nonzero_duration}"
223
+ end
224
+ end
225
+
226
+ private
227
+
228
+ def self.parse_numeric str
229
+ if str.include? "."
230
+ str.to_f
231
+ elsif str.include? "/"
232
+ str.to_r
233
+ else
234
+ str.to_i
235
+ end
236
+ end
237
+
238
+ def self.parse_numeric_range str
239
+ result = str.match /(\d+([\.\/]\d+)?)([\.]{2,3})(\d+([\.\/]\d+)?)/
240
+ raise ArgumentError, "string #{str} is not a numeric range" if result.nil?
241
+
242
+ dots = result.values_at(3)
243
+ l_num = parse_numeric(result.values_at(1)[0])
244
+ r_num = parse_numeric(result.values_at(4)[0])
245
+ Range.new l_num, r_num, dots.size == 3
246
+ end
209
247
  end
210
248
 
211
249
  end
@@ -1,22 +1,27 @@
1
1
  module Musicality
2
2
 
3
+ # These symbols all need to match the notation parsers
4
+
3
5
  ARTICULATION_SYMBOLS = {
4
- Articulations::SLUR => "(",
5
- Articulations::LEGATO => "[",
6
- Articulations::TENUTO => "_",
7
- Articulations::PORTATO => "%",
6
+ Articulations::TENUTO => "-",
7
+ Articulations::ACCENT => ">",
8
+ Articulations::MARCATO => "^",
9
+ Articulations::PORTATO => "_",
8
10
  Articulations::STACCATO => ".",
9
- Articulations::STACCATISSIMO => "'"
11
+ Articulations::STACCATISSIMO => "!",
10
12
  }
11
13
 
12
14
  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],
15
+ Link::Tie => "~",
16
+ Link::Glissando => ";",
17
+ Link::Portamento => ":",
18
18
  }
19
19
 
20
- ACCENT_SYMBOL = "!"
20
+ MARK_SYMBOLS = {
21
+ Mark::Slur::Begin => "(",
22
+ Mark::Slur::End => ")",
23
+ Mark::Triplet::Begin => "[",
24
+ Mark::Triplet::End => "]",
25
+ }
21
26
 
22
27
  end
@@ -23,17 +23,17 @@ module Articulation
23
23
  end
24
24
 
25
25
  i0 = index
26
- r1 = _nt_slur
26
+ r1 = _nt_tenuto
27
27
  if r1
28
28
  r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
29
29
  r0 = r1
30
30
  else
31
- r2 = _nt_legato
31
+ r2 = _nt_accent
32
32
  if r2
33
33
  r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
34
34
  r0 = r2
35
35
  else
36
- r3 = _nt_tenuto
36
+ r3 = _nt_marcato
37
37
  if r3
38
38
  r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
39
39
  r0 = r3
@@ -67,95 +67,95 @@ module Articulation
67
67
  r0
68
68
  end
69
69
 
70
- module Slur0
70
+ module Tenuto0
71
71
  def to_articulation
72
- Musicality::Articulations::SLUR
72
+ Musicality::Articulations::TENUTO
73
73
  end
74
74
  end
75
75
 
76
- def _nt_slur
76
+ def _nt_tenuto
77
77
  start_index = index
78
- if node_cache[:slur].has_key?(index)
79
- cached = node_cache[:slur][index]
78
+ if node_cache[:tenuto].has_key?(index)
79
+ cached = node_cache[:tenuto][index]
80
80
  if cached
81
- node_cache[:slur][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
81
+ node_cache[:tenuto][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
82
82
  @index = cached.interval.end
83
83
  end
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
- r0.extend(Slur0)
89
+ r0.extend(Tenuto0)
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
 
96
- node_cache[:slur][start_index] = r0
96
+ node_cache[:tenuto][start_index] = r0
97
97
 
98
98
  r0
99
99
  end
100
100
 
101
- module Legato0
101
+ module Accent0
102
102
  def to_articulation
103
- Musicality::Articulations::LEGATO
103
+ Musicality::Articulations::ACCENT
104
104
  end
105
105
  end
106
106
 
107
- def _nt_legato
107
+ def _nt_accent
108
108
  start_index = index
109
- if node_cache[:legato].has_key?(index)
110
- cached = node_cache[:legato][index]
109
+ if node_cache[:accent].has_key?(index)
110
+ cached = node_cache[:accent][index]
111
111
  if cached
112
- node_cache[:legato][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
112
+ node_cache[:accent][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
113
113
  @index = cached.interval.end
114
114
  end
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
- r0.extend(Legato0)
120
+ r0.extend(Accent0)
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
 
127
- node_cache[:legato][start_index] = r0
127
+ node_cache[:accent][start_index] = r0
128
128
 
129
129
  r0
130
130
  end
131
131
 
132
- module Tenuto0
132
+ module Marcato0
133
133
  def to_articulation
134
- Musicality::Articulations::TENUTO
134
+ Musicality::Articulations::MARCATO
135
135
  end
136
136
  end
137
137
 
138
- def _nt_tenuto
138
+ def _nt_marcato
139
139
  start_index = index
140
- if node_cache[:tenuto].has_key?(index)
141
- cached = node_cache[:tenuto][index]
140
+ if node_cache[:marcato].has_key?(index)
141
+ cached = node_cache[:marcato][index]
142
142
  if cached
143
- node_cache[:tenuto][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
143
+ node_cache[:marcato][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
144
144
  @index = cached.interval.end
145
145
  end
146
146
  return cached
147
147
  end
148
148
 
149
- if (match_len = has_terminal?("_", false, index))
149
+ if (match_len = has_terminal?("^", false, index))
150
150
  r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
151
- r0.extend(Tenuto0)
151
+ r0.extend(Marcato0)
152
152
  @index += match_len
153
153
  else
154
- terminal_parse_failure("_")
154
+ terminal_parse_failure('"^"')
155
155
  r0 = nil
156
156
  end
157
157
 
158
- node_cache[:tenuto][start_index] = r0
158
+ node_cache[:marcato][start_index] = r0
159
159
 
160
160
  r0
161
161
  end
@@ -177,12 +177,12 @@ module Articulation
177
177
  return cached
178
178
  end
179
179
 
180
- if (match_len = has_terminal?("%", false, index))
180
+ if (match_len = has_terminal?("_", false, index))
181
181
  r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
182
182
  r0.extend(Portato0)
183
183
  @index += match_len
184
184
  else
185
- terminal_parse_failure("%")
185
+ terminal_parse_failure('"_"')
186
186
  r0 = nil
187
187
  end
188
188
 
@@ -213,7 +213,7 @@ module Articulation
213
213
  r0.extend(Staccato0)
214
214
  @index += match_len
215
215
  else
216
- terminal_parse_failure(".")
216
+ terminal_parse_failure('"."')
217
217
  r0 = nil
218
218
  end
219
219
 
@@ -239,12 +239,12 @@ module Articulation
239
239
  return cached
240
240
  end
241
241
 
242
- if (match_len = has_terminal?("'", false, index))
242
+ if (match_len = has_terminal?("!", false, index))
243
243
  r0 = instantiate_node(SyntaxNode,input, index...(index + match_len))
244
244
  r0.extend(Staccatissimo0)
245
245
  @index += match_len
246
246
  else
247
- terminal_parse_failure("'")
247
+ terminal_parse_failure('"!"')
248
248
  r0 = nil
249
249
  end
250
250