musicality 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog.md +30 -0
  3. data/lib/musicality/errors.rb +1 -0
  4. data/lib/musicality/notation/conversion/change_conversion.rb +63 -3
  5. data/lib/musicality/notation/conversion/note_time_converter.rb +23 -5
  6. data/lib/musicality/notation/conversion/score_conversion.rb +60 -0
  7. data/lib/musicality/notation/conversion/score_converter.rb +105 -0
  8. data/lib/musicality/notation/model/change.rb +98 -28
  9. data/lib/musicality/notation/model/part.rb +1 -1
  10. data/lib/musicality/notation/model/score.rb +4 -4
  11. data/lib/musicality/notation/packing/change_packing.rb +35 -25
  12. data/lib/musicality/notation/packing/score_packing.rb +2 -2
  13. data/lib/musicality/notation/util/function.rb +99 -0
  14. data/lib/musicality/notation/util/piecewise_function.rb +79 -99
  15. data/lib/musicality/notation/util/transition.rb +12 -0
  16. data/lib/musicality/notation/util/value_computer.rb +12 -152
  17. data/lib/musicality/performance/conversion/score_collator.rb +35 -20
  18. data/lib/musicality/performance/midi/part_sequencer.rb +2 -5
  19. data/lib/musicality/validatable.rb +6 -1
  20. data/lib/musicality/version.rb +1 -1
  21. data/lib/musicality.rb +4 -4
  22. data/musicality.gemspec +1 -0
  23. data/spec/notation/conversion/change_conversion_spec.rb +216 -9
  24. data/spec/notation/conversion/measure_note_map_spec.rb +2 -2
  25. data/spec/notation/conversion/note_time_converter_spec.rb +91 -9
  26. data/spec/notation/conversion/{measured_score_conversion_spec.rb → score_conversion_spec.rb} +44 -9
  27. data/spec/notation/conversion/score_converter_spec.rb +246 -0
  28. data/spec/notation/model/change_spec.rb +139 -36
  29. data/spec/notation/model/part_spec.rb +3 -3
  30. data/spec/notation/model/score_spec.rb +4 -4
  31. data/spec/notation/packing/change_packing_spec.rb +222 -71
  32. data/spec/notation/packing/part_packing_spec.rb +1 -1
  33. data/spec/notation/packing/score_packing_spec.rb +3 -2
  34. data/spec/notation/util/function_spec.rb +43 -0
  35. data/spec/notation/util/transition_spec.rb +51 -0
  36. data/spec/notation/util/value_computer_spec.rb +43 -87
  37. data/spec/performance/conversion/score_collator_spec.rb +46 -7
  38. data/spec/performance/midi/part_sequencer_spec.rb +2 -1
  39. metadata +29 -14
  40. data/lib/musicality/notation/conversion/measured_score_conversion.rb +0 -70
  41. data/lib/musicality/notation/conversion/measured_score_converter.rb +0 -95
  42. data/lib/musicality/notation/conversion/unmeasured_score_conversion.rb +0 -47
  43. data/lib/musicality/notation/conversion/unmeasured_score_converter.rb +0 -64
  44. data/spec/notation/conversion/measured_score_converter_spec.rb +0 -329
  45. data/spec/notation/conversion/unmeasured_score_conversion_spec.rb +0 -71
  46. data/spec/notation/conversion/unmeasured_score_converter_spec.rb +0 -116
