musicality 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 25e0c57192fe59be6b7839c2eb1b7a0ebfca7d5e
4
- data.tar.gz: 3e5b8efeddfdcb1a7fa4b1f78a8752204109779e
3
+ metadata.gz: f9413fe250183b04ea15a863a580cd90887ccb5e
4
+ data.tar.gz: d2820bd7695d490fb139508d663b202b2d867202
5
5
  SHA512:
6
- metadata.gz: 41c88ca97959bdb89f55e27a69505a77a3f045c5ef6406d4c9d3fba61969f60ef3a7e9ad3e94d4323217b3bc45d6d972cd06ee070448a6f34c69b3b93b41fd49
7
- data.tar.gz: b6019f6508f05bfd4d8cfb82e6bd9b724b3a4b6af0e1dde1f2cf2eb5d625836fcc00a47162f4d2457a74d3cd9b81f14fb2f8ed8438eb96a4435595a9c155c10f
6
+ metadata.gz: ffb85df1738b9948c0d23c627be1a42b195ce438b9098575ec9d662b1383f9689b7c9bc57cd432498bd9dd87306d4ddb5f8c4ad481502c3d3d1dfa664fe7bfca
7
+ data.tar.gz: f4e9a0f14009a2a50b3cf377504283cca9e5858bce3335649a80bb99021f386ed6203b62f88ea935541976bddfedb81bf766f5ffb8648ca9e1b1fe67f3236eeb
@@ -1,7 +1,7 @@
1
1
  module Musicality
2
2
 
3
3
  module Conversion
4
- # Converte offsets from measure-based to note-based.
4
+ # Convert offsets from measure-based to note-based.
5
5
  # @param [Array] measure_offsets Measure offsets to be converted
6
6
  # @param [Hash] measure_durations Map measure durations to measure offsets where the duration takes effect.
7
7
  # @raise [NonZeroError] if first measure duration is not mapped to offset 0
@@ -23,7 +23,7 @@ class Score
23
23
  end
24
24
 
25
25
  def duration
26
- @parts.map {|p| p.duration }.max
26
+ @parts.map {|name,part| part.duration }.max || 0.to_r
27
27
  end
28
28
 
29
29
  def collated?
@@ -31,6 +31,9 @@ class Score
31
31
  end
32
32
 
33
33
  class Timed < Score
34
+ def seconds_long
35
+ self.duration
36
+ end
34
37
  end
35
38
 
36
39
  class TempoBased < Score
@@ -53,6 +56,10 @@ class Score
53
56
  @tempo_changes == other.tempo_changes
54
57
  end
55
58
 
59
+ def notes_long
60
+ self.duration
61
+ end
62
+
56
63
  def check_start_tempo
57
64
  if @start_tempo <= 0
58
65
  raise NonPositiveError, "start tempo (#{@start_tempo}) is not positive"
@@ -126,6 +133,27 @@ class Score
126
133
  return super(other) && @start_meter == other.start_meter &&
127
134
  @meter_changes == other.meter_changes
128
135
  end
136
+
137
+ def measures_long
138
+ noff_end = self.notes_long
139
+ noff_prev = 0.to_r
140
+ moff_prev, mdur_prev = 0.to_r, @start_meter.measure_duration
141
+
142
+ @meter_changes.sort.each do |moff,change|
143
+ mdur = change.value.measure_duration
144
+ notes_elapsed = mdur_prev * (moff - moff_prev)
145
+ noff = noff_prev + notes_elapsed
146
+
147
+ if noff >= noff_end
148
+ break
149
+ else
150
+ noff_prev = noff
151
+ end
152
+
153
+ moff_prev, mdur_prev = moff, mdur
154
+ end
155
+ return moff_prev + Rational(noff_end - noff_prev, mdur_prev)
156
+ end
129
157
  end
130
158
  end
131
159
 
