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 +13 -6
- data/lib/post_tonal/pitch_class_set.rb +78 -21
- data/lib/post_tonal/version.rb +1 -1
- data/test/unit/pitch_class_set_test.rb +127 -0
- metadata +2 -2
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
|
-
-
|
11
|
+
- Adds homepage information to gem specification
|
5
12
|
|
6
13
|
####October 21, 2012 [0.1.0.pre]
|
7
|
-
-
|
8
|
-
-
|
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
|
-
-
|
18
|
+
- Implements inversion in PitchClassSet
|
12
19
|
|
13
20
|
####October 16, 2012 [0.0.2.pre]
|
14
|
-
-
|
21
|
+
- Implements normal form in PitchClassSet
|
15
22
|
|
16
23
|
####October 15, 2012 [0.0.1.pre]
|
17
|
-
-
|
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
|
-
@
|
43
|
-
return false if !pitch_class_set.
|
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
|
-
|
81
|
-
|
82
|
-
|
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
|
-
|
85
|
-
|
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
|
-
#
|
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
|
-
|
121
|
-
|
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
|
-
|
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
|
data/lib/post_tonal/version.rb
CHANGED
@@ -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.
|
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-
|
12
|
+
date: 2012-10-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: shoulda
|