@@ -0,0 +1,99 @@
1
+ module Musicality
2
+
3
+ class Function
4
+ DOMAIN_MIN, DOMAIN_MAX = -Float::INFINITY, Float::INFINITY
5
+
6
+ def sample xrange, srate
7
+ xrange.step(Rational(1,srate)).map { |x| at(x) }
8
+ end
9
+
10
+ # x in start domain, transformed to x in end domain
11
+ def self.transform_domains start_domain, end_domain, x
12
+ perc = (x - start_domain.first) / (start_domain.last - start_domain.first).to_f
13
+ return perc * (end_domain.last - end_domain.first) + end_domain.first
14
+ end
15
+
16
+ class Constant < Function
17
+ attr_reader :value
18
+
19
+ def initialize value
20
+ @value = value
21
+ end
22
+
23
+ def at(x)
24
+ @value
25
+ end
26
+
27
+ def ==(other)
28
+ super(other) && @value == other.value
29
+ end
30
+ end
31
+
32
+ class Linear < Function
33
+ attr_reader :slope, :intercept
34
+
35
+ def initialize p1,p2
36
+ @slope = (p2[1] - p1[1])/(p2[0] - p1[0]).to_f
37
+ @intercept = p1[1] - @slope * p1[0]
38
+ end
39
+
40
+ def at(x)
41
+ x * @slope + @intercept
42
+ end
43
+
44
+ def ==(other)
45
+ super(other) && @slope == other.slope && @intercept == other.intercept
46
+ end
47
+ end
48
+
49
+ class Sigmoid < Function
50
+ def self.sigm x
51
+ 1.0 / (1 + Math::exp(-x))
52
+ end
53
+
54
+ #def self.inv_sigm y
55
+ # -Math::log((1-y)/y.to_f)
56
+ #end
57
+
58
+ SIGM_DOMAIN = -5..5
59
+ SIGM_RANGE = Sigmoid.sigm(SIGM_DOMAIN.first)..Sigmoid.sigm(SIGM_DOMAIN.last)
60
+ SIGM_SPAN = SIGM_RANGE.last - SIGM_RANGE.first
61
+
62
+ attr_reader :y0, :dy, :domain
63
+ def initialize p0, p1
64
+ @y0, y1 = p0[1], p1[1]
65
+ @dy = y1 - @y0
66
+ @domain = p0[0]..p1[0]
67
+ end
68
+
69
+ def at(x)
70
+ x_ = Function.transform_domains(@domain, SIGM_DOMAIN, x)
71
+ y_ = (Sigmoid.sigm(x_) - SIGM_RANGE.first) / SIGM_SPAN
72
+ y = @y0 + y_ * @dy
73
+ return y
74
+ end
75
+
76
+ #def from(y)
77
+ # y2 = (y - @y0) / @dy
78
+ # x2 = Sigmoid.inv_sigm(y2 * SIGM_SPAN + SIGM_RANGE.first)
79
+ # x = Function.transform_domains(SIGM_DOMAIN, @domain, x2)
80
+ # return x
81
+ #end
82
+
83
+ # Given a domain, an xy-point in that domain, and the y-value at
84
+ # the end of the domain, find the y-value at the start of the domain,
85
+ # assuming the the function is sigmoid.
86
+ def self.find_y0 domain, pt, y1
87
+ x,y = pt
88
+ x_ = Function.transform_domains(domain, SIGM_DOMAIN, x)
89
+ y_ = (sigm(x_) - SIGM_RANGE.first) / SIGM_SPAN
90
+ return Function::Linear.new([y_,y],[1,y1]).at(0)
91
+ end
92
+
93
+ def ==(other)
94
+ super(other) && @y0 == other.y0 && @dy == other.dy
95
+ end
96
+ end
97
+ end
98
+
99
+ end
@@ -1,121 +1,101 @@
1
1
  module Musicality
2
2
 
3
- # Combine functions that are each applicable for a non-overlapping domain.
4
- #
5
- # @author James Tunnell
6
- class PiecewiseFunction
7
- attr_reader :pieces
8
-
9
- # Take an array of points (each point is a two-element array pair) and
10
- # create a piecewise function to calculate values in-between.
11
- def initialize points = []
12
- @pieces = { }
3
+ class Function
4
+ # Combine functions that are each applicable for a non-overlapping domain.
5
+ #
6
+ # @author James Tunnell
7
+ class Piecewise < Function
8
+ attr_reader :pieces
13
9
 
14
- points = points.sort_by {|p| p[0]}
15
-
16
- if points.count > 1
17
- if points.is_a?(Hash)
18
- points = points.to_a
19
- end
20
-
21
- for i in 1...points.count
22
- add_points points[i-1], points[i]
23
- end
10
+ # Take an array of points (each point is a two-element array pair) and
11
+ # create a piecewise function to calculate values in-between.
12
+ def initialize
13
+ @pieces = { }
24
14
  end
25
- end
26
-
27
- def add_points prev_point, point
28
- domain = prev_point[0]..point[0]
29
- func = lambda do |x|
30
- perc = (x - domain.min).to_f / (domain.max - domain.min)
31
- y = Interpolation.linear prev_point[1], point[1], perc
32
- return y
33
- end
34
- add_piece(domain, func)
35
- end
36
-
37
- # Add a function piece, which covers the given domain (includes domain start
38
- # but not the end).
39
- # @param [Range] domain The function domain. If this overlaps an existing domain,
40
- # the existing domain will be split with the non-
41
- # overlapping pieces kept and the overlapping old piece
42
- # discarded.
43
- def add_piece domain, func
44
15
 
