musicality 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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