stretto 0.6.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.
Files changed (77) hide show
  1. data/CHANGELOG.markdown +0 -0
  2. data/README.markdown +67 -0
  3. data/Rakefile +9 -0
  4. data/lib/stretto.rb +14 -0
  5. data/lib/stretto/grammar/channel_pressure_grammar.treetop +9 -0
  6. data/lib/stretto/grammar/chord_grammar.treetop +60 -0
  7. data/lib/stretto/grammar/controller_change_grammar.treetop +9 -0
  8. data/lib/stretto/grammar/duration_grammar.treetop +60 -0
  9. data/lib/stretto/grammar/grammar_helper.rb +6 -0
  10. data/lib/stretto/grammar/harmonic_chord_grammar.treetop +15 -0
  11. data/lib/stretto/grammar/harmony_grammar.treetop +15 -0
  12. data/lib/stretto/grammar/instrument_grammar.treetop +9 -0
  13. data/lib/stretto/grammar/key_signature_grammar.treetop +10 -0
  14. data/lib/stretto/grammar/layer_change_grammar.treetop +9 -0
  15. data/lib/stretto/grammar/measure_grammar.treetop +7 -0
  16. data/lib/stretto/grammar/note_grammar.treetop +32 -0
  17. data/lib/stretto/grammar/pitch_bend_grammar.treetop +7 -0
  18. data/lib/stretto/grammar/polyphonic_pressure_grammar.treetop +9 -0
  19. data/lib/stretto/grammar/rest_grammar.treetop +9 -0
  20. data/lib/stretto/grammar/stretto_grammar.treetop +62 -0
  21. data/lib/stretto/grammar/tempo_grammar.treetop +9 -0
  22. data/lib/stretto/grammar/timing_grammar.treetop +9 -0
  23. data/lib/stretto/grammar/tokens/attack_decay_token.rb +42 -0
  24. data/lib/stretto/grammar/tokens/chord_token.rb +67 -0
  25. data/lib/stretto/grammar/tokens/controller_change_token.rb +26 -0
  26. data/lib/stretto/grammar/tokens/duration_token.rb +55 -0
  27. data/lib/stretto/grammar/tokens/harmonic_chord_token.rb +25 -0
  28. data/lib/stretto/grammar/tokens/harmony_with_melody_token.rb +66 -0
  29. data/lib/stretto/grammar/tokens/hash_token.rb +15 -0
  30. data/lib/stretto/grammar/tokens/key_signature_token.rb +30 -0
  31. data/lib/stretto/grammar/tokens/measure_token.rb +21 -0
  32. data/lib/stretto/grammar/tokens/modifier_token.rb +99 -0
  33. data/lib/stretto/grammar/tokens/note_string_token.rb +106 -0
  34. data/lib/stretto/grammar/tokens/note_token.rb +25 -0
  35. data/lib/stretto/grammar/tokens/pattern_token.rb +26 -0
  36. data/lib/stretto/grammar/tokens/polyphonic_pressure_token.rb +28 -0
  37. data/lib/stretto/grammar/tokens/rest_token.rb +21 -0
  38. data/lib/stretto/grammar/tokens/value_token.rb +28 -0
  39. data/lib/stretto/grammar/tokens/variable_definition_token.rb +30 -0
  40. data/lib/stretto/grammar/value_grammar.treetop +45 -0
  41. data/lib/stretto/grammar/variable_grammar.treetop +10 -0
  42. data/lib/stretto/grammar/voice_change_grammar.treetop +9 -0
  43. data/lib/stretto/music_elements/channel_pressure.rb +44 -0
  44. data/lib/stretto/music_elements/chord.rb +194 -0
  45. data/lib/stretto/music_elements/controller_change.rb +49 -0
  46. data/lib/stretto/music_elements/harmonic_chord.rb +56 -0
  47. data/lib/stretto/music_elements/harmony.rb +37 -0
  48. data/lib/stretto/music_elements/instrument.rb +57 -0
  49. data/lib/stretto/music_elements/key_signature.rb +110 -0
  50. data/lib/stretto/music_elements/layer.rb +22 -0
  51. data/lib/stretto/music_elements/layer_change.rb +39 -0
  52. data/lib/stretto/music_elements/measure.rb +38 -0
  53. data/lib/stretto/music_elements/melody.rb +72 -0
  54. data/lib/stretto/music_elements/modifiers/attack_decay.rb +55 -0
  55. data/lib/stretto/music_elements/modifiers/chord_intervals.rb +44 -0
  56. data/lib/stretto/music_elements/modifiers/duration.rb +180 -0
  57. data/lib/stretto/music_elements/modifiers/value.rb +172 -0
  58. data/lib/stretto/music_elements/modifiers/variables.rb +365 -0
  59. data/lib/stretto/music_elements/music_element.rb +88 -0
  60. data/lib/stretto/music_elements/note.rb +282 -0
  61. data/lib/stretto/music_elements/pattern.rb +100 -0
  62. data/lib/stretto/music_elements/pitch_bend.rb +46 -0
  63. data/lib/stretto/music_elements/polyphonic_pressure.rb +62 -0
  64. data/lib/stretto/music_elements/rest.rb +26 -0
  65. data/lib/stretto/music_elements/tempo.rb +42 -0
  66. data/lib/stretto/music_elements/timing.rb +33 -0
  67. data/lib/stretto/music_elements/variable.rb +49 -0
  68. data/lib/stretto/music_elements/voice.rb +49 -0
  69. data/lib/stretto/music_elements/voice_change.rb +39 -0
  70. data/lib/stretto/parsers/exceptions.rb +11 -0
  71. data/lib/stretto/parsers/parser.rb +89 -0
  72. data/lib/stretto/renderers/midiator/player.rb +200 -0
  73. data/lib/stretto/util/jfugue_format_parser.rb +20 -0
  74. data/lib/stretto/util/node.rb +5 -0
  75. data/lib/stretto/util/utils.rb +41 -0
  76. data/lib/stretto/version.rb +3 -0
  77. metadata +203 -0