45
- raise ArgumentError, "domain is not a Range" if !domain.is_a? Range
46
- raise ArgumentError, "func is not a Proc" if !func.is_a? Proc
16
+ def ==(other)
17
+ @pieces == other.pieces
18
+ end
47
19
 
48
- contains_domain_completely = @pieces.select { |d,f| d.include?(domain.begin) && d.include?(domain.end) }
49
- if contains_domain_completely.any?
50
- contains_domain_completely.each do |d,f|
51
- l = d.begin...domain.begin
52
- if d.exclude_end?
53
- r = domain.end...d.end
54
- else
55
- r = domain.end..d.end
20
+ # Add a function piece, which covers the given domain (includes domain start
21
+ # but not the end).
22
+ # @param [Range] domain The function domain. If this overlaps an existing domain,
23
+ # the existing domain will be split with the non-
24
+ # overlapping pieces kept and the overlapping old piece
25
+ # discarded.
26
+ def add_piece domain, func
27
+
28
+ raise ArgumentError, "domain is not a Range" unless domain.is_a? Range
29
+ raise ArgumentError, "func is not a Function" unless func.is_a? Function
30
+
31
+ contains_domain_completely = @pieces.select { |d,f| d.include?(domain.begin) && d.include?(domain.end) }
32
+ if contains_domain_completely.any?
33
+ contains_domain_completely.each do |d,f|
34
+ l = d.begin...domain.begin
35
+ if d.exclude_end?
36
+ r = domain.end...d.end
37
+ else
38
+ r = domain.end..d.end
39
+ end
40
+
41
+ @pieces.delete d
42
+
43
+ if domain.begin != d.begin
44
+ @pieces[l] = f
45
+ end
46
+ if domain.end == d.end
47
+ @pieces[domain.begin..domain.end] = func
48
+ else
49
+ @pieces[domain.begin...domain.end] = func
50
+ @pieces[r] = f
51
+ end
52
+ end
53
+ else
54
+ delete_completely = @pieces.select { |d,f| domain.include?(d.begin) && domain.include?(d.end) }
55
+ delete_completely.each do |d,f|
56
+ @pieces.delete d
56
57
  end
57
58
 
58
- @pieces.delete d
59
+ # should only be one
60
+ move_end = @pieces.select { |d,f| domain.include?(d.end) }
61
+ move_end.each do |d,f|
62
+ @pieces.delete d
63
+ @pieces[d.begin...domain.begin] = f
64
+ end
59
65
 
60
- if domain.begin != d.begin
61
- @pieces[l] = f
66
+ # should only be one
67
+ move_begin = @pieces.select { |d,f| domain.include?(d.begin) }
68
+ move_begin.each do |d,f|
69
+ @pieces.delete d
70
+ if d.exclude_end?
71
+ @pieces[domain.end...d.end] = f
72
+ else
73
+ @pieces[domain.end..d.end] = f
74
+ end
62
75
  end
63
- if domain.end == d.end
64
- @pieces[domain.begin..domain.end] = func
65
- else
76
+
77
+ if move_begin.any?
66
78
  @pieces[domain.begin...domain.end] = func
67
- @pieces[r] = f
68
- end
69
- end
70
- else
71
- delete_completely = @pieces.select { |d,f| domain.include?(d.begin) && domain.include?(d.end) }
72
- delete_completely.each do |d,f|
73
- @pieces.delete d
74
- end
75
-
76
- # should only be one
77
- move_end = @pieces.select { |d,f| domain.include?(d.end) }
78
- move_end.each do |d,f|
79
- @pieces.delete d
80
- @pieces[d.begin...domain.begin] = f
81
- end
82
-
83
- # should only be one
84
- move_begin = @pieces.select { |d,f| domain.include?(d.begin) }
85
- move_begin.each do |d,f|
86
- @pieces.delete d
87
- if d.exclude_end?
88
- @pieces[domain.end...d.end] = f
89
79
  else
90
- @pieces[domain.end..d.end] = f
80
+ @pieces[domain] = func
91
81
  end
92
82
  end
93
-
94
- if move_begin.any?
95
- @pieces[domain.begin...domain.end] = func
96
- else
97
- @pieces[domain] = func
98
- end
99
83
  end
