musicality 0.1.0 → 0.2.0

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: 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