@@ -0,0 +1,365 @@
1
+ module Stretto
2
+
3
+ # Module that holds the predefined variables according to JFugue
4
+ module Variables
5
+
6
+ INSTRUMENT_VARIABLES = {
7
+ 'PIANO' => 0,
8
+ 'ACOUSTIC_GRAND' => 0,
9
+ 'BRIGHT_ACOUSTIC' => 1,
10
+ 'ELECTRIC_GRAND' => 2,
11
+ 'HONKEY_TONK' => 3,
12
+ 'ELECTRIC_PIANO' => 4,
13
+ 'ELECTRIC_PIANO_1' => 4,
14
+ 'ELECTRIC_PIANO_2' => 5,
15
+ 'HARPISCHORD' => 6,
16
+ 'CLAVINET' => 7,
17
+ 'CELESTA' => 8,
18
+ 'GLOCKENSPIEL' => 9,
19
+ 'MUSIC_BOX' => 10,
20
+ 'VIBRAPHONE' => 11,
21
+ 'MARIMBA' => 12,
22
+ 'XYLOPHONE' => 13,
23
+ 'TUBULAR_BELLS' => 14,
24
+ 'DULCIMER' => 15,
25
+ 'DRAWBAR_ORGAN' => 16,
26
+ 'PERCUSSIVE_ORGAN' => 17,
27
+ 'ROCK_ORGAN' => 18,
28
+ 'CHURCH_ORGAN' => 19,
29
+ 'REED_ORGAN' => 20,
30
+ 'ACCORDION' => 21,
31
+ 'HARMONICA' => 22,
32
+ 'TANGO_ACCORDION' => 23,
33
+ 'GUITAR' => 24,
34
+ 'NYLON_STRING_GUITAR' => 24,
35
+ 'STEEL_STRING_GUITAR' => 25,
36
+ 'ELECTRIC_JAZZ_GUITAR' => 26,
37
+ 'ELECTRIC_CLEAN_GUITAR' => 27,
38
+ 'ELECTRIC_MUTED_GUITAR' => 28,
39
+ 'OVERDRIVEN_GUITAR' => 29,
40
+ 'DISTORTION_GUITAR' => 30,
41
+ 'GUITAR_HARMONICS' => 31,
42
+ 'ACOUSTIC_BASS' => 32,
43
+ 'ELECTRIC_BASS_FINGER' => 33,
44
+ 'ELECTRIC_BASS_PICK' => 34,
45
+ 'FRETLESS_BASS' => 35,
46
+ 'SLAP_BASS_1' => 36,
47
+ 'SLAP_BASS_2' => 37,
48
+ 'SYNTH_BASS_1' => 38,
49
+ 'SYNTH_BASS_2' => 39,
50
+ 'VIOLIN' => 40,
51
+ 'VIOLA' => 41,
52
+ 'CELLO' => 42,
53
+ 'CONTRABASS' => 43,
54
+ 'TREMOLO_STRINGS' => 44,
55
+ 'PIZZICATO_STRINGS' => 45,
56
+ 'ORCHESTRAL_STRINGS' => 46,
57
+ 'TIMPANI' => 47,
58
+ 'STRING_ENSEMBLE_1' => 48,
59
+ 'STRING_ENSEMBLE_2' => 49,
60
+ 'SYNTH_STRINGS_1' => 50,
61
+ 'SYNTH_STRINGS_2' => 51,
62
+ 'CHOIR_AAHS' => 52,
63
+ 'VOICE_OOHS' => 53,
64
+ 'SYNTH_VOICE' => 54,
65
+ 'ORCHESTRA_HIT' => 55,
66
+ 'TRUMPET' => 56,
67
+ 'TROMBONE' => 57,
68
+ 'TUBA' => 58,
69
+ 'MUTED_TRUMPET' => 59,
70
+ 'FRENCH_HORN' => 60,
71
+ 'BRASS_SECTION' => 61,
72
+ 'SYNTHBRASS_1' => 62,
73
+ 'SYNTHBRASS_2' => 63,
74
+ 'SOPRANO_SAX' => 64,
75
+ 'ALTO_SAX' => 65,
76
+ 'TENOR_SAX' => 66,
77
+ 'BARITONE_SAX' => 67,
78
+ 'OBOE' => 68,
79
+ 'ENGLISH_HORN' => 69,
80
+ 'BASOON' => 70,
81
+ 'CLARINET' => 71,
82
+ 'PICCOLO' => 72,
83
+ 'FLUTE' => 73,
84
+ 'RECORDER' => 74,
85
+ 'PAN_FLUTE' => 75,
86
+ 'BLOWN_BOTTLE' => 76,
87
+ 'SHAKUHACHI' => 77,
88
+ 'WHISTLE' => 78,
89
+ 'OCARINA' => 79,
90
+ 'LEAD_SQUARE' => 80,
91
+ 'SQUARE' => 80,
92
+ 'LEAD_SAWTOOTH' => 81,
93
+ 'SAWTOOTH' => 81,
94
+ 'LEAD_CALLIOPE' => 82,
95
+ 'CALLIOPE' => 82,
96
+ 'LEAD_CHIFF' => 83,
97
+ 'CHIFF' => 83,
98
+ 'LEAD_CHARANG' => 84,
99
+ 'CHARANG' => 84,
100
+ 'LEAD_VOICE' => 85,
101
+ 'VOICE' => 85,
102
+ 'LEAD_FIFTHS' => 86,
103
+ 'FIFTHS' => 86,
104
+ 'LEAD_BASSLEAD' => 87,
105
+ 'BASSLEAD' => 87,
106
+ 'PAD_NEW_AGE' => 88,
107
+ 'NEW_AGE' => 88,
108
+ 'PAD_WARM' => 89,
109
+ 'WARM' => 89,
110
+ 'PAD_POLYSYNTH' => 90,
111
+ 'POLYSYNTH' => 90,
112
+ 'PAD_CHOIR' => 91,
113
+ 'CHOIR' => 91,
114
+ 'PAD_BOWED' => 92,
115
+ 'BOWED' => 92,
116
+ 'PAD_METALLIC' => 93,
117
+ 'METALLIC' => 93,
118
+ 'PAD_HALO' => 94,
119
+ 'HALO' => 94,
120
+ 'PAD_SWEEP' => 95,
121
+ 'SWEEP' => 95,
122
+ 'FX_RAIN' => 96,
123
+ 'RAIN' => 96,
124
+ 'FX_SOUNDTRACK' => 97,
125
+ 'SOUNDTRACK' => 97,
126
+ 'FX_CRYSTAL' => 98,
127
+ 'CRYSTAL' => 98,
128
+ 'FX_ATMOSPHERE' => 99,
129
+ 'ATMOSPHERE' => 99,
130
+ 'FX_BRIGHTNESS' => 100,
131
+ 'BRIGHTNESS' => 100,
132
+ 'FX_GOBLINS' => 101,
133
+ 'GOBLINS' => 101,
134
+ 'FX_ECHOES' => 102,
135
+ 'ECHOES' => 102,
136
+ 'FX_SCI_FI' => 103,
137
+ 'SCI_FI' => 103,
138
+ 'SITAR' => 104,
139
+ 'BANJO' => 105,
140
+ 'SHAMISEN' => 106,
141
+ 'KOTO' => 107,
142
+ 'KALIMBA' => 108,
143
+ 'BAGPIPE' => 109,
144
+ 'FIDDLE' => 110,
145
+ 'SHANAI' => 111,
146
+ 'TINKLE_BELL' => 112,
147
+ 'AGOGO' => 113,
148
+ 'STEEL_DRUMS' => 114,
149
+ 'WOODBLOCK' => 115,
150
+ 'TAIKO_DRUM' => 116,
151
+ 'MELODIC_TOM' => 117,
152
+ 'SYNTH_DRUM' => 118,
153
+ 'REVERSE_CYMBAL' => 119,
154
+ 'GUITAR_FRET_NOISE' => 120,
155
+ 'BREATH_NOISE' => 121,
156
+ 'SEASHORE' => 122,
157
+ 'BIRD_TWEET' => 123,
158
+ 'TELEPHONE_RING' => 124,
159
+ 'HELICOPTER' => 125,
160
+ 'APPLAUSE' => 126,
161
+ 'GUNSHOT' => 127,
162
+ }
163
+
164
+ PERCUSSION_VARIABLES = {
165
+ 'ACOUSTIC_BASE_DRUM' => 35,
166
+ 'BASS_DRUM' => 36,
167
+ 'SIDE_KICK' => 37,
168
+ 'ACOUSTIC_SNARE' => 38,
169
+ 'HAND_CLAP' => 39,
170
+ 'ELECTRIC_SNARE' => 40,
171
+ 'LOW_FLOOR_TOM' => 41,
172
+ 'CLOSED_HI_HAT' => 42,
173
+ 'HIGH_FLOOR_TOM' => 43,
174
+ 'PEDAL_HI_TOM' => 44,
175
+ 'LOW_TOM' => 45,
176
+ 'OPEN_HI_HAT' => 46,
177
+ 'LOW_MID_TOM' => 47,
178
+ 'HI_MID_TOM' => 48,
179
+ 'CRASH_CYMBAL_1' => 49,
180
+ 'HIGH_TOM' => 50,
181
+ 'RIDE_CYMBAL_1' => 51,
182
+ 'CHINESE_CYMBAL' => 52,
183
+ 'RIDE_BELL' => 53,
184
+ 'TAMBOURINE' => 54,
185
+ 'SPLASH_CYMBAL' => 55,
186
+ 'COWBELL' => 56,
187
+ 'CRASH_CYMBAL_2' => 57,
188
+ 'VIBRASLAP' => 58,
189
+ 'RIDE_CYMBAL_2' => 59,
190
+ 'HI_BONGO' => 60,
191
+ 'LOW_BONGO' => 61,
192
+ 'MUTE_HI_CONGA' => 62,
193
+ 'OPEN_HI_CONGA' => 63,
194
+ 'LOW_CONGO' => 64,
195
+ 'HIGH_TIMBALE' => 65,
196
+ 'LOW_TIMBALE' => 66,
197
+ 'HIGH_AGOGO' => 67,
198
+ 'LOW_AGOGO' => 68,
199
+ 'CABASA' => 69,
200
+ 'MARACAS' => 70,
201
+ 'SHORT_WHISTLE' => 71,
202
+ 'LONG_WHISTLE' => 72,
203
+ 'SHORT_GUIRO' => 73,
204
+ 'LONG_GUIRO' => 74,
205
+ 'CLAVES' => 75,
206
+ 'HI_WOOD_BLOCK' => 76,
207
+ 'LOW_WOOD_BLOCK' => 77,
208
+ 'MUTE_CUICA' => 78,
209
+ 'OPEN_CUICA' => 79,
210
+ 'MUTE_TRIANGLE' => 80,
211
+ 'OPEN_TRIANGLE' => 81,
212
+ }
213
+
214
+ TEMPO_VARIABLES = {
215
+ 'GRAVE' => 40,
216
+ 'LARGO' => 45,
217
+ 'LARGHETTO' => 50,
218
+ 'LENTO' => 55,
219
+ 'ADAGIO' => 60,
220
+ 'ADAGIETTO' => 65,
221
+ 'ANDANTE' => 70,
222
+ 'ANDANTINO' => 80,
223
+ 'MODERATO' => 95,
224
+ 'ALLEGRETTO' => 110,
225
+ 'ALLEGRO' => 120,
226
+ 'VIVACE' => 145,
227
+ 'PRESTO' => 180,
228
+ 'PRESTISSIMO' => 220,
229
+ }
230
+
231
+ CONTROLLER_VARIABLES = {
232
+ 'BANK_SELECT_COARSE' => 0,
233
+ 'MOD_WHEEL_COARSE' => 1,
234
+ 'BREATH_COARSE' => 2,
235
+ 'FOOT_PEDAL_COARSE' => 4,
236
+ 'PORTAMENTO_TIME_COARSE' => 5,
237
+ 'DATA_ENTRY_COARSE' => 6,
238
+ 'VOLUME_COARSE' => 7,
239
+ 'BALANCE_COARSE' => 8,
240
+ 'PAN_POSITION_COARSE' => 10,
241
+ 'EXPRESSION_COARSE' => 11,
242
+ 'EFFECT_CONTROL_1_COARSE' => 12,
243
+ 'EFFECT_CONTROL_2_COARSE' => 13,
244
+ 'SLIDER_1' => 16,
245
+ 'SLIDER_2' => 17,
246
+ 'SLIDER_3' => 18,
247
+ 'SLIDER_4' => 19,
248
+ 'BANK_SELECT_FINE' => 32,
249
+ 'MOD_WHEEL_FINE' => 33,
250
+ 'BREATH_FINE' => 34,
251
+ 'FOOT_PEDAL_FINE' => 36,
252
+ 'PORTAMENTO_TIME_FINE' => 37,
253
+ 'DATA_ENTRY_FINE' => 38,
254
+ 'VOLUME_FINE' => 39,
255
+ 'BALANCE_FINE' => 40,
256
+ 'PAN_POSITION_FINE' => 42,
257
+ 'EXPRESSION_FINE' => 43,
258
+ 'EFFECT_CONTROL_1_FINE' => 44,
259
+ 'EFFECT_CONTROL_2_FINE' => 45,
260
+ 'HOLD_PEDAL' => 64,
261
+ 'HOLD' => 64,
262
+ 'PORTAMENTO' => 65,
263
+ 'SUSTENUTO_PEDAL' => 66,
264
+ 'SUSTENUTO' => 66,
265
+ 'SOFT_PEDAL' => 67,
266
+ 'SOFT' => 67,
267
+ 'LEGATO_PEDAL' => 68,
268
+ 'LEGATO' => 68,
269
+ 'HOLD_2_PEDAL' => 69,
270
+ 'HOLD_2' => 69,
271
+ 'SOUND_VARIATION' => 70,
272
+ 'VARIATION' => 70,
273
+ 'SOUND_TIMBRE' => 71,
274
+ 'TIMBRE' => 71,
275
+ 'SOUND_RELEASE_TIME' => 72,
276
+ 'RELEASE_TIME' => 72,
277
+ 'SOUND_ATTACK_TIME' => 73,
278
+ 'ATTACK_TIME' => 73,
279
+ 'SOUND_BRIGHTNESS' => 74,
280
+ 'X_BRIGHTNESS' => 74,
281
+ 'SOUND_CONTROL_6' => 75,
282
+ 'CONTROL_6' => 75,
283
+ 'SOUND_CONTROL_7' => 76,
284
+ 'CONTROL_7' => 76,
285
+ 'SOUND_CONTROL_8' => 77,
286
+ 'CONTROL_8' => 77,
287
+ 'SOUND_CONTROL_9' => 78,
288
+ 'CONTROL_9' => 78,
289
+ 'SOUND_CONTROL_10' => 79,
290
+ 'CONTROL_10' => 79,
291
+ 'GENERAL_PURPOSE_BUTTON_1' => 80,
292
+ 'GENERAL_BUTTON_1' => 80,
293
+ 'BUTTON_1' => 80,
294
+ 'GENERAL_PURPOSE_BUTTON_2' => 81,
295
+ 'GENERAL_BUTTON_2' => 81,
296
+ 'BUTTON_2' => 81,
297
+ 'GENERAL_PURPOSE_BUTTON_3' => 82,
298
+ 'GENERAL_BUTTON_3' => 82,
299
+ 'BUTTON_3' => 82,
300
+ 'GENERAL_PURPOSE_BUTTON_4' => 83,
301
+ 'GENERAL_BUTTON_4' => 83,
302
+ 'BUTTON_4' => 83,
303
+ 'EFFECTS_LEVEL' => 91,
304
+ 'EFFECTS' => 91,
305
+ 'TREMOLO_LEVEL' => 92,
306
+ 'TREMOLO' => 92,
307
+ 'CHORUS_LEVEL' => 93,
308
+ 'CHORUS' => 93,
309
+ 'CELESTE_LEVEL' => 94,
310
+ 'CELESTE' => 94,
311
+ 'PHASER_LEVEL' => 95,
312
+ 'PHASER' => 95,
313
+ 'DATA_BUTTON_INCREMENT' => 96,
314
+ 'DATA_BUTTON_INC' => 96,
315
+ 'BUTTON_INC' => 96,
316
+ 'DATA_BUTTON_DECREMENT' => 97,
317
+ 'DATA_BUTTON_DEC' => 97,
318
+ 'BUTTON_DEC' => 97,
319
+ 'NON_REGISTERED_COARSE' => 98,
320
+ 'NON_REGISTERED_FINE' => 99,
321
+ 'REGISTERED_COARSE' => 100,
322
+ 'REGISTERED_FINE' => 101,
323
+ 'ALL_SOUND_OFF' => 120,
324
+ 'ALL_CONTROLLERS_OFF' => 121,
325
+ 'LOCAL_KEYBOARD' => 122,
326
+ 'ALL_NOTES_OFF' => 123,
327
+ 'OMNI_MODE_OFF' => 124,
328
+ 'OMNI_OFF' => 124,
329
+ 'OMNI_MODE_ON' => 125,
330
+ 'OMNI_ON' => 125,
331
+ 'MONO_OPERATION' => 126,
332
+ 'MONO' => 126,
333
+ 'POLY_OPERATION' => 127,
334
+ 'POLY' => 127,
335
+
336
+ #== Combined values ==
337
+ 'BANK_SELECT' => 16383,
338
+ 'MOD_WHEEL' => 161,
339
+ 'BREATH' => 290,
340
+ 'FOOT_PEDAL' => 548,
341
+ 'PORTAMENTO_TIME' => 677,
342
+ 'DATA_ENTRY' => 806,
343
+ 'VOLUME' => 935,
344
+ 'BALANCE' => 1064,
345
+ 'PAN_POSITION' => 1322,
346
+ 'EXPRESSION' => 1451,
347
+ 'EFFECT_CONTROL_1' => 1580,
348
+ 'EFFECT_CONTROL_2' => 1709,
349
+ 'NON_REGISTERED' => 12770,
350
+ 'REGISTERED' => 13208,
351
+
352
+ #== Controller values ==
353
+ 'ON' => 127,
354
+ 'OFF' => 0,
355
+ 'DEFAULT' => 64,
356
+ }
357
+
358
+ # All predefined variables for stretto
359
+ PREDEFINED_VARIABLES = INSTRUMENT_VARIABLES.
360
+ merge(PERCUSSION_VARIABLES).
361
+ merge(TEMPO_VARIABLES).
362
+ merge(CONTROLLER_VARIABLES)
363
+
364
+ end
365
+ end
@@ -0,0 +1,88 @@
1
+ require File.join(File.dirname(__FILE__), '../util/node')
2
+ require File.join(File.dirname(__FILE__), 'modifiers/duration')
3
+
4
+ module Stretto
5
+ module MusicElements
6
+
7
+ # Superclass of all music elements in Stretto.
8
+ #
9
+ # These are all the elements than can be added to a pattern, most of them represent some
10
+ # data to be sent to a MIDI channel, or are some notation element to aid in the composition.
11
+ class MusicElement
12
+
13
+ include Stretto::Node
14
+
15
+ # In the case of parsed element, this is the originating string.
16
+ # In the case of calculated elements, this should be an empty string, and its string
17
+ # representation must be provided by the element
18
+ #
19
+ # @return [String, nil]
20
+ attr_reader :original_string
21
+
22
+ # The pattern to where this element belongs. Used to make calculations about key signatures,
23
+ # ties, instruments, voices, etc. that may modify the element itself.
24
+ #
25
+ # @return [Pattern, nil]
26
+ attr_reader :pattern
27
+
28
+ # Stores the original string and an optional pattern
29
+ def initialize(original_string, pattern = nil)
30
+ @original_string = original_string # TODO: Validates always an original string?
31
+ @pattern = pattern
32
+ end
33
+
34
+ # @return The string representation of the element
35
+ # @todo No specs for this. Ideally, its string representation should be one that can be
36
+ # parsed again to retrieve the same element
37
+ def to_s
38
+ original_string || build_music_string
39
+ end
40
+
41
+ # @abstract
42
+ # @todo Not yet implemented
43
+ def build_music_string
44
+ raise "build_music_string not implemented in #{self.class}"
45
+ end
46
+
47
+ alias inspect to_s
48
+
49
+ # By default, it is true, so we can tie notes with elements in between
50
+ def start_of_tie?
51
+ true
52
+ end
53
+
54
+ # By default, it is true, so we can tie notes with elements in between
55
+ def end_of_tie?
56
+ true
57
+ end
58
+
59
+ # By default, duration is 0
60
+ #
61
+ # The correct duration should be overriden by subclasses
62
+ def duration
63
+ 0
64
+ end
65
+
66
+ # @private
67
+ #
68
+ # Called whenever an element is attached to a pattern, and its attributes need to be
69
+ # recalculated / validated (because of variables, key signatures, ties, etc.)
70
+ #
71
+ # Each element class must override this class to provide the callback when the element
72
+ # is added to a pattern.
73
+ def substitute_variables!
74
+ # TODO: Big TODO - Change this method's name for a callback.
75
+ end
76
+
77
+ # Assigns the pattern to the element, and runs any associated callback
78
+ #
79
+ # @see #substitute_variables!
80
+ def pattern=(pattern)
81
+ @pattern = pattern
82
+ substitute_variables! # TODO: Remove this call
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+ end