musical_score 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8b09d9932a8034a704c30a63a3bf1f2c656788e9
4
- data.tar.gz: db84bae2d9473dfda8d6ab146ad0effd966de5d5
3
+ metadata.gz: f4fe9ce7d2dc51b7136d205eef2d8401b67c1e0b
4
+ data.tar.gz: 339ccef7ae5b6bf7492a5e8e3d9d4a5c830b3579
5
5
  SHA512:
6
- metadata.gz: e16f49f188756a8738f2a2b533f9b1d9bbe6b8fc19d5aa507432ed23b2dff3ccd73bae9125bb021832a349d29d5f0cdb04f1982261985ad6f74cf6ed9e347474
7
- data.tar.gz: ee2052aa91df90bd32184c2e83c8e50dada2928dd6b88fbce9eda6c128ae3822fcddc9158f5f8924703ccd767cc670c061ffd584f4f54388a2703377efd4e641
6
+ metadata.gz: 07b419d4fd50b20fb505954537794fec98b24eddb2c3bddcad8fb16dd0f015f53ca9f386e9766de725590a716a41c0294a8485a88e4f4689f2a4fd0278fd75e6
7
+ data.tar.gz: cf3d0a5a58b34be0364668b29ef635cd11c64741bacca005ba33f15b32bec295665ae987c48e1c8fedd9208714c75d9f563909e73ec19c0a44b3db3a3e5b536c
data/.rspec CHANGED
@@ -1,2 +1,2 @@
1
- --format Fuubar
1
+ --format documentation
2
2
  --color
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/yumaito/musical_score.svg?branch=master)](https://travis-ci.org/yumaito/musical_score)
4
4
  [![Code Climate](https://codeclimate.com/github/yumaito/musical_score/badges/gpa.svg)](https://codeclimate.com/github/yumaito/musical_score)
5
+ [![Gem Version](https://badge.fury.io/rb/musical_score.svg)](https://badge.fury.io/rb/musical_score)
5
6
 
6
7
  Library for representing and analysing musical score.
7
8
  This library is implemented along with the definitions of [MusicXML](http://www.musicxml.com/) mainly.
@@ -32,9 +33,15 @@ require 'musical_score'
32
33
 
33
34
  musical_score = MusicalScore::IO.import("path/to/musicxml.xml")
34
35
  ```
35
-
36
36
  Now you can handle the musical score as a ruby class object.
37
37
 
38
+ For example, if you want to know the pitch of the first note information:
39
+ ```ruby
40
+ pitch = musical_score.part[0].measures[0].notes[0].pitch
41
+ puts pitch
42
+ # E3
43
+ ```
44
+
38
45
  ## Contributing
39
46
 
40
47
  Bug reports and pull requests are welcome on GitHub at https://github.com/yumaito/musical_score. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -50,6 +50,17 @@ module MusicalScore
50
50
  return attributes
51
51
  end
52
52
 
53
+ Contract HashOf[String => Any] => MusicalScore::Attribute::Attribute
54
+ def self.create_by_hash(doc)
55
+ divisions = doc["divisions"][0].to_i
56
+ clef = doc.has_key?("clef") ? MusicalScore::Attribute::Clef.create_by_hash(doc["clef"][0]) : nil
57
+ time = doc.has_key?("time") ? MusicalScore::Attribute::Time.create_by_hash(doc["time"][0]) : nil
58
+ key = doc.has_key?("key") ? MusicalScore::Attribute::Key.create_by_hash(doc["key"][0]) : nil
59
+
60
+ attributes = MusicalScore::Attribute::Attribute.new(divisions: divisions, clef: clef, key: key, time: time)
61
+ return attributes
62
+ end
63
+
53
64
  def export_xml
54
65
  attribute_element = REXML::Element.new('attributes')
55
66
  divisions_element = REXML::Element.new('divisions').add_text(@divisions.to_s)
@@ -27,6 +27,15 @@ module MusicalScore
27
27
  return clef
28
28
  end
29
29
 
30
+ Contract HashOf[String => Any] => MusicalScore::Attribute::Clef
31
+ def self.create_by_hash(doc)
32
+ sign = doc["sign"][0].to_sym
33
+ line = doc.has_key?("line") ? doc["line"][0].to_i : 0
34
+ clef_octave_change = doc.has_key?("clef-octave-change") ? doc["clef-octave-change"][0].to_i : 0
35
+ clef = MusicalScore::Attribute::Clef.new(sign, line, clef_octave_change)
36
+ return clef
37
+ end
38
+
30
39
  def export_xml
31
40
  clef_element = REXML::Element.new('clef')
32
41
  sign_element = REXML::Element.new('sign').add_text(@sign.to_s)
@@ -41,4 +50,4 @@ module MusicalScore
41
50
  end
42
51
  end
43
52
  end
44
- end
53
+ end
@@ -3,7 +3,7 @@ module MusicalScore
3
3
  module Attribute
4
4
  class Key < MusicalScore::ElementBase
5
5
  include Contracts
6
- @@mode = %i(major :minor)
6
+ @@mode = %i(major minor)
7
7
  @@circle_of_fifths = [0, 7, 2, 9, 4, 11, 6, 1, 8, 3, 10, 5]
8
8
 
9
9
  attr_reader :fifths, :mode
@@ -59,6 +59,13 @@ module MusicalScore
59
59
  return MusicalScore::Attribute::Key.new(fifths, mode)
60
60
  end
61
61
 
62
+ Contract HashOf[String => Any] => MusicalScore::Attribute::Key
63
+ def self.create_by_hash(doc)
64
+ fifths = doc["fifths"][0].to_i
65
+ mode = doc["mode"][0].to_sym
66
+ return MusicalScore::Attribute::Key.new(fifths, mode)
67
+ end
68
+
62
69
  def export_xml
63
70
  key_element = REXML::Element.new('key')
64
71
  fifths_element = REXML::Element.new('fifths').add_text(@fifths.to_s)
@@ -71,4 +78,4 @@ module MusicalScore
71
78
  end
72
79
  end
73
80
  end
74
- end
81
+ end
@@ -25,6 +25,13 @@ module MusicalScore
25
25
  return MusicalScore::Attribute::Time.new(beats, beat_type)
26
26
  end
27
27
 
28
+ Contract HashOf[String => Any] => MusicalScore::Attribute::Time
29
+ def self.create_by_hash(doc)
30
+ beats = doc["beats"][0].to_i
31
+ beat_type = doc["beat-type"][0].to_i
32
+ return MusicalScore::Attribute::Time.new(beats, beat_type)
33
+ end
34
+
28
35
  def export_xml
29
36
  time = REXML::Element.new('time')
30
37
  beats = REXML::Element.new('beats')
@@ -10,6 +10,10 @@ module MusicalScore
10
10
  raise "Called abstract method: create_by_xml"
11
11
  end
12
12
 
13
+ def self.create_by_hash(hash)
14
+ raise "Called abstract method: create_by_hash"
15
+ end
16
+
13
17
  def export_xml
14
18
  raise "Called abstract method: export_xml"
15
19
  end
@@ -0,0 +1,16 @@
1
+ require 'musical_score'
2
+ require 'rexml/document'
3
+ require 'rexml/formatters/pretty'
4
+ module MusicalScore
5
+ module IO
6
+ def export_xml(path, score)
7
+ formatter = REXML::Formatters::Pretty.new(4)
8
+ formatter.compact = true
9
+ File.open(path, 'w') do |file|
10
+ formatter.write(score.export_xml, file)
11
+ end
12
+ end
13
+
14
+ module_function :export_xml
15
+ end
16
+ end
@@ -1,12 +1,13 @@
1
1
  require 'musical_score'
2
2
  require 'rexml/document'
3
+ require 'xmlsimple'
3
4
  module MusicalScore
4
5
  module IO
5
6
  def import(file)
6
7
  extname = File.extname(file)
7
8
  case extname
8
9
  when ".xml"
9
- return import_xml(file)
10
+ return import_xml_via_hash(file)
10
11
  else
11
12
  raise MusicalScore::InvalidFileType
12
13
  end
@@ -17,6 +18,12 @@ module MusicalScore
17
18
  return score
18
19
  end
19
20
 
20
- module_function :import, :import_xml
21
+ def import_xml_via_hash(file_path)
22
+ doc = XmlSimple.xml_in(open(file_path))
23
+ score = MusicalScore::Score::Score.create_by_hash(doc, file_path)
24
+ return score
25
+ end
26
+
27
+ module_function :import, :import_xml, :import_xml_via_hash
21
28
  end
22
29
  end
@@ -21,6 +21,10 @@ module MusicalScore
21
21
  end
22
22
  end
23
23
 
24
+ def last
25
+ return @measures[@measures.size-1]
26
+ end
27
+
24
28
  def all_notes
25
29
  result = Array.new
26
30
  @measures.each do |measure|
@@ -25,6 +25,14 @@ module MusicalScore
25
25
  return MusicalScore::Note::Lyric.new(text, syllabic, is_extend)
26
26
  end
27
27
 
28
+ Contract HashOf[String => Any] => MusicalScore::Note::Lyric
29
+ def self.create_by_hash(doc)
30
+ syllabic = doc.has_key?("syllabic") ? doc["syllabic"][0].to_sym : nil
31
+ text = doc["text"][0]
32
+ is_extend = doc.has_key?("extend")
33
+ return MusicalScore::Note::Lyric.new(text, syllabic, is_extend)
34
+ end
35
+
28
36
  def export_xml(number)
29
37
  lyric_element = REXML::Element.new('lyric')
30
38
  lyric_element.add_attribute('number', number.to_s)
@@ -40,4 +48,4 @@ module MusicalScore
40
48
  end
41
49
  end
42
50
  end
43
- end
51
+ end
@@ -80,6 +80,17 @@ module MusicalScore
80
80
  return MusicalScore::Note::Notation::Notation.new(articulation: articulation, dynamics: dynamics, tie: tie, tuplet: tuplet)
81
81
  end
82
82
 
83
+ Contract HashOf[String => Any] => MusicalScore::Note::Notation::Notation
84
+ def self.create_by_hash(doc)
85
+ articulation = doc.has_key?("articulations") ? doc["articulations"][0].keys[0].to_sym : nil
86
+ dynamics = doc.has_key?("dynamics") ? doc["dynamics"][0].keys[0].to_sym : nil
87
+ tie_arg = doc.has_key?("tied") ? doc.dig("tied", 0, "type").to_sym : nil
88
+ tie = tie_arg ? MusicalScore::Note::Notation::Tie.new(tie_arg) : nil
89
+ tuplet_arg = doc.has_key?("tuplet") ? doc.dig("tuplet", 0, "type").to_sym : nil
90
+ tuplet = tuplet_arg ? MusicalScore::Note::Notation::Tuplet.new(tuplet_arg) : nil
91
+ return MusicalScore::Note::Notation::Notation.new(articulation: articulation, dynamics: dynamics, tie: tie, tuplet: tuplet)
92
+ end
93
+
83
94
  def export_xml
84
95
  notations_element = REXML::Element.new('notations')
85
96
  articulation_element = REXML::Element.new('articulations')
@@ -113,6 +113,26 @@ module MusicalScore
113
113
  end
114
114
  end
115
115
 
116
+ Contract HashOf[String => Any] => MusicalScore::Note::Note
117
+ def self.create_by_hash(doc)
118
+ dots = doc.has_key?("dot") ? doc["dot"].size : 0
119
+ duration = doc["duration"][0].to_i
120
+ type = MusicalScore::Note::Type.new(doc["type"][0])
121
+ tie = doc.has_key?("tie") ? doc.dig("tie", 0, "type").to_sym : nil
122
+ notation = doc.has_key?("notations") ? MusicalScore::Note::Notation::Notation.create_by_hash(doc["notations"][0]) : nil
123
+ time_modification = doc.has_key?("time-modification") ? MusicalScore::Note::TimeModification.create_by_hash(doc["time-modification"][0]) : nil
124
+ rest = doc.has_key?("rest")
125
+
126
+ if (rest)
127
+ return MusicalScore::Note::Note.new(duration: duration, tie: tie, dot: dots, rest: rest, type: type, time_modification: time_modification, notation: notation)
128
+ else
129
+ pitch = MusicalScore::Note::Pitch.create_by_hash(doc["pitch"][0])
130
+ lyric = doc.has_key?("lyric") ? MusicalScore::Note::Lyric.create_by_hash(doc["lyric"][0]) : nil
131
+ return MusicalScore::Note::Note.new(duration: duration, tie: tie, dot: dots, type: type, lyric: lyric, pitch: pitch, time_modification: time_modification, notation: notation)
132
+ end
133
+
134
+ end
135
+
116
136
  def export_xml
117
137
  note_element = REXML::Element.new('note')
118
138
  note_element.add_element('rest') if @rest
@@ -100,6 +100,14 @@ module MusicalScore
100
100
  return MusicalScore::Note::Pitch.new(step, alter, octave)
101
101
  end
102
102
 
103
+ Contract HashOf[String => Any] => MusicalScore::Note::Pitch
104
+ def self.create_by_hash(doc)
105
+ step = doc["step"][0].to_sym
106
+ octave = doc["octave"][0].to_i
107
+ alter = doc.has_key?("alter") ? doc["alter"][0].to_i : 0
108
+ return MusicalScore::Note::Pitch.new(step, alter, octave)
109
+ end
110
+
103
111
  def export_xml
104
112
  pitch_element = REXML::Element.new('pitch')
105
113
  step_element = REXML::Element.new('step').add_text(@step.to_s)
@@ -18,6 +18,13 @@ module MusicalScore
18
18
  return MusicalScore::Note::TimeModification.new(actual_notes, normal_notes)
19
19
  end
20
20
 
21
+ Contract HashOf[String => Any] => MusicalScore::Note::TimeModification
22
+ def self.create_by_hash(doc)
23
+ actual_notes = doc["actual-notes"][0].to_i
24
+ normal_notes = doc["normal-notes"][0].to_i
25
+ return MusicalScore::Note::TimeModification.new(actual_notes, normal_notes)
26
+ end
27
+
21
28
  def export_xml
22
29
  time_modification_element = REXML::Element.new('time-modification')
23
30
  actual_notes_element = REXML::Element.new('actual-notes').add_text(@actual_notes.to_s)
@@ -30,4 +37,4 @@ module MusicalScore
30
37
  end
31
38
  end
32
39
  end
33
- end
40
+ end
@@ -29,6 +29,19 @@ module MusicalScore
29
29
  return MusicalScore::Part::Measure.new(notes, number, attributes)
30
30
  end
31
31
 
32
+ Contract HashOf[String => Any] => MusicalScore::Part::Measure
33
+ def self.create_by_hash(doc)
34
+ number = doc["number"].to_i
35
+ attributes = doc.has_key?("attributes") ? MusicalScore::Attribute::Attribute.create_by_hash(doc["attributes"][0]) : nil
36
+ note_array = Array.new
37
+ doc["note"].each do |element|
38
+ note = MusicalScore::Note::Note.create_by_hash(element)
39
+ note_array.push(note)
40
+ end
41
+ notes = MusicalScore::Notes.new(note_array)
42
+ return MusicalScore::Part::Measure.new(notes, number, attributes)
43
+ end
44
+
32
45
  def export_xml
33
46
  measure_element = REXML::Element.new('measure')
34
47
  measure_element.add_attribute('number',@number.to_s)
@@ -26,6 +26,17 @@ module MusicalScore
26
26
  return MusicalScore::Part::Part.new(measures)
27
27
  end
28
28
 
29
+ Contract HashOf[String => Any] => MusicalScore::Part::Part
30
+ def self.create_by_hash(doc)
31
+ measure_array = Array.new
32
+ doc["measure"].each do |element|
33
+ measure = MusicalScore::Part::Measure.create_by_hash(element)
34
+ measure_array.push(measure)
35
+ end
36
+ measures = MusicalScore::Measures.new(measure_array)
37
+ return MusicalScore::Part::Part.new(measures)
38
+ end
39
+
29
40
  def export_xml(number)
30
41
  part = REXML::Element.new('part')
31
42
  part.add_attribute('id', "P" + number.to_s)
@@ -17,6 +17,14 @@ module MusicalScore
17
17
  name = xml_doc.text
18
18
  return MusicalScore::Score::Identification::Creator.new(name, type)
19
19
  end
20
+
21
+ Contract HashOf[String => Any] => MusicalScore::Score::Identification::Creator
22
+ def self.create_by_hash(doc)
23
+ type = doc["type"].to_sym
24
+ name = doc["content"]
25
+ return MusicalScore::Score::Identification::Creator.new(name, type)
26
+ end
27
+
20
28
  def export_xml
21
29
  creator = REXML::Element.new('creator')
22
30
  creator.add_attribute('type', @type)
@@ -36,6 +36,28 @@ module MusicalScore
36
36
  return MusicalScore::Score::Identification::Encoding.new(encoding_date, encoding_description, softwares, supports)
37
37
  end
38
38
 
39
+ Contract HashOf[String => Any] => MusicalScore::Score::Identification::Encoding
40
+ def self.create_by_hash(doc)
41
+ encoding_date = Time.new
42
+ if (doc.has_key?("encoding-date"))
43
+ encoding_date = Time.parse(doc["encoding-date"][0])
44
+ end
45
+ encoding_description = doc.has_key?("encoding_description") ? doc["encoding_date"] : ''
46
+ softwares = Array.new
47
+ if doc.has_key?("software")
48
+ doc["software"].each do |element|
49
+ softwares.push(element)
50
+ end
51
+ end
52
+ supports = Array.new
53
+ doc["supports"].each do |element|
54
+ if (element["type"] == "yes")
55
+ supports.push(element["element"])
56
+ end
57
+ end
58
+ return MusicalScore::Score::Identification::Encoding.new(encoding_date, encoding_description, softwares, supports)
59
+ end
60
+
39
61
  def export_xml
40
62
  encoding = REXML::Element.new('encoding')
41
63
  @softwares.each do |software|
@@ -32,6 +32,18 @@ module MusicalScore
32
32
  return MusicalScore::Score::Identification::Identification.new(creators, encoding)
33
33
  end
34
34
 
35
+ Contract HashOf[String => Any] => MusicalScore::Score::Identification::Identification
36
+ def self.create_by_hash(doc)
37
+ creators = Array.new
38
+ if (doc.has_key?("creator"))
39
+ doc["creator"].each do |element|
40
+ creators.push(MusicalScore::Score::Identification::Creator.create_by_hash(element))
41
+ end
42
+ end
43
+ encoding = doc.has_key?("encoding") ? MusicalScore::Score::Identification::Encoding.create_by_hash(doc["encoding"][0]) : nil
44
+ return MusicalScore::Score::Identification::Identification.new(creators, encoding)
45
+ end
46
+
35
47
  def export_xml
36
48
  identification = REXML::Element.new('identification')
37
49
  @creators.each do |creator|
@@ -72,7 +72,43 @@ module MusicalScore
72
72
  return MusicalScore::Score::Score.new(args)
73
73
  end
74
74
 
75
- def export_xml(path)
75
+ Contract HashOf[String => Any], Maybe[String] => MusicalScore::Score::Score
76
+ def self.create_by_hash(doc, file_path)
77
+ args = {}
78
+ args[:file_path] = file_path
79
+
80
+ if doc.has_key?("identification")
81
+ identification = MusicalScore::Score::Identification::Identification.create_by_hash(doc["identification"][0])
82
+ args[:identification] = identification
83
+ end
84
+
85
+ credits = Array.new
86
+ doc["credit"].each do |element|
87
+ if (element.has_key?("credit-words"))
88
+ credits.push(element.dig("credit-words", 0, "content"))
89
+ end
90
+ end
91
+ args[:credits] = credits
92
+
93
+ part_list = Array.new
94
+ doc.dig("part-list", 0, "score-part").each do |element|
95
+ part_name = element["part-name"][0]
96
+ part_abbreviation = element["part-abbreviation"][0]
97
+ part = MusicalScore::Score::Part::Part.new(part_name, part_abbreviation)
98
+ part_list.push(part)
99
+ end
100
+ args[:part_list] = part_list
101
+
102
+ parts = Array.new
103
+ doc["part"].each do |element|
104
+ part = MusicalScore::Part::Part.create_by_hash(element)
105
+ parts.push(part)
106
+ end
107
+ args[:parts] = parts
108
+ return MusicalScore::Score::Score.new(args)
109
+ end
110
+
111
+ def export_xml()
76
112
  doc = REXML::Document.new
77
113
  doc << REXML::XMLDecl.new('1.0', 'UTF-8')
78
114
  doc << REXML::Document.new(<<-EOS).doctype
@@ -108,12 +144,7 @@ module MusicalScore
108
144
 
109
145
  doc.add_element(score_partwise)
110
146
 
111
- xml = ''
112
- formatter = REXML::Formatters::Pretty.new(4)
113
- formatter.compact = true
114
- formatter.write(doc, xml)
115
-
116
- # puts xml
147
+ return doc
117
148
  end
118
149
 
119
150
  def set_location
@@ -1,4 +1,4 @@
1
1
  module MusicalScore
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  APP_NAME = "MusicalScore"
4
4
  end
@@ -34,9 +34,9 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "bundler", "~> 1.13"
35
35
  spec.add_development_dependency "rake", "~> 10.0"
36
36
  spec.add_development_dependency "rspec", "~> 3.1"
37
- spec.add_development_dependency "fuubar"
38
37
  spec.add_development_dependency "yard"
39
38
  spec.add_development_dependency "yard-contracts"
40
39
 
41
40
  spec.add_dependency "contracts"
41
+ spec.add_dependency "xml-simple"
42
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: musical_score
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuma Ito
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-19 00:00:00.000000000 Z
11
+ date: 2016-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.1'
55
55
  - !ruby/object:Gem::Dependency
56
- name: fuubar
56
+ name: yard
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -67,7 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: yard
70
+ name: yard-contracts
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - ">="
@@ -81,13 +81,13 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: yard-contracts
84
+ name: contracts
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
- type: :development
90
+ type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
@@ -95,7 +95,7 @@ dependencies:
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
- name: contracts
98
+ name: xml-simple
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
@@ -136,6 +136,7 @@ files:
136
136
  - lib/musical_score/const.rb
137
137
  - lib/musical_score/element_base.rb
138
138
  - lib/musical_score/errors.rb
139
+ - lib/musical_score/io/exporter.rb
139
140
  - lib/musical_score/io/importer.rb
140
141
  - lib/musical_score/location.rb
141
142
  - lib/musical_score/measures.rb