music-transcription 0.17.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/examples/hip.rb +4 -4
  3. data/examples/missed_connection.rb +3 -3
  4. data/examples/song1.rb +6 -6
  5. data/examples/song2.rb +3 -3
  6. data/lib/music-transcription.rb +8 -2
  7. data/lib/music-transcription/model/change.rb +9 -3
  8. data/lib/music-transcription/model/measure_score.rb +62 -0
  9. data/lib/music-transcription/model/meter.rb +5 -1
  10. data/lib/music-transcription/model/note.rb +4 -1
  11. data/lib/music-transcription/model/note_score.rb +60 -0
  12. data/lib/music-transcription/model/part.rb +4 -1
  13. data/lib/music-transcription/model/program.rb +5 -2
  14. data/lib/music-transcription/model/tempo.rb +13 -23
  15. data/lib/music-transcription/packing/measure_score_packing.rb +34 -0
  16. data/lib/music-transcription/packing/{score_packing.rb → note_score_packing.rb} +12 -21
  17. data/lib/music-transcription/packing/part_packing.rb +1 -1
  18. data/lib/music-transcription/packing/program_packing.rb +1 -1
  19. data/lib/music-transcription/parsing/convenience_methods.rb +37 -58
  20. data/lib/music-transcription/parsing/numbers/nonnegative_float_parsing.rb +172 -59
  21. data/lib/music-transcription/parsing/numbers/nonnegative_float_parsing.treetop +13 -1
  22. data/lib/music-transcription/parsing/numbers/positive_float_parsing.rb +505 -0
  23. data/lib/music-transcription/parsing/numbers/positive_float_parsing.treetop +35 -0
  24. data/lib/music-transcription/parsing/numbers/positive_integer_parsing.rb +2 -0
  25. data/lib/music-transcription/parsing/numbers/positive_integer_parsing.treetop +2 -0
  26. data/lib/music-transcription/parsing/numbers/positive_rational_parsing.rb +86 -0
  27. data/lib/music-transcription/parsing/numbers/positive_rational_parsing.treetop +21 -0
  28. data/lib/music-transcription/parsing/parseable.rb +32 -0
  29. data/lib/music-transcription/parsing/tempo_parsing.rb +396 -0
  30. data/lib/music-transcription/parsing/tempo_parsing.treetop +49 -0
  31. data/lib/music-transcription/validatable.rb +5 -18
  32. data/lib/music-transcription/version.rb +1 -1
  33. data/spec/model/measure_score_spec.rb +85 -0
  34. data/spec/model/note_score_spec.rb +68 -0
  35. data/spec/model/tempo_spec.rb +15 -15
  36. data/spec/packing/{score_packing_spec.rb → measure_score_packing_spec.rb} +13 -7
  37. data/spec/packing/note_score_packing_spec.rb +100 -0
  38. data/spec/packing/part_packing_spec.rb +1 -1
  39. data/spec/parsing/convenience_methods_spec.rb +80 -81
  40. data/spec/parsing/numbers/nonnegative_float_spec.rb +19 -2
  41. data/spec/parsing/numbers/positive_float_spec.rb +28 -0
  42. data/spec/parsing/numbers/positive_integer_spec.rb +13 -2
  43. data/spec/parsing/numbers/positive_rational_spec.rb +28 -0
  44. data/spec/parsing/tempo_parsing_spec.rb +21 -0
  45. metadata +27 -8
  46. data/lib/music-transcription/model/score.rb +0 -68
  47. data/spec/model/score_spec.rb +0 -69
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5a8173f71d182fdb10c274aa8aa4be1084313fc
4
- data.tar.gz: 0ff97739c5721cdc104f627fe221b920e3f63f6f
3
+ metadata.gz: f5b490ee5916154f2376f07568ccd234ff6fb82a
4
+ data.tar.gz: 2a2fff2f3b7e94deacc2438d510f1d803cf6efcb
5
5
  SHA512:
6
- metadata.gz: 1f021993759bce36baeb58e0123a7ce74a2b3c6663a308b6fc02e78c643a0af666056406be5e847102b80729b938366c494669390bd152450e726b456238dc8a
7
- data.tar.gz: d746f77a31bf4b795bfffaef789fdd4ba828bd9e29aede3fa305f31c52e7570401309e5b205bfa93d0646c9f50ca4d5853a156aeccaf4c6c3cfc32bb7aeb20db
6
+ metadata.gz: 797d3b962ded3291e92d8ba49a390072663d1ae37b0e7e957b3acc562d2d1793d569a7c117fd750de3bb99e03ed4d935cc0b13338c95e669993128acbd246902
7
+ data.tar.gz: e0ae19e64aa43b0dc274d61601db32cbcccf87b33226c312e4f76407f7e87b7694a4f678c32de08bf17a714da5aa2e113a7ca15b470dbc2e8b48dbab07360489
@@ -10,14 +10,14 @@ include Parsing
10
10
  score = Score.new(FOUR_FOUR,120) do |s|
