post_tonal 0.1.1.pre → 0.2.0.pre

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.
data/CHANGELOG.md CHANGED
@@ -1,17 +1,24 @@
1
1
  #CHANGELOG
2
2
 
3
+ ####October 22, 2012 [0.2.0.pre]
4
+ - Implements prime form
5
+ - Fixes normal form logic and updates tests
6
+
7
+ ####October 21, 2012 [0.1.1.pre]
8
+ - Adds homepage information to gem specification
9
+
3
10
  ####October 21, 2012 [0.1.1.pre]
4
- -Add homepage information to gem specification
11
+ - Adds homepage information to gem specification
5
12
 
6
13
  ####October 21, 2012 [0.1.0.pre]
7
- -Implement transposition in PitchClassSet
8
- -Change normal_form, inversion, and transpose so that they each return a PitchClassSet
14
+ - Implements transposition in PitchClassSet
15
+ - Changes normal_form, inversion, and transpose so that they each return a PitchClassSet
9
16
 
10
17
  ####October 20, 2012 [0.0.3.pre]
11
- -Implement inversion in PitchClassSet
18
+ - Implements inversion in PitchClassSet
12
19
 
13
20
  ####October 16, 2012 [0.0.2.pre]
14
- -Implement normal form in PitchClassSet
21
+ - Implements normal form in PitchClassSet
15
22
 
16
23
  ####October 15, 2012 [0.0.1.pre]
17
- - Create PitchClass, PitchClassSet, PitchClassInterval, PitchInterval, and NoteParser
24
+ - Creates PitchClass, PitchClassSet, PitchClassInterval, PitchInterval, and NoteParser
@@ -7,8 +7,9 @@ module PostTonal
7
7
 
8
8
  def initialize(pitch_classes = nil)
9
9
  @pitch_classes = pitch_classes || []
10
- @normalized_pitch_classes = pitch_classes ? self.class.to_normal_form(@pitch_classes) : []
11
- @inverted_pitch_classes = pitch_classes ? invert(@pitch_classes) : []
10
+ @normalized_pitch_classes = @pitch_classes.size > 0 ? self.class.to_normal_form(@pitch_classes) : []
11
+ @inverted_pitch_classes = @pitch_classes.size > 0 ? invert(@pitch_classes) : []
12
+ @prime_pitch_classes = @pitch_classes.size > 0 ? to_prime_form : []
12
13
  end
13
14
 
14
15
  # Add a pitch to the pitch class set
@@ -31,16 +32,17 @@ module PostTonal
31
32
  @pitch_classes << pc
32
33
  @normalized_pitch_classes = self.class.to_normal_form(@pitch_classes)
33
34
  @inverted_pitch_classes = invert(@pitch_classes)
35
+ @prime_pitch_classes = to_prime_form
34
36
  end
35
37
 
36
38
  pc
37
39
  end
38
40
 
39
41
  def eql?(pitch_class_set)
40
- return false if @pitch_classes.size != pitch_class_set.pitch_classes.size
42
+ return false if @pitch_classes.size != pitch_class_set.pitch_classes.size || @pitch_classes.size == 0
41
43
 
42
- @normalized_pitch_classes.each_with_index do |pitch_class, i|
43
- return false if !pitch_class_set.normal_form.pitch_classes[i].eql?(pitch_class)
44
+ @pitch_classes.each_with_index do |pitch_class, i|
45
+ return false if !pitch_class.eql?(pitch_class_set.pitch_classes[i])
44
46
  end
45
47
 
46
48
  true
@@ -75,19 +77,14 @@ module PostTonal
75
77
  if newLen < shortest[:length]
76
78
  shortest = {:array => normal.dup, :length => newLen}
77
79
  elsif newLen == shortest[:length]
78
- (normal.size - 1).downto(q) do |r|
79
80
 
80
- newLen = normal[r].value - normal.first.value
81
- newLen += 12 if newLen < 0
82
- newLen += 12 if newLen == 1 && normal.size > 2
81
+ rs = shortest[:array].reverse
82
+ normal.reverse.each_with_index do |pitch_class, i|
83
+ this_dist = (pitch_class.value - normal.first.value).abs
84
+ that_dist = (rs[i].value - rs.last.value).abs
83
85
 
84
- sNewLen = shortest[:array][r].value - shortest[:array].first.value
85
- sNewLen += 12 if sNewLen < 0
86
- sNewLen += 12 if sNewLen == 1 && normal.size > 2
87
-
88
- if newLen < sNewLen
89
- shortest = {:array => normal.dup, :length => newLen}
90
- break
86
+ if this_dist < that_dist
87
+ shortest = {:array => normal, :length => newLen}
91
88
  end
92
89
  end
93
90
  end
@@ -106,9 +103,21 @@ module PostTonal
106
103
  self.class.new(@normalized_pitch_classes)
