musical_score 0.1.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.
- 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
|