11
11
  s.program = Program.new([0...2, 0...2,2...4,0...2])
12
12
  s.parts["lead"] = Part.new(Dynamics::MF) do |p|
13
- riff = notes("/6Bb3 /4 /12Db4= /6Db4= /36Db4 /36Eb4 /36Db4 /6Ab3 /12Db4 \
14
- /6Bb3 /4 /12Db4= /4Db4= /8=Db4 /8C4")
13
+ riff = "/6Bb3 /4 /12Db4= /6Db4= /36Db4 /36Eb4 /36Db4 /6Ab3 /12Db4 \
14
+ /6Bb3 /4 /12Db4= /4Db4= /8=Db4 /8C4".to_notes
15
15
  p.notes = riff + riff.map {|n| n.transpose(2) }
16
16
  end
17
17
 
18
18
  s.parts["bass"] = Part.new(Dynamics::MP) do |p|
19
- riff = notes("/6Bb2 /4 /3Ab2 /6F2 /12Ab2 \
20
- /6Bb2 /4 /3Ab2 /4Ab2")
19
+ riff = "/6Bb2 /4 /3Ab2 /6F2 /12Ab2 \
20
+ /6Bb2 /4 /3Ab2 /4Ab2".to_notes
21
21
  p.notes = riff + riff.map {|n| n.transpose(2) }
22
22
  end
23
23
  end
@@ -10,9 +10,9 @@ include Parsing
10
10
  score = Score.new(FOUR_FOUR, 120) do |s|
11
11
  s.program = Program.new([0...2,0...6])
12
12
  s.parts["bass"] = Part.new(Dynamics::MF) do |p|
13
- p.notes = notes("/4Eb2 /4 /4Bb2 /4 /4Eb2 /8 /8B2 /4Bb2 /4Ab2")
14
- p.notes += notes("/4Bb2 /8 /8F3= /2F3 /4Bb2 /8 /8F3= /2F3")
15
- p.notes += notes("/4B2 /8 /8Gb3= /2Gb3 /8 /8Gb3= /2Gb3")
13
+ p.notes = "/4Eb2 /4 /4Bb2 /4 /4Eb2 /8 /8B2 /4Bb2 /4Ab2".to_notes
14
+ p.notes += "/4Bb2 /8 /8F3= /2F3 /4Bb2 /8 /8F3= /2F3".to_notes
15
+ p.notes += "/4B2 /8 /8Gb3= /2Gb3 /8 /8Gb3= /2Gb3".to_notes
16
16
  end
17
17
  end
18
18
 
@@ -11,15 +11,15 @@ score = Score.new(FOUR_FOUR, 120) do |s|
11
11
  s.program = Program.new([ 0...4.0, 0...4.0 ])
12
12
 
13
13
  s.parts[1] = Part.new(Dynamics::MF) do |p|
14
- p.notes = notes("3/8C2 /4Eb2 5/16F2 /16Eb2 \
15
- /8 /4C2 /4Eb2 3/8 \
16
- 3/8C2 /4Eb2 5/16F2 /16Eb2 \
17
- /8 /4C2 /4Eb2")
14
+ p.notes = "3/8C2 /4Eb2 5/16F2 /16Eb2 \
15
+ /8 /4C2 /4Eb2 3/8 \
16
+ 3/8C2 /4Eb2 5/16F2 /16Eb2 \
17
+ /8 /4C2 /4Eb2".to_notes
18
18
  end
19
19
 
20
20
  s.parts[2] = Part.new(Dynamics::MF) do |p|
21
- p.notes = notes("/8 /8Bb3 /8Bb3 /8Bb3 /8Bb3 /4C4 /4A3 /8G3 /8F3 5/16=G3 /16=F3 /8E3 /8 \
22
- /8 /8Bb3 /8Bb3 /8Bb3 /8Bb3 /4C4 /8A3 /8E4 /8=E4 /8=D4 /8C4")
21
+ p.notes = "/8 /8Bb3 /8Bb3 /8Bb3 /8Bb3 /4C4 /4A3 /8G3 /8F3 5/16=G3 /16=F3 /8E3 /8 \
22
+ /8 /8Bb3 /8Bb3 /8Bb3 /8Bb3 /4C4 /8A3 /8E4 /8=E4 /8=D4 /8C4".to_notes
23
23
  end
24
24
  end
25
25
 
@@ -10,15 +10,15 @@ score = Score.new(FOUR_FOUR, 120) do |s|
10
10
  s.program = Program.new([0...4.0, 0...4.0 ])
11
11
 
12
12
  s.parts[1] = Part.new(Dynamics::MF) do |p|
13
- p.notes = notes("1C4 1Bb3 1Ab3 /2G3 /2Bb3")
13
+ p.notes = "1C4 1Bb3 1Ab3 /2G3 /2Bb3".to_notes
14
14
  end
15
15
 
16
16
  s.parts[2] = Part.new(Dynamics::MF) do |p|
17
- p.notes = notes("3/8E5 1D5 1C5 5/8C5 /2C5 /2D5")
17
+ p.notes = "3/8E5 1D5 1C5 5/8C5 /2C5 /2D5".to_notes
18
18
  end
19
19
 
20
20
  s.parts[3] = Part.new(Dynamics::MF) do |p|
21
- p.notes = notes("/8 /4G5 /2F5 /4 /4F5 /2Eb5 /4 /4Eb5 /2Eb5 /8 /2Eb5 /2F5")
21
+ p.notes = "/8 /4G5 /2F5 /4 /4F5 /2Eb5 /4 /4Eb5 /2Eb5 /8 /2Eb5 /2F5".to_notes
22
22
  end
23
23
  end
24
24
 
@@ -14,13 +14,16 @@ require 'music-transcription/model/change'
14
14
  require 'music-transcription/model/part'
15
15
  require 'music-transcription/model/program'
16
16
  require 'music-transcription/model/tempo'
17
+ require 'music-transcription/model/note_score'
17
18
  require 'music-transcription/model/meter'
18
19
  require 'music-transcription/model/meters'
19
- require 'music-transcription/model/score'
20
+ require 'music-transcription/model/measure_score'
20
21
 
21
22
  require 'treetop'
22
23
  require 'music-transcription/parsing/numbers/nonnegative_integer_parsing'
23
24
  require 'music-transcription/parsing/numbers/positive_integer_parsing'
25
+ require 'music-transcription/parsing/numbers/positive_float_parsing'
26
+ require 'music-transcription/parsing/numbers/positive_rational_parsing'
24
27
  require 'music-transcription/parsing/numbers/nonnegative_float_parsing'
25
28
  require 'music-transcription/parsing/numbers/nonnegative_rational_parsing'
26
29
  require 'music-transcription/parsing/pitch_parsing'
@@ -34,9 +37,12 @@ require 'music-transcription/parsing/note_parsing'
34
37
  require 'music-transcription/parsing/note_node'
35
38
  require 'music-transcription/parsing/meter_parsing'
36
39
  require 'music-transcription/parsing/segment_parsing'
40
+ require 'music-transcription/parsing/tempo_parsing'
41
+ require 'music-transcription/parsing/parseable'
37
42
  require 'music-transcription/parsing/convenience_methods'
38
43
 
39
44
  require 'music-transcription/packing/change_packing'
40
45
  require 'music-transcription/packing/part_packing'
41
46
  require 'music-transcription/packing/program_packing'
42
- require 'music-transcription/packing/score_packing'
47
+ require 'music-transcription/packing/note_score_packing'
48
+ require 'music-transcription/packing/measure_score_packing'
@@ -17,12 +17,15 @@ class Change
17
17
 
18
18
  class Immediate < Change
19
19
  include Validatable
20
-
21
- @@check_methods = [ :ensure_zero_duration ]
20
+
22
21
  def initialize value
23
22
  super(value,0)
24
23
  end
25
24
 
25
+ def check_methods
26
+ [ :ensure_zero_duration ]
27
+ end
28
+
26
29
  def ensure_zero_duration
27
30
  unless @duration == 0
28
31
  raise NonZeroError, "immediate change duration #{self.duration} must be 0"
@@ -33,11 +36,14 @@ class Change
33
36
  class Gradual < Change
34
37
  include Validatable
35
38
 
36
- @@check_methods = [ :ensure_nonnegative_duration ]
37
39
  def initialize value, transition_duration
38
40
  super(value, transition_duration)
39
41
  end
40
42
 
43
+ def check_methods
44
+ [ :ensure_nonnegative_duration ]
45
+ end
46
+
41
47
  def ensure_nonnegative_duration
42
48
  if @duration < 0
43
49
  raise NegativeError, "gradual change duration #{self.duration} must be non-negative"
@@ -0,0 +1,62 @@
1
+ module Music
2
+ module Transcription
3
+
4
+ class MeasureScore < NoteScore
5
+ attr_accessor :start_meter, :meter_changes
6
+
7
+ def initialize start_meter, start_tempo, meter_changes: {}, tempo_changes: {}, parts: {}, program: Program.new
8
+ @start_meter = start_meter
9
+ @meter_changes = meter_changes
10
+
11
+ super(start_tempo, tempo_changes: tempo_changes, program: program, parts: parts)
12
+ yield(self) if block_given?
13
+ end
14
+
15
+ def check_methods
16
+ super() + [:check_startmeter_type, :check_meterchange_types, :check_meterchange_durs]
17
+ end
18
+
19
+ def validatables
20
+ super() + [ @start_meter ] + @meter_changes.values +
21
+ @meter_changes.values.map {|v| v.value}
22
+ end
23
+
24
+ def valid_tempo_types
25
+ super() + [ Tempo::BPM ]
26
+ end
27
+
28
+ def check_startmeter_type
29
+ unless @start_meter.is_a? Meter
30
+ raise TypeError, "start meter #{@start_meter} is not a Meter object"
31
+ end
32
+ end
33
+
34
+ def check_meterchange_types
35
+ badtypes = @meter_changes.select {|k,v| !v.value.is_a?(Meter) }
36
+ if badtypes.any?
37
+ raise TypeError, "meter change values #{nonmeter_values} are not Meter objects"
38
+ end
39
+ end
40
+
41
+ def check_meterchange_durs
42
+ nonzero_duration = @meter_changes.select {|k,v| v.duration != 0 }
43
+ if nonzero_duration.any?
44
+ raise NonZeroError, "meter changes #{nonzero_duration} have non-zero duration"
45
+ end
46
+ end
47
+
48
+ def ==(other)
49
+ return super() && @start_meter == other.start_meter &&
50
+ @meter_changes == other.meter_changes
51
+ end
52
+
53
+ # Convert to NoteScore object by first converting measure-based offsets to
54
+ # note-based offsets, and eliminating the use of meters. Also, tempo is
55
+ # converted from beats-per-minute to notes-per-minute.
56
+ def to_note_score
57
+
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -3,15 +3,19 @@ module Transcription
3
3
 
4
4
  class Meter
5
5
  include Validatable
6
+
6
7
  attr_reader :measure_duration, :beat_duration, :beats_per_measure
7
8
 
8
- @@check_methods = [ :check_beats_per_measure, :check_beat_duration ]
9
9
  def initialize beats_per_measure, beat_duration
10
10
  @beats_per_measure = beats_per_measure
11
11
  @beat_duration = beat_duration
12
12
  @measure_duration = beats_per_measure * beat_duration
13
13
  end
14
14
 
15
+ def check_methods
16
+ [ :check_beats_per_measure, :check_beat_duration ]
17
+ end
18
+
15
19
  def check_beats_per_measure
16
20
  unless @beats_per_measure > 0
17
21
  raise NonPositiveError, "beats per measure #{@beats_per_measure} is not positive"
@@ -11,7 +11,6 @@ class Note
11
11
 
12
12
  DEFAULT_ARTICULATION = Articulations::NORMAL
13
13
 
14
- @@check_methods = [ :ensure_positive_duration ]
15
14
  def initialize duration, pitches = [], articulation: DEFAULT_ARTICULATION, accented: false, links: {}
16
15
  @duration = duration
17
16
  @pitches = Set.new(pitches).sort
@@ -20,6 +19,10 @@ class Note
20
19
  @links = links
21
20
  end
22
21
 
22
+ def check_methods
23
+ [ :ensure_positive_duration ]
24
+ end
25
+
23
26
  def ensure_positive_duration
24
27
  unless @duration > 0
25
28
  raise NonPositiveError, "duration #{@duration} is not positive"
@@ -0,0 +1,60 @@
1
+ module Music
2
+ module Transcription
3
+
4
+ class NoteScore
5
+ include Validatable
6
+
7
+ attr_accessor :start_tempo, :parts, :program, :tempo_changes
8
+
9
+ def initialize start_tempo, tempo_changes: {}, parts: {}, program: Program.new
10
+ @start_tempo = start_tempo
11
+ @tempo_changes = tempo_changes
12
+ @parts = parts
13
+ @program = program
14
+
15
+ yield(self) if block_given?
16
+ end
17
+
18
+ def check_methods
19
+ [ :check_start_tempo_type, :check_tempo_change_types ]
20
+ end
21
+
22
+ def validatables
23
+ [ @program ] + @tempo_changes.values + @parts.values
24
+ end
25
+
26
+ def valid_tempo_types
27
+ [ Tempo::QNPM, Tempo::NPM, Tempo::NPS ]
28
+ end
29
+
30
+ def check_start_tempo_type
31
+ unless valid_tempo_types.include?(@start_tempo.class)
32
+ raise TypeError, "type of start tempo #{@start_tempo} is not one of valid tempo types: #{valid_tempo_types}"
33
+ end
34
+ end
35
+
36
+ def check_tempo_change_types
37
+ baddtypes = @tempo_changes.select {|k,v| !valid_tempo_types.include?(v.value.class) }
38
+ if baddtypes.any?
39
+ raise NonPositiveError, "type of tempo change values #{baddtypes} are not one of valid tempo types: #{valid_tempo_types}"
40
+ end
41
+ end
42
+
43
+ def clone
44
+ Marshal.load(Marshal.dump(self))
45
+ end
46
+
47
+ def ==(other)
48
+ return @start_tempo == other.start_tempo &&
49
+ @tempo_changes == other.tempo_changes &&
50
+ @parts == other.parts &&
51
+ @program == other.program
52
+ end
53
+
54
+ def duration
55
+ @parts.map {|p| p.duration }.max
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -8,7 +8,6 @@ class Part
8
8
 
9
9
  attr_accessor :start_dynamic, :dynamic_changes, :notes
10
10
 
11
- @@check_methods = [:ensure_start_dynamic, :ensure_dynamic_change_values_range ]
12
11
  def initialize start_dynamic, notes: [], dynamic_changes: {}
13
12
  @notes = notes
14
13
  @start_dynamic = start_dynamic
@@ -17,6 +16,10 @@ class Part
17
16
  yield(self) if block_given?
18
17
  end
19
18
 
19
+ def check_methods
20
+ [:ensure_start_dynamic, :ensure_dynamic_change_values_range ]
21
+ end
22
+
20
23
  def validatables
21
24
  @notes + @dynamic_changes.values
22
25
  end
@@ -9,12 +9,15 @@ class Program
9
9
  include Validatable
10
10
 
11
11
  attr_accessor :segments
12
-
13
- @@check_methods = [:ensure_increasing_segments, :ensure_nonnegative_segments]
12
+
14
13
  def initialize segments = []
15
14
  @segments = segments
16
15
  end
17
16
 
17
+ def check_methods
18
+ [:ensure_increasing_segments, :ensure_nonnegative_segments]
19
+ end
20
+
18
21
  # @return [Float] the sum of all program segment lengths
19
22
  def length
20
23
  segments.inject(0.0) { |length, segment| length + (segment.last - segment.first) }
@@ -1,37 +1,27 @@
1
1
  module Music
2
2
  module Transcription
3
3
 
4
- # Represent the musical tempo, with beats ber minute and beat duration.
5
4
  class Tempo
6
- include Comparable
7
- attr_reader :beats_per_minute, :beat_duration
8
-
9
- def initialize beats_per_minute, beat_duration = Rational(1,4)
10
- @beats_per_minute = beats_per_minute
11
- @beat_duration = beat_duration
5
+ attr_reader :value
6
+ def initialize value
7
+ raise NonPositiveError, "Given tempo value #{value} is not positive" if value <= 0
8
+ @value = value
12
9
  end
13
10
 
14
11
  def ==(other)
15
- (other.beats_per_minute == @beats_per_minute) &&
16
- (other.beat_duration == @beat_duration)
17
- end
18
-
19
- def notes_per_second
20
- (@beats_per_minute * @beat_duration) / 60.0
12
+ self.class == other.class && self.value == other.value
21
13
  end
22
14
 
23
- def between? a, b
24
- notes_per_second.between? a, b
25
- end
26
-
27
- def <=>(other)
28
- if other.is_a? Tempo
29
- notes_per_second <=> other.notes_per_second
30
- else
31
- notes_per_second <=> other
15
+ [ :qnpm, :bpm, :npm, :nps ].each do |sym|
16
+ klass = Class.new(Tempo) do
17
+ def to_s
18
+ "#{@value}#{self.class::PRINT_SYM}"
19
+ end
32
20
  end
21
+ klass.const_set(:PRINT_SYM,sym)
22
+ Tempo.const_set(sym.upcase,klass)
33
23
  end
34
24
  end
35
25
 
36
26
  end
37
- end
27
+ end
@@ -0,0 +1,34 @@
1
+ module Music
2
+ module Transcription
3
+
4
+ class MeasureScore
5
+ def pack
6
+ hash = super()
7
+ hash["start_meter"] = start_meter.to_s
8
+ hash["meter_changes"] = Hash[ meter_changes.map do |offset,change|
9
+ a = change.pack
10
+ a[0] = a[0].to_s
11
+ [offset,a]
12
+ end ]
13
+ return hash
14
+ end
15
+
16
+ def self.unpack packing
17
+ unpacked_start_meter = Meter.parse(packing["start_meter"])
18
+ unpacked_mcs = Hash[ packing["meter_changes"].map do |k,v|
19
+ v = v.clone
20
+ v[0] = Meter.parse(v[0])
21
+ [k, Change.from_ary(v) ]
22
+ end ]
23
+
24
+ note_score = NoteScore.unpack(packing)
25
+
26
+ new(unpacked_start_meter, note_score.start_tempo,
27
+ meter_changes: unpacked_mcs, tempo_changes: note_score.tempo_changes,
28
+ program: note_score.program, parts: note_score.parts
29
+ )
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -1,19 +1,15 @@
1
1
  module Music
2
2
  module Transcription
3
3
 
4
- class Score
4
+ class NoteScore
5
5
  def pack
6
- packed_start_meter = start_meter.to_s
7
- packed_mcs = Hash[ meter_changes.map do |offset,change|
6
+ packed_starttempo = start_tempo.to_s
7
+ packed_tcs = Hash[ tempo_changes.map do |offset,change|
8
8
  a = change.pack
9
9
  a[0] = a[0].to_s
10
10
  [offset,a]
11
11
  end ]
12
12
 
13
- packed_tcs = Hash[ tempo_changes.map do |k,v|
14
- [k,v.to_ary]
15
- end ]
16
-
17
13
  packed_parts = Hash[
18
14
  @parts.map do |name,part|
19
15
  [ name, part.pack ]
@@ -21,9 +17,7 @@ class Score
21
17
  ]
22
18
  packed_prog = program.pack
23
19
 
24
- { "start_meter" => packed_start_meter,
25
- "meter_changes" => packed_mcs,
26
- "start_tempo" => start_tempo,
20
+ { "start_tempo" => packed_starttempo,
27
21
  "tempo_changes" => packed_tcs,
28
22
  "program" => packed_prog,
29
23
  "parts" => packed_parts,
@@ -31,27 +25,24 @@ class Score
31
25
  end
32
26
 
33
27
  def self.unpack packing
34
- unpacked_start_meter = Parsing::meter(packing["start_meter"])
35
- unpacked_mcs = Hash[ packing["meter_changes"].map do |k,v|
28
+ unpacked_starttempo = Tempo.parse(packing["start_tempo"])
29
+ unpacked_tcs = Hash[ packing["tempo_changes"].map do |k,v|
36
30
  v = v.clone
37
- v[0] = Parsing::meter(v[0])
31
+ v[0] = Tempo.parse(v[0])
38
32
  [k, Change.from_ary(v) ]
39
33
  end ]
40
34
 
41
- unpacked_tcs = Hash[ packing["tempo_changes"].map do |k,v|
42
- [k, Change.from_ary(v)]
43
- end ]
44
-
45
35
  unpacked_parts = Hash[ packing["parts"].map do |name,packed|
46
36
  [name, Part.unpack(packed)]
47
37
  end ]
48
38
 
49
39
  unpacked_prog = Program.unpack packing["program"]
50
40
 
51
- new(unpacked_start_meter, packing["start_tempo"],
52
- meter_changes: unpacked_mcs, tempo_changes: unpacked_tcs,
53
- program: unpacked_prog, parts: unpacked_parts
54
- )
41
+ new(unpacked_starttempo,
42
+ tempo_changes: unpacked_tcs,
43
+ program: unpacked_prog,
44
+ parts: unpacked_parts
45
+ )
55
46
  end
56
47
  end
57
48