107
104
  end
108
105
 
109
- # Transposes the set by a degree (integer)
106
+ # Returns a PitchClassSet of the current PitchClassSet in prime form
107
+ def prime_form
108
+ prime1 = normal_form.transpose_to_zero
109
+ prime2 = inversion.normal_form.transpose_to_zero
110
+ return prime2 if prime2.is_more_packed_than? prime1
111
+ prime1
112
+ end
113
+
114
+ # Transposes the set
115
+ #
116
+ # degree - The number of steps to transpose. May be positive or negative
117
+ # reset_octave - If true, resets octave attribute to 0 for all pitch classes
118
+ #
110
119
  # Returns PitchClassSet of the transposed set
111
- def transpose(degree)
120
+ def transpose(degree, reset_octave = false)
112
121
  transposed = self.class.new
113
122
 
114
123
  @pitch_classes.each do |pitch_class|
@@ -117,8 +126,12 @@ module PostTonal
117
126
 
118
127
  val += degree
119
128
 
120
- oct += val / 12
121
- oct -= 1 if val < 0 && val % 12 == 0
129
+ if reset_octave
130
+ oct = 0
131
+ else
132
+ oct += val / 12
133
+ oct -= 1 if val < 0 && val % 12 == 0
134
+ end
122
135
 
123
136
  transposed.add_pitch(val, oct)
124
137
  end
@@ -126,7 +139,34 @@ module PostTonal
126
139
  transposed
127
140
  end
128
141
 
129
- private
142
+ def reset_octave
143
+ ro = []
144
+
145
+ @pitch_classes.each do |pitch_class|
146
+ ro << PitchClass.new(pitch_class.value)
147
+ end
148
+
149
+ self.class.new(ro)
150
+ end
151
+
152
+ # Check if this pitch class set is more tightly packed to the left than the comparison pitch class set.
153
+ #
154
+ # Returns false if less tightly packed or if is the same set
155
+ def is_more_packed_than?(pitch_class_set)
156
+ return false if (@pitch_classes.size != pitch_class_set.pitch_classes.size || @pitch_classes.size == 0) || eql?(pitch_class_set)
157
+
158
+ rpcs = pitch_class_set.pitch_classes.reverse
159
+ @pitch_classes.reverse.each_with_index do |pitch_class, i|
160
+ this_dist = (pitch_class.value - @pitch_classes.first.value).abs
161
+ that_dist = (rpcs[i].value - rpcs.last.value).abs
162
+
163
+ return true if this_dist < that_dist
164
+ end
165
+
166
+ false
167
+ end
168
+
169
+ protected
130
170
 
131
171
  # Inverts an array of pitch classes. The PitchClass attribute octave may become invalid after inversion.
132
172
  # Returns a PitchClassSet of the inverted pitch classes
@@ -141,5 +181,22 @@ module PostTonal
141
181
  inverted
142
182
  end
143
183
 
184
+ # Returns the normal form of an array of pitch classes
185
+ def to_prime_form
186
+ #prime1 = normal_form.transpose_to_zero.pitch_classes
187
+ #prime2 = inversion.normal_form.transpose_to_zero
188
+
189
+ #return prime1.pitch_classes if prime1.is_more_packed_than? prime2
190
+ #return prime2.pitch_classes_classes
191
+ []
192
+ end
193
+
194
+ def transpose_to_zero
195
+ dist = 12 - @pitch_classes[0].value
196
+ "TT0: #{@pitch_classes}, dist: #{dist}"
197
+ return transpose(dist, true) if dist % 12 != 0
198
+ self
199
+ end
200
+
144
201
  end
145
202
  end
@@ -1,3 +1,3 @@
1
1
  module PostTonal
2
- VERSION = '0.1.1.pre'
2
+ VERSION = '0.2.0.pre'
3
3
  end
@@ -118,6 +118,20 @@ class PitchClassSetTest < Test::Unit::TestCase
118
118
  [6,7,0].each_with_index do |n, i|
119
119
  assert_equal(n, @p7.normal_form.pitch_classes[i].value)
120
120
  end
121
+
122
+ @p8 = PostTonal::PitchClassSet.new
123
+ @p8.add_pitch(0)
124
+ @p8.add_pitch(3)
125
+ @p8.add_pitch(8)
126
+ @p8.add_pitch(9)
127
+
128
+ @p8n = PostTonal::PitchClassSet.new
129
+ @p8n.add_pitch(8)
130
+ @p8n.add_pitch(9)
131
+ @p8n.add_pitch(0)
132
+ @p8n.add_pitch(3)
133
+
134
+ assert_equal(@p8n, @p8.normal_form, "Normal form of #{@p8} should be #{@p8n}")
121
135
  end
122
136
 
123
137
  def test_inversion
@@ -156,4 +170,117 @@ class PitchClassSetTest < Test::Unit::TestCase
156
170
  end
