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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9413fe250183b04ea15a863a580cd90887ccb5e
|
4
|
+
data.tar.gz: d2820bd7695d490fb139508d663b202b2d867202
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ffb85df1738b9948c0d23c627be1a42b195ce438b9098575ec9d662b1383f9689b7c9bc57cd432498bd9dd87306d4ddb5f8c4ad481502c3d3d1dfa664fe7bfca
|
7
|
+
data.tar.gz: f4e9a0f14009a2a50b3cf377504283cca9e5858bce3335649a80bb99021f386ed6203b62f88ea935541976bddfedb81bf766f5ffb8648ca9e1b1fe67f3236eeb
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Musicality
|
2
2
|
|
3
3
|
module Conversion
|
4
|
-
#
|
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 {|
|
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
|
|
data/lib/musicality/version.rb
CHANGED
@@ -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.
|
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-
|
11
|
+
date: 2014-11-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|