100
- end
101
-
102
- # Evaluate the piecewise function by finding a function piece whose domain
103
- # includes the given independent value.
104
- def eval x
105
- y = nil
106
84
 
107
- @pieces.each do |domain, func|
108
- if domain.include? x
109
- y = func.call x
110
- break
111
- end
85
+ def domain_include? x
86
+ !@pieces.keys.detect {|domain| domain.include?(x)}.nil?
112
87
  end
113
88
 
114
- if y.nil?
115
- raise ArgumentError, "The input #{x} is not in the domain."
89
+ # Evaluate the piecewise function by finding a function piece whose domain
90
+ # includes the given independent value.
91
+ def at x
92
+ @pieces.each do |domain, func|
93
+ if domain.include? x
94
+ return func.at(x)
95
+ end
96
+ end
97
+ raise DomainError, "The input #{x} is not in the domain."
116
98
  end
117
-
118
- return y
119
99
  end
120
100
  end
121
101
 
@@ -0,0 +1,12 @@
1
+ module Musicality
2
+
3
+ class Transition < Function::Piecewise
4
+ def initialize func, transition_domain
5
+ super()
6
+ add_piece(transition_domain, func)
7
+ add_piece(transition_domain.last..DOMAIN_MAX,
8
+ Function::Constant.new(func.at(transition_domain.last)))
9
+ end
10
+ end
11
+
12
+ end
@@ -1,169 +1,29 @@
1
1
  module Musicality
2
2
 
3
3
  # Given a start value, and value changes, compute the value at any offset.
4
- class ValueComputer
4
+ class ValueComputer < Function::Piecewise
5
5
  attr_reader :piecewise_function
6
-
7
6
  def initialize start_value, value_changes = {}
8
- @piecewise_function = PiecewiseFunction.new
9
- set_default_value start_value
10
-
7
+ super()
8
+ set_default_value(start_value)
11
9
  if value_changes.any?
12
10
  value_changes.sort.each do |offset,change|
13
-
14
- case change
15
- when Change::Immediate
16
- add_immediate_change change, offset
17
- when Change::Gradual
18
- add_linear_change change, offset
19
- # add_sigmoid_change change, offset
20
- end
21
-
11
+ add_change(offset, change)
22
12
  end
23
13
  end
24
14
  end
25
-
26
- # Compute the value at the given offset.
27
- # @param [Numeric] offset The given offset to compute value at.
28
- def value_at offset
29
- @piecewise_function.eval offset
30
- end
31
-
32
- def sample xmin, xmax, srate
33
- sample_period = Rational(1,srate)
34
- ((xmin.to_r)..(xmax.to_r)).step(sample_period).map do |x|
35
- value_at(x)
36
- end
37
- end
38
-
39
- # finds the minimum domain value
40
- def domain_min
41
- -Float::INFINITY
42
- end
43
-
44
- # finds the maximum domain value
45
- def domain_max
46
- Float::INFINITY
47
- end
48
-
49
- # finds the minimum domain value
50
- def self.domain_min
51
- -Float::INFINITY
52
- end
53
-
54
- # finds the maximum domain value
55
- def self.domain_max
56
- Float::INFINITY
57
- end
58
-
15
+
59
16
  private
60
17
 
61
- def set_default_value value
62
- func = lambda {|x| value }
63
- @piecewise_function.add_piece( domain_min..domain_max, func )
18
+ def add_change offset, change
19
+ start_value = at(offset)
20
+ trans = change.to_transition(offset, start_value)
21
+ add_piece(offset..Function::DOMAIN_MAX, trans)
64
22
  end
65
23
 