@@ -1,3 +1,3 @@
1
1
  module Musicality
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -32,6 +32,22 @@ describe Score do
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ describe '#duration' do
37
+ context 'no parts' do
38
+ it 'should return 0' do
39
+ Score.new.duration.should eq(0)
40
+ end
41
+ end
42
+
43
+ context 'one part' do
44
+ it 'should return the part duration' do
45
+ Score.new(parts: {"part1" => Part.new(Dynamics::PP,
46
+ notes: "/4 /4 /2 1".to_notes)
47
+ }).duration.should eq(2)
48
+ end
49
+ end
50
+ end
35
51
  end
36
52
 
37
53
  describe Score::Measured do
@@ -66,6 +82,58 @@ describe Score::Measured do
66
82
  end
67
83
  end
68
84
 
85
+ describe '#measures_long' do
86
+ context 'with no meter changes' do
87
+ context 'with no parts' do
88
+ it 'should return 0' do
89
+ Score::Measured.new(TWO_FOUR, 120).measures_long.should eq(0)
90
+ end
91
+ end
92
+
93
+ context 'with one part' do
94
+ it 'should return the duration of the part, in measures' do
95
+ Score::Measured.new(TWO_FOUR, 120, parts: {
96
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes)
97
+ }).measures_long.should eq(3.5)
98
+ end
99
+ end
100
+
101
+ context 'with two parts' do
102
+ it 'should return the duration of the longest part, in measures' do
103
+ Score::Measured.new(TWO_FOUR, 120, parts: {
104
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
105
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
106
+ }).measures_long.should eq(4)
107
+ end
108
+ end
109
+ end
110
+
111
+ context 'with meter changes' do
112
+ it 'should return the duration of the longest part, in measures' do
113
+ Score::Measured.new(TWO_FOUR, 120,
114
+ meter_changes: {
115
+ 2 => Change::Immediate.new(FOUR_FOUR),
116
+ },
117
+ parts: {
118
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
119
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
120
+ }
121
+ ).measures_long.should eq(3)
122
+
123
+ Score::Measured.new(TWO_FOUR, 120,
124
+ meter_changes: {
125
+ 2 => Change::Immediate.new(FOUR_FOUR),
126
+ 4 => Change::Immediate.new(SIX_EIGHT),
127
+ },
128
+ parts: {
129
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
130
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1 /2".to_notes)
131
+ }
132
+ ).measures_long.should eq(3.5)
133
+ end
134
+ end
135
+ end
136
+
69
137
  describe '#valid?' do
70
138
  {
71
139
  'valid start tempo' => [ FOUR_FOUR, 40 ],
@@ -134,6 +202,15 @@ describe Score::Unmeasured do
134
202
  s.tempo_changes.should eq tcs
135
203
  end
136
204
  end
205
+
206
+ describe '#notes_long' do
207
+ it 'should return the duration of the longest part' do
208
+ Score::Unmeasured.new(120, parts: {
209
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
210
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
211
+ }).notes_long.should eq(2)
212
+ end
213
+ end
137
214
 
138
215
  describe '#valid?' do
139
216
  {
@@ -185,6 +262,15 @@ describe Score::Timed do
185
262
  end
186
263
  end
187
264
 
265
+ describe '#seconds_long' do
266
+ it 'should return the duration of the longest part' do
267
+ Score::Timed.new(parts: {
268
+ "abc" => Part.new(Dynamics::MF, notes: "/4 /4 /2 3/4".to_notes),
269
+ "def" => Part.new(Dynamics::MF, notes: "/4 /4 /2 1".to_notes)
270
+ }).seconds_long.should eq(2)
271
+ end
272
+ end
273
+
188
274
  describe '#valid?' do
189
275
  {
190
276
  'valid part' => [ :parts => { "piano" => Samples::SAMPLE_PART }],
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: musicality
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Tunnell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-23 00:00:00.000000000 Z
11
+ date: 2014-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler