musical_score 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +25 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +45 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/codeclimate-config.patch +1191 -0
- data/lib/musical_score/attribute/attribute.rb +69 -0
- data/lib/musical_score/attribute/clef.rb +44 -0
- data/lib/musical_score/attribute/key.rb +74 -0
- data/lib/musical_score/attribute/time.rb +43 -0
- data/lib/musical_score/const.rb +16 -0
- data/lib/musical_score/element_base.rb +17 -0
- data/lib/musical_score/errors.rb +3 -0
- data/lib/musical_score/io/importer.rb +22 -0
- data/lib/musical_score/location.rb +13 -0
- data/lib/musical_score/measures.rb +42 -0
- data/lib/musical_score/note/lyric.rb +43 -0
- data/lib/musical_score/note/notation/notation.rb +105 -0
- data/lib/musical_score/note/notation/tie.rb +22 -0
- data/lib/musical_score/note/notation/tuplet.rb +22 -0
- data/lib/musical_score/note/note.rb +141 -0
- data/lib/musical_score/note/pitch.rb +140 -0
- data/lib/musical_score/note/time_modification.rb +33 -0
- data/lib/musical_score/note/type.rb +29 -0
- data/lib/musical_score/notes.rb +37 -0
- data/lib/musical_score/part/measure.rb +49 -0
- data/lib/musical_score/part/part.rb +45 -0
- data/lib/musical_score/score/identification/creator.rb +29 -0
- data/lib/musical_score/score/identification/encoding.rb +66 -0
- data/lib/musical_score/score/identification/identification.rb +47 -0
- data/lib/musical_score/score/part/part.rb +37 -0
- data/lib/musical_score/score/score.rb +126 -0
- data/lib/musical_score/version.rb +4 -0
- data/lib/musical_score.rb +12 -0
- data/musical_score.gemspec +42 -0
- metadata +184 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
Dir[File.expand_path('../', __FILE__) << '/**/*.rb'].each do |file|
|
3
|
+
# require file except myself
|
4
|
+
if(file != __FILE__)
|
5
|
+
require file
|
6
|
+
end
|
7
|
+
end
|
8
|
+
module MusicalScore
|
9
|
+
module Attribute
|
10
|
+
class Attribute < MusicalScore::ElementBase
|
11
|
+
include Contracts
|
12
|
+
attr_accessor :divisions, :key, :time, :instruments, :clef
|
13
|
+
|
14
|
+
# initialize the attibute
|
15
|
+
#
|
16
|
+
Contract KeywordArgs[
|
17
|
+
:divisions => Num,
|
18
|
+
:clef => Optional[MusicalScore::Attribute::Clef],
|
19
|
+
:key => Optional[MusicalScore::Attribute::Key],
|
20
|
+
:time => Optional[MusicalScore::Attribute::Time],
|
21
|
+
:instruments => Optional[String],
|
22
|
+
] => Any
|
23
|
+
def initialize(
|
24
|
+
divisions:,
|
25
|
+
clef: MusicalScore::Attribute::Clef.new(:G),
|
26
|
+
key: MusicalScore::Attribute::Key.new(0, :major),
|
27
|
+
time: MusicalScore::Attribute::Time.new(4, 4),
|
28
|
+
instruments: 'Piano',
|
29
|
+
**rest_args
|
30
|
+
)
|
31
|
+
@divisions = divisions
|
32
|
+
@clef = clef
|
33
|
+
@key = key
|
34
|
+
@time = time
|
35
|
+
@instruments = instruments
|
36
|
+
end
|
37
|
+
|
38
|
+
Contract REXML::Element => MusicalScore::Attribute::Attribute
|
39
|
+
def self.create_by_xml(xml_doc)
|
40
|
+
divisions = xml_doc.elements["//divisions"].text.to_i
|
41
|
+
clef_doc = xml_doc.elements["//clef"]
|
42
|
+
time_doc = xml_doc.elements["//time"]
|
43
|
+
key_doc = xml_doc.elements["//key"]
|
44
|
+
|
45
|
+
clef = clef_doc ? MusicalScore::Attribute::Clef.create_by_xml(clef_doc) : nil
|
46
|
+
time = time_doc ? MusicalScore::Attribute::Time.create_by_xml(time_doc) : nil
|
47
|
+
key = key_doc ? MusicalScore::Attribute::Key.create_by_xml(key_doc) : nil
|
48
|
+
|
49
|
+
attributes = MusicalScore::Attribute::Attribute.new(divisions: divisions, clef: clef, time: time)
|
50
|
+
return attributes
|
51
|
+
end
|
52
|
+
|
53
|
+
def export_xml
|
54
|
+
attribute_element = REXML::Element.new('attributes')
|
55
|
+
divisions_element = REXML::Element.new('divisions').add_text(@divisions.to_s)
|
56
|
+
key_element = @key.export_xml
|
57
|
+
time_element = @time.export_xml
|
58
|
+
clef_element = @clef.export_xml
|
59
|
+
|
60
|
+
attribute_element.add_element(divisions_element)
|
61
|
+
attribute_element.add_element(key_element)
|
62
|
+
attribute_element.add_element(time_element)
|
63
|
+
attribute_element.add_element(clef_element)
|
64
|
+
|
65
|
+
return attribute_element
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "contracts"
|
2
|
+
module MusicalScore
|
3
|
+
module Attribute
|
4
|
+
class Clef < MusicalScore::ElementBase
|
5
|
+
include Contracts
|
6
|
+
@@sign = %i(G F C percussion TAB jianpu none)
|
7
|
+
attr_reader :sign, :line, :clef_octave_change
|
8
|
+
|
9
|
+
# constructor
|
10
|
+
#
|
11
|
+
# @param sign The sign of clef, such as treble, bass. It is described by the @@sign symbols
|
12
|
+
# @param line The number of line from the bottom of the staff, which the sign note is defined at the line.
|
13
|
+
# @param clef_octave_change The number of clef changes, which is written either an octave higher or lower than sounding pitch
|
14
|
+
Contract Enum[*@@sign], Pos, Num => Any
|
15
|
+
def initialize(sign, line = 0, clef_octave_change = 0)
|
16
|
+
@sign = sign.to_sym
|
17
|
+
@line = line
|
18
|
+
@clef_octave_change = clef_octave_change
|
19
|
+
end
|
20
|
+
|
21
|
+
Contract REXML::Element => MusicalScore::Attribute::Clef
|
22
|
+
def self.create_by_xml(xml_doc)
|
23
|
+
sign = xml_doc.elements["sign"].text.to_sym
|
24
|
+
line = xml_doc.elements["line"] ? xml_doc.elements["line"].text.to_i : 0
|
25
|
+
clef_octave_change = xml_doc.elements["clef-octave-change"] ? xml_doc.elements["clef-octave-change"].text.to_i : 0
|
26
|
+
clef = MusicalScore::Attribute::Clef.new(sign, line, clef_octave_change)
|
27
|
+
return clef
|
28
|
+
end
|
29
|
+
|
30
|
+
def export_xml
|
31
|
+
clef_element = REXML::Element.new('clef')
|
32
|
+
sign_element = REXML::Element.new('sign').add_text(@sign.to_s)
|
33
|
+
line_element = @line != 0 ? REXML::Element.new('line').add_text(@line.to_s) : nil
|
34
|
+
clef_octave_change_element = @clef_octave_change != 0 ? REXML::Element.new('clef-octave-change').add_text(@clef_octave_change.to_s) : nil
|
35
|
+
|
36
|
+
clef_element.add_element(sign_element)
|
37
|
+
clef_element.add_element(line_element) if line_element
|
38
|
+
clef_element.add_element(clef_octave_change_element) if clef_octave_change_element
|
39
|
+
|
40
|
+
return clef_element
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require "contracts"
|
2
|
+
module MusicalScore
|
3
|
+
module Attribute
|
4
|
+
class Key < MusicalScore::ElementBase
|
5
|
+
include Contracts
|
6
|
+
@@mode = %i(major :minor)
|
7
|
+
@@circle_of_fifths = [0, 7, 2, 9, 4, 11, 6, 1, 8, 3, 10, 5]
|
8
|
+
|
9
|
+
attr_reader :fifths, :mode
|
10
|
+
# constructor
|
11
|
+
#
|
12
|
+
# @param fifths The number of sharps (positive) or flats (negative)
|
13
|
+
# @param mode major or minor
|
14
|
+
Contract Enum[*-NUMBER_OF_FIFTHS..NUMBER_OF_FIFTHS], Enum[*@@mode] => Any
|
15
|
+
def initialize(fifths, mode)
|
16
|
+
@fifths = fifths
|
17
|
+
@mode = mode.to_sym
|
18
|
+
end
|
19
|
+
|
20
|
+
# detect tonic in major scale and minor scale, and pithes that has sharp or flat
|
21
|
+
#
|
22
|
+
Contract None => HashOf[Any, Any]
|
23
|
+
def tonic_key_and_altered_pitches
|
24
|
+
if @fifths >= 0
|
25
|
+
pitch_number = @@circle_of_fifths[@fifths]
|
26
|
+
major_pitch = MusicalScore::Note::Pitch.new_note_sharp(pitch_number)
|
27
|
+
|
28
|
+
minor_number = (pitch_number + RELATED_KEY_SLIDE_NUMBER) % NUMBER_OF_NOTES
|
29
|
+
minor_pitch = MusicalScore::Note::Pitch.new_note_sharp(minor_number)
|
30
|
+
|
31
|
+
altered_pitches = Array.new
|
32
|
+
@fifths.times do |i|
|
33
|
+
count = (i + SHARP_START_INDEX) % NUMBER_OF_NOTES
|
34
|
+
altered_pitches.push(MusicalScore::Note::Pitch.new_note_sharp(@@circle_of_fifths[count]))
|
35
|
+
end
|
36
|
+
return { :major_pitch => major_pitch, :minor_pitch => minor_pitch, :altered_pitches => altered_pitches }
|
37
|
+
else
|
38
|
+
reversed = @@circle_of_fifths.reverse
|
39
|
+
fif = @fifths.abs
|
40
|
+
pitch_number = reversed[fif-1]
|
41
|
+
major_pitch = MusicalScore::Note::Pitch.new_note_flat(pitch_number)
|
42
|
+
|
43
|
+
minor_number = (pitch_number + RELATED_KEY_SLIDE_NUMBER) % NUMBER_OF_NOTES
|
44
|
+
minor_pitch = MusicalScore::Note::Pitch.new_note_flat(minor_number)
|
45
|
+
|
46
|
+
altered_pitches = Array.new
|
47
|
+
fif.times do |i|
|
48
|
+
count = (i + FLAT_START_INDEX) % NUMBER_OF_NOTES
|
49
|
+
altered_pitches.push(MusicalScore::Note::Pitch.new_note_flat(reversed[count]))
|
50
|
+
end
|
51
|
+
return { :major_pitch => major_pitch, :minor_pitch => minor_pitch, :altered_pitches => altered_pitches }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Contract REXML::Element => MusicalScore::Attribute::Key
|
56
|
+
def self.create_by_xml(xml_doc)
|
57
|
+
fifths = xml_doc.elements["fifths"].text.to_i
|
58
|
+
mode = xml_doc.elements["mode"].text.to_sym
|
59
|
+
return MusicalScore::Attribute::Key.new(fifths, mode)
|
60
|
+
end
|
61
|
+
|
62
|
+
def export_xml
|
63
|
+
key_element = REXML::Element.new('key')
|
64
|
+
fifths_element = REXML::Element.new('fifths').add_text(@fifths.to_s)
|
65
|
+
mode_element = REXML::Element.new('mode').add_text(@mode.to_s)
|
66
|
+
|
67
|
+
key_element.add_element(fifths_element)
|
68
|
+
key_element.add_element(mode_element)
|
69
|
+
|
70
|
+
return key_element
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
module MusicalScore
|
3
|
+
module Attribute
|
4
|
+
class Time < MusicalScore::ElementBase
|
5
|
+
include Contracts
|
6
|
+
attr_reader :beats, :beat_type
|
7
|
+
|
8
|
+
# constructor
|
9
|
+
#
|
10
|
+
Contract Num, Num => Any
|
11
|
+
def initialize(beats, beat_type)
|
12
|
+
@beats = beats
|
13
|
+
@beat_type = beat_type
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String] describe the time object in a fraction style
|
17
|
+
def to_s
|
18
|
+
return "%d/%d" % [@beats, @beat_type]
|
19
|
+
end
|
20
|
+
|
21
|
+
Contract REXML::Element => MusicalScore::Attribute::Time
|
22
|
+
def self.create_by_xml(xml_doc)
|
23
|
+
beats = xml_doc.elements["beats"].text.to_i
|
24
|
+
beat_type = xml_doc.elements["beat-type"].text.to_i
|
25
|
+
return MusicalScore::Attribute::Time.new(beats, beat_type)
|
26
|
+
end
|
27
|
+
|
28
|
+
def export_xml
|
29
|
+
time = REXML::Element.new('time')
|
30
|
+
beats = REXML::Element.new('beats')
|
31
|
+
beat_type = REXML::Element.new('beat-type')
|
32
|
+
|
33
|
+
beats.add_text(@beats.to_s)
|
34
|
+
beat_type.add_text(@beat_type.to_s)
|
35
|
+
|
36
|
+
time.add_element(beats)
|
37
|
+
time.add_element(beat_type)
|
38
|
+
|
39
|
+
return time
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module MusicalScore
|
2
|
+
SHARP = :sharp
|
3
|
+
FLAT = :flat
|
4
|
+
|
5
|
+
NUMBER_OF_NOTES = 12
|
6
|
+
NUMBER_OF_FIFTHS = 7
|
7
|
+
SHARP_START_INDEX = 11
|
8
|
+
FLAT_START_INDEX = 6
|
9
|
+
|
10
|
+
RELATED_KEY_SLIDE_NUMBER = 9
|
11
|
+
|
12
|
+
AVAILABLE_NUMBERS_OF_ALTER = [-2, -1, 0, 1, 2]
|
13
|
+
TYPE_START_STOP = %i(start stop)
|
14
|
+
TYPE_START_STOP_CONTINUE = %i(start stop continue)
|
15
|
+
TYPE_CREATOR = %i(composer lyricist arranger)
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
require 'rexml/document'
|
3
|
+
|
4
|
+
module MusicalScore
|
5
|
+
class ElementBase
|
6
|
+
include Contracts
|
7
|
+
|
8
|
+
Contract Or[REXML::Document, REXML::Element] => Any
|
9
|
+
def self.create_by_xml(element)
|
10
|
+
raise "Called abstract method: create_by_xml"
|
11
|
+
end
|
12
|
+
|
13
|
+
def export_xml
|
14
|
+
raise "Called abstract method: export_xml"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'musical_score'
|
2
|
+
require 'rexml/document'
|
3
|
+
module MusicalScore
|
4
|
+
module IO
|
5
|
+
def import(file)
|
6
|
+
extname = File.extname(file)
|
7
|
+
case extname
|
8
|
+
when ".xml"
|
9
|
+
return import_xml(file)
|
10
|
+
else
|
11
|
+
raise MusicalScore::InvalidFileType
|
12
|
+
end
|
13
|
+
end
|
14
|
+
def import_xml(file_path)
|
15
|
+
doc = REXML::Document.new(File.new(file_path))
|
16
|
+
score = MusicalScore::Score::Score.create_by_xml(doc, file_path)
|
17
|
+
return score
|
18
|
+
end
|
19
|
+
|
20
|
+
module_function :import, :import_xml
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
|
3
|
+
module MusicalScore
|
4
|
+
class Location
|
5
|
+
attr_reader :measure_number, :location
|
6
|
+
include Contracts
|
7
|
+
Contract Nat, Rational => Any
|
8
|
+
def initialize(measure_number, location)
|
9
|
+
@measure_number = measure_number
|
10
|
+
@location = location
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
require 'musical_score/part/measure'
|
3
|
+
module MusicalScore
|
4
|
+
class Measures < MusicalScore::ElementBase
|
5
|
+
include Contracts
|
6
|
+
include Enumerable
|
7
|
+
attr_reader :measures
|
8
|
+
|
9
|
+
Contract ArrayOf[MusicalScore::Part::Measure] => Any
|
10
|
+
def initialize(measures)
|
11
|
+
@measures = measures
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](index)
|
15
|
+
return @measures[index]
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
@measures.each do |measure|
|
20
|
+
yield measure
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def all_notes
|
25
|
+
result = Array.new
|
26
|
+
@measures.each do |measure|
|
27
|
+
result.concat(measure)
|
28
|
+
end
|
29
|
+
return result
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_location
|
33
|
+
current_location = Rational(0)
|
34
|
+
@measures.each do |measure|
|
35
|
+
number = measure.number
|
36
|
+
measure.notes.set_location(current_location, number)
|
37
|
+
current_location += measure.notes.duration
|
38
|
+
measure.length = measure.notes.duration
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
module MusicalScore
|
3
|
+
module Note
|
4
|
+
class Lyric < MusicalScore::ElementBase
|
5
|
+
include Contracts
|
6
|
+
@@syllabic = %i(single begin end middle)
|
7
|
+
attr_accessor :text, :syllabic, :is_extend
|
8
|
+
|
9
|
+
# constructor
|
10
|
+
#
|
11
|
+
# @param text
|
12
|
+
# @param syllabic
|
13
|
+
# @param is_extend
|
14
|
+
Contract String, Maybe[Enum[*@@syllabic]], Bool => Any
|
15
|
+
def initialize(text, syllabic, is_extend = false)
|
16
|
+
@text = text
|
17
|
+
@syllabic = syllabic
|
18
|
+
@is_extend = is_extend
|
19
|
+
end
|
20
|
+
Contract REXML::Element => MusicalScore::Note::Lyric
|
21
|
+
def self.create_by_xml(xml_doc)
|
22
|
+
syllabic = xml_doc.elements["syllabic"] ? xml_doc.elements["syllabic"].text.to_sym : nil
|
23
|
+
text = xml_doc.elements["text"].text
|
24
|
+
is_extend = xml_doc.elements["extend"] ? true : false
|
25
|
+
return MusicalScore::Note::Lyric.new(text, syllabic, is_extend)
|
26
|
+
end
|
27
|
+
|
28
|
+
def export_xml(number)
|
29
|
+
lyric_element = REXML::Element.new('lyric')
|
30
|
+
lyric_element.add_attribute('number', number.to_s)
|
31
|
+
text_element = REXML::Element.new('text').add_text(@text.to_s)
|
32
|
+
|
33
|
+
if (@syllabic)
|
34
|
+
syllabic_element = REXML::Element.new('syllabic').add_text(@syllabic.to_s)
|
35
|
+
lyric_element.add_element(syllabic_element)
|
36
|
+
end
|
37
|
+
lyric_element.add_element(text_element)
|
38
|
+
|
39
|
+
return lyric_element
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
Dir[File.expand_path('../', __FILE__) << '/**/*.rb'].each do |file|
|
3
|
+
# require file except myself
|
4
|
+
if(file != __FILE__)
|
5
|
+
require file
|
6
|
+
end
|
7
|
+
end
|
8
|
+
module MusicalScore
|
9
|
+
module Note
|
10
|
+
module Notation
|
11
|
+
class Notation < MusicalScore::ElementBase
|
12
|
+
include Contracts
|
13
|
+
@@articulation = %i(
|
14
|
+
accent
|
15
|
+
breath_mark
|
16
|
+
caesura
|
17
|
+
detached_legato
|
18
|
+
doit
|
19
|
+
falloff
|
20
|
+
plop
|
21
|
+
scoop
|
22
|
+
spiccato
|
23
|
+
staccatissimo
|
24
|
+
staccato
|
25
|
+
stress
|
26
|
+
strong_accent
|
27
|
+
tenuto
|
28
|
+
unstress
|
29
|
+
)
|
30
|
+
@@dynamics = %i(
|
31
|
+
f
|
32
|
+
ff
|
33
|
+
fff
|
34
|
+
ffff
|
35
|
+
fffff
|
36
|
+
fp
|
37
|
+
fz
|
38
|
+
mf
|
39
|
+
mp
|
40
|
+
p
|
41
|
+
pp
|
42
|
+
ppp
|
43
|
+
pppp
|
44
|
+
ppppp
|
45
|
+
rf
|
46
|
+
rfz
|
47
|
+
sf
|
48
|
+
sffz
|
49
|
+
sfpp
|
50
|
+
sfz
|
51
|
+
)
|
52
|
+
attr_accessor :articulation, :dynamics, :tie, :tuplet
|
53
|
+
Contract KeywordArgs[
|
54
|
+
:articulation => Maybe[Enum[*@@articulation]],
|
55
|
+
:dynamics => Maybe[Enum[*@@dynamics]],
|
56
|
+
:tie => Maybe[MusicalScore::Note::Notation::Tie],
|
57
|
+
:tuplet => Maybe[MusicalScore::Note::Notation::Tuplet],
|
58
|
+
] => Any
|
59
|
+
def initialize(
|
60
|
+
articulation: nil,
|
61
|
+
dynamics: nil,
|
62
|
+
tie: nil,
|
63
|
+
tuplet: nil,
|
64
|
+
**rest_args
|
65
|
+
)
|
66
|
+
@articulation = articulation
|
67
|
+
@dynamics = dynamics
|
68
|
+
@tie = tie
|
69
|
+
@tuplet = tuplet
|
70
|
+
end
|
71
|
+
|
72
|
+
Contract REXML::Element => MusicalScore::Note::Notation::Notation
|
73
|
+
def self.create_by_xml(xml_doc)
|
74
|
+
articulation = xml_doc.elements["articulations"] ? xml_doc.elements["articulations"].elements[1].name.to_sym : nil
|
75
|
+
dynamics = xml_doc.elements["dynamics"] ? xml_doc.elements["dynamics"].elements[1].name.to_sym : nil
|
76
|
+
tie_arg = xml_doc.elements["tied"] ? xml_doc.elements["tied"].attributes["type"].to_sym : nil
|
77
|
+
tie = tie_arg ? MusicalScore::Note::Notation::Tie.new(tie_arg) : nil
|
78
|
+
tuplet_arg = xml_doc.elements["tuplet"] ? xml_doc.elements["tuplet"].attributes["type"].to_sym : nil
|
79
|
+
tuplet = tuplet_arg ? MusicalScore::Note::Notation::Tuplet.new(tuplet_arg) : nil
|
80
|
+
return MusicalScore::Note::Notation::Notation.new(articulation: articulation, dynamics: dynamics, tie: tie, tuplet: tuplet)
|
81
|
+
end
|
82
|
+
|
83
|
+
def export_xml
|
84
|
+
notations_element = REXML::Element.new('notations')
|
85
|
+
articulation_element = REXML::Element.new('articulations')
|
86
|
+
dynamics_element = REXML::Element.new('dynamics')
|
87
|
+
|
88
|
+
if (@articulation)
|
89
|
+
articulation_element.add_element(REXML::Element.new(@articulation.to_s))
|
90
|
+
notations_element.add_element(articulation_element)
|
91
|
+
end
|
92
|
+
if (@dynamics)
|
93
|
+
dynamics_element.add_element(REXML::Element.new(@dynamics.to_s))
|
94
|
+
notations_element.add_element(dynamics_element)
|
95
|
+
end
|
96
|
+
|
97
|
+
notations_element.add_element(@tie.export_xml) if @tie
|
98
|
+
notations_element.add_element(@tuplet.export_xml) if @tuplet
|
99
|
+
|
100
|
+
return notations_element
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
module MusicalScore
|
3
|
+
module Note
|
4
|
+
module Notation
|
5
|
+
class Tie < MusicalScore::ElementBase
|
6
|
+
include Contracts
|
7
|
+
attr_accessor :type
|
8
|
+
Contract Enum[*TYPE_START_STOP_CONTINUE] => Any
|
9
|
+
def initialize(type)
|
10
|
+
@type = type.to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
def export_xml
|
14
|
+
tie_element = REXML::Element.new('tied')
|
15
|
+
tie_element.add_attribute('type',@type.to_s)
|
16
|
+
|
17
|
+
return tie_element
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'contracts'
|
2
|
+
module MusicalScore
|
3
|
+
module Note
|
4
|
+
module Notation
|
5
|
+
class Tuplet < MusicalScore::ElementBase
|
6
|
+
include Contracts
|
7
|
+
attr_accessor :type
|
8
|
+
Contract Enum[*TYPE_START_STOP] => Any
|
9
|
+
def initialize(type)
|
10
|
+
@type = type
|
11
|
+
end
|
12
|
+
|
13
|
+
def export_xml
|
14
|
+
tuplet_element = REXML::Element.new('tuplet')
|
15
|
+
tuplet_element.add_attribute('type', @type.to_s)
|
16
|
+
|
17
|
+
return tuplet_element
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|