66
- # Add a function piece to the piecewise function, which will to compute value
67
- # for a matching note offset. Transition duration will be ignored since the
68
- # change is immediate.
69
- #
70
- # @param [ValueChange] value_change An event with information about the new value.
71
- # @param [Numeric] offset
72
- def add_immediate_change value_change, offset
73
- func = nil
74
- value = value_change.value
75
- domain = offset..domain_max
76
- func = lambda {|x| value }
77
-
78
- @piecewise_function.add_piece domain, func
79
- end
80
-
81
- # Add a function piece to the piecewise function, which will to compute value
82
- # for a matching note offset. If the dynamic event duration is non-zero, a
83
- # linear transition function is created.
84
- #
85
- # @param [ValueChange] value_change An event with information about the new value.
86
- # @param [Numeric] offset
87
- def add_linear_change value_change, offset
88
-
89
- func = nil
90
- value = value_change.value
91
- duration = value_change.duration
92
- domain = offset..domain_max
93
-
94
- if duration == 0
95
- add_immediate_change(value_change, offset)
96
- else
97
- b = @piecewise_function.eval domain.first
98
- m = (value.to_f - b.to_f) / duration.to_f
99
-
100
- func = lambda do |x|
101
- raise RangeError, "#{x} is not in the domain" if !domain.include?(x)
102
-
103
- if x < (domain.first + duration)
104
- (m * (x - domain.first)) + b
105
- else
106
- value
107
- end
108
- end
109
- @piecewise_function.add_piece domain, func
110
- end
111
- end
112
-
113
- # Add a function piece to the piecewise function, which will to compute value
114
- # for a matching note offset. If the dynamic event duration is non-zero, a
115
- # linear transition function is created.
116
- #
117
- # @param [ValueChange] value_change An event with information about the new value.
118
- # @param [Numeric] offset
119
- def add_sigmoid_change value_change, offset
120
-
121
- func = nil
122
- start_value = @piecewise_function.eval offset
123
- end_value = value_change.value
124
- value_diff = end_value - start_value
125
- duration = value_change.duration
126
- domain = offset.to_f..domain_max
127
- abruptness = 0.7 # value_change.transition.abruptness.to_f
128
-
129
- if duration == 0
130
- add_immediate_change(value_change,offset)
131
- else
132
- raise ArgumentError, "abruptness is not between 0 and 1" unless abruptness.between?(0,1)
133
-
134
- min_magn = 2
135
- max_magn = 6
136
- tanh_domain_magn = abruptness * (max_magn - min_magn) + min_magn
137
- tanh_domain = -tanh_domain_magn..tanh_domain_magn
138
-
139
- tanh_range = Math::tanh(tanh_domain.first)..Math::tanh(tanh_domain.last)
140
- tanh_span = tanh_range.last - tanh_range.first
141
-
142
- func = lambda do |x|
143
- raise RangeError, "#{x} is not in the domain" if !domain.include?(x)
144
- if x < (domain.first + duration)
145
- start_domain = domain.first...(domain.first + duration)
146
- x2 = transform_domains(start_domain, tanh_domain, x)
147
- y = Math::tanh x2
148
- z = (y / tanh_span) + 0.5 # ranges from 0 to 1
149
- start_value + (z * value_diff)
150
- else
151
- end_value
152
- end
153
- end
154
- @piecewise_function.add_piece domain, func
155
- end
156
- end
157
-
158
- # x should be in the start domain
159
- def transform_domains start_domain, end_domain, x
160
- perc = (x - start_domain.first) / (start_domain.last - start_domain.first).to_f
161
- x2 = perc * (end_domain.last - end_domain.first) + end_domain.first
162
- end
163
-
164
- # 0 to 1
165
- def logistic x
166
- 1.0 / (1 + Math::exp(-x))
24
+ def set_default_value value
25
+ func = Function::Constant.new(value)
26
+ add_piece(Function::DOMAIN_MIN..Function::DOMAIN_MAX, func)
167
27
  end
168
28
  end
169
29
 
@@ -48,30 +48,45 @@ class ScoreCollator
48
48
  seg = seg.first...seg.last
49
49
 
50
50
  # add segment start value
51
- value = comp.value_at seg.first
51
+ value = comp.at seg.first
52
52
  new_changes[segment_start_offset] = Change::Immediate.new(value)
53
53
 
54
- # add any immediate changes in segment
55
- changes.select {|o,c| c.is_a?(Change::Immediate) && seg.include?(o) }.each do |off,c|
56
- new_changes[(off - seg.first) + segment_start_offset] = c.clone
57
- end
58
-
59
- # add gradual changes
60
- changes.select {|o,c| c.is_a?(Change::Gradual)}.each do |off, change|
54
+ changes.each do |off,change|
61
55
  adj_start_off = (off - seg.first) + segment_start_offset