157
171
  end
158
172
 
173
+ def test_prime_form
174
+ @p1 = PostTonal::PitchClassSet.new
175
+ @p1.add_pitch(0)
176
+ @p1.add_pitch(1)
177
+ @p1.add_pitch(4)
178
+ @p1.add_pitch(7)
179
+
180
+ @p1p = PostTonal::PitchClassSet.new
181
+ @p1p.add_pitch(0)
182
+ @p1p.add_pitch(1)
183
+ @p1p.add_pitch(4)
184
+ @p1p.add_pitch(7)
185
+
186
+ assert_equal(@p1p, @p1.prime_form)
187
+
188
+
189
+ @p2 = PostTonal::PitchClassSet.new
190
+ @p2.add_pitch(6)
191
+ @p2.add_pitch(7)
192
+ @p2.add_pitch(8)
193
+
194
+ @p2p = PostTonal::PitchClassSet.new
195
+ @p2p.add_pitch(0)
196
+ @p2p.add_pitch(1)
197
+ @p2p.add_pitch(2)
198
+
199
+ assert_equal(@p2p, @p2.prime_form)
200
+
201
+ @p3 = PostTonal::PitchClassSet.new
202
+ @p3.add_pitch(0)
203
+ @p3.add_pitch(3)
204
+ @p3.add_pitch(8)
205
+ @p3.add_pitch(9)
206
+
207
+ @p3p = PostTonal::PitchClassSet.new
208
+ @p3p.add_pitch(0)
209
+ @p3p.add_pitch(1)
210
+ @p3p.add_pitch(4)
211
+ @p3p.add_pitch(7)
212
+
213
+ assert_equal(@p3p, @p3.prime_form)
214
+
215
+
216
+ @p4 = PostTonal::PitchClassSet.new
217
+ @p4.add_pitch(1)
218
+ @p4.add_pitch(5)
219
+ @p4.add_pitch(6)
220
+ @p4.add_pitch(7)
221
+
222
+ @p4p = PostTonal::PitchClassSet.new
223
+ @p4p.add_pitch(0)
224
+ @p4p.add_pitch(1)
225
+ @p4p.add_pitch(2)
226
+ @p4p.add_pitch(6)
227
+
228
+ assert_equal(@p4p, @p4.prime_form)
229
+
230
+ @p5 = PostTonal::PitchClassSet.new
231
+ @p5.add_pitch(0)
232
+ @p5.add_pitch(2)
233
+ @p5.add_pitch(4)
234
+ @p5.add_pitch(7)
235
+ @p5.add_pitch(11)
236
+
237
+ @p5p = PostTonal::PitchClassSet.new
238
+ @p5p.add_pitch(0)
239
+ @p5p.add_pitch(1)
240
+ @p5p.add_pitch(3)
241
+ @p5p.add_pitch(5)
242
+ @p5p.add_pitch(8)
243
+
244
+ assert_equal(@p5p, @p5.prime_form)
245
+
246
+ @p6 = PostTonal::PitchClassSet.new
247
+ @p6.add_pitch(3)
248
+ @p6.add_pitch(6)
249
+ @p6.add_pitch(7)
250
+ @p6.add_pitch(8)
251
+ @p6.add_pitch(9)
252
+ @p6.add_pitch(10)
253
+
254
+ @p6p = PostTonal::PitchClassSet.new
255
+ @p6p.add_pitch(0)
256
+ @p6p.add_pitch(1)
257
+ @p6p.add_pitch(2)
258
+ @p6p.add_pitch(3)
259
+ @p6p.add_pitch(4)
260
+ @p6p.add_pitch(7)
261
+
262
+ assert_equal(@p6p, @p6.prime_form)
263
+
264
+ @p7 = PostTonal::PitchClassSet.new
265
+ @p7.add_pitch(0)
266
+ @p7.add_pitch(2)
267
+ @p7.add_pitch(5)
268
+ @p7.add_pitch(6)
269
+ @p7.add_pitch(7)
270
+ @p7.add_pitch(9)
271
+ @p7.add_pitch(10)
272
+ @p7.add_pitch(11)
273
+
274
+ @p7p = PostTonal::PitchClassSet.new
275
+ @p7p.add_pitch(0)
276
+ @p7p.add_pitch(1)
277
+ @p7p.add_pitch(2)
278
+ @p7p.add_pitch(4)
279
+ @p7p.add_pitch(5)
280
+ @p7p.add_pitch(6)
281
+ @p7p.add_pitch(7)
282
+ @p7p.add_pitch(9)
283
+
284
+ assert_equal(@p7p, @p7.prime_form)
285
+ end
159
286
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: post_tonal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1.pre
4
+ version: 0.2.0.pre
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-21 00:00:00.000000000 Z
12
+ date: 2012-10-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: shoulda