62
- end_off = off + change.duration
63
- if seg.include?(off) # change that are wholly included in segment
64
- if end_off <= seg.last
65
- new_changes[adj_start_off] = change.clone
66
- else # change that overlap segment end
67
- over = end_off - seg.last
68
- new_changes[adj_start_off] = Change::Gradual.new(change.value,
69
- change.duration - over, change.elapsed, change.remaining + over)
56
+
57
+ new_change = case change
58
+ when Change::Immediate
59
+ change.clone if seg.include?(off)
60
+ when Change::Gradual::Trimmed
61
+ end_off = off + change.remaining
62
+ if off < seg.last && end_off > seg.first
63
+ add_preceding = seg.first > off ? seg.first - off : 0
64
+ add_trailing = end_off > seg.last ? end_off - seg.last : 0
65
+
66
+ if add_preceding == 0 && add_trailing == 0
67
+ change.clone
68
+ else
69
+ adj_start_off += add_preceding
70
+ change.untrim.trim(change.preceding + add_preceding,
71
+ change.trailing + add_trailing)
72
+ end
70
73
  end
71
- elsif end_off > seg.first && end_off < seg.last # change that overlap segment start
72
- under = seg.first - off
73
- new_changes[segment_start_offset] = Change::Gradual.new(change.value,
74
- change.duration - under, change.elapsed + under, change.remaining)
74
+ when Change::Gradual
75
+ end_off = off + change.duration
76
+ if off < seg.last && end_off > seg.first
77
+ preceding = seg.first > off ? seg.first - off : 0
78
+ trailing = end_off > seg.last ? end_off - seg.last : 0
79
+ if preceding == 0 && trailing == 0
80
+ change.clone
81
+ else
82
+ adj_start_off += preceding
83
+ change.trim(preceding, trailing)
84
+ end
85
+ end
86
+ end
87
+
88
+ unless new_change.nil?
89
+ new_changes[adj_start_off] = new_change
75
90
  end
76
91
  end
77
92
  end
@@ -81,12 +81,9 @@ class PartSequencer
81
81
  dyn_comp = ValueComputer.new(start_dyn,dyn_changes)
82
82
  finish = 0
83
83
  if dyn_changes.any?
84
- finish, change = dyn_changes.max
85
- if change.is_a? Change::Gradual
86
- finish += change.duration
87
- end
84
+ finish = dyn_changes.map {|off,ch| ch.offsets(off).max }.max
88
85
  end
89
- samples = dyn_comp.sample(0, finish, sample_rate)
86
+ samples = dyn_comp.sample(0..finish, sample_rate)
90
87
 
91
88
  prev = nil
92
89
  samples.each_index do |i|
@@ -1,7 +1,12 @@
1
1
  # assumes that @checks is defined as an array of no-arg lambdas, each
2
2
  # lambda raising an error (with useful msg) when check fails
3
3
  module Validatable
4
- attr_reader :errors
4
+ def errors
5
+ if @errors.nil?
6
+ self.validate
7
+ end
8
+ return @errors
9
+ end
5
10
 
6
11
  def check_methods; []; end
7
12
  def validatables; []; end
@@ -1,3 +1,3 @@
1
1
  module Musicality
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/musicality.rb CHANGED
@@ -47,17 +47,17 @@ require 'musicality/notation/packing/program_packing'
47
47
  require 'musicality/notation/packing/score_packing'
48
48
 
49
49
  require 'musicality/notation/util/interpolation'
50
+ require 'musicality/notation/util/function'
50
51
  require 'musicality/notation/util/piecewise_function'
52
+ require 'musicality/notation/util/transition'
51
53
  require 'musicality/notation/util/value_computer'
52
54
 
53
55
  require 'musicality/notation/conversion/tempo_conversion'
54
56
  require 'musicality/notation/conversion/change_conversion'
55
57
  require 'musicality/notation/conversion/note_time_converter'
56
- require 'musicality/notation/conversion/unmeasured_score_converter'
57
- require 'musicality/notation/conversion/unmeasured_score_conversion'
58
58
  require 'musicality/notation/conversion/measure_note_map'
59
- require 'musicality/notation/conversion/measured_score_converter'
60
- require 'musicality/notation/conversion/measured_score_conversion'
59
+ require 'musicality/notation/conversion/score_converter'
60
+ require 'musicality/notation/conversion/score_conversion'
61
61
 
62
62
  #
63
63
  # Performance
data/musicality.gemspec CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency "bundler", "~> 1.7"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 2.9"
26
+ spec.add_development_dependency "pry"
26
27
 
27
28
  spec.add_dependency "treetop", "~> 1.5"
28
29
  spec.add_dependency 'midilib', '~> 2.0'