music-utils 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -5,4 +5,7 @@
5
5
  pkg/
6
6
 
7
7
  # Gems
8
- Gemfile.lock
8
+ Gemfile.lock
9
+
10
+ # vim swap files
11
+ *.swp
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.2.0 (May 25, 2011)
2
+
3
+ Features:
4
+
5
+ - Added functionality to calculate the highest note of an interval
6
+
1
7
  ## 1.1.2 (May 21, 2011)
2
8
 
3
9
  Features:
data/README.md CHANGED
@@ -10,21 +10,27 @@ Examples
10
10
  ### Intervals
11
11
 
12
12
  Simples:
13
-
13
+
14
14
  MusicUtils.number(:do, :mi) #=> 3 (3th)
15
15
  MusicUtils.semitones(:do, :mi) #=> 4 (semi-tones)
16
16
  MusicUtils.quality(:do, :mi) #=> M (major)
17
17
 
18
18
  Compounds:
19
19
 
20
- MusicUtils.number(:do, :mi, 1) #=> 3 (3th)
20
+ MusicUtils.number(:do, :mi, 1) #=> 10 (10th)
21
21
  MusicUtils.semitones(:do, :mi, 1) #=> 16 (semi-tones)
22
22
  MusicUtils.quality(:do, :mi, 1) #=> M (major)
23
23
 
24
24
  Short Notation:
25
25
 
26
- MusicUtils.short(:do, :mi) #=> M2
27
- MusicUtils.short(:do, :mi, 1) #=> M9
26
+ MusicUtils.short(:do, :mi) #=> M3
27
+ MusicUtils.short(:do, :mi, 1) #=> M10
28
+
29
+ Highest note of interval:
30
+
31
+ MusicUtils.high_note(:do, :P5) #=> :sol
32
+ MusicUtils.high_note(:fas, :m3) #=> :la
33
+
28
34
 
29
35
  ### Scales
30
36
 
@@ -60,7 +66,6 @@ To run the tests:
60
66
  To Do
61
67
  -----
62
68
 
63
- * Fix octave semitones count bug
64
69
  * Add validations (notes, alterations, etc)
65
70
  * Add support to pentatonic scale and others
66
71
 
data/lib/music-utils.rb CHANGED
@@ -25,9 +25,16 @@ module MusicUtils
25
25
  Interval.new(note1, note2, step).short
26
26
  end
27
27
 
28
+ # Returns the second note of an interval
29
+ # calculates from its first note and number
30
+ # and quality in short notation
31
+ def MusicUtils.high_note(from, short)
32
+ Interval.high_note(from, short)
33
+ end
34
+
28
35
  # Returns a scale
29
36
  def MusicUtils.scale(from, scale)
30
37
  Scales.scale(from, scale)
31
38
  end
32
39
 
33
- end
40
+ end
@@ -49,20 +49,9 @@ module MusicUtils
49
49
  count = count + (12 * @step) if @step > 0
50
50
 
51
51
  # counting notes alterations
52
- case @note1_alt
53
- when Scales::FLAT ; count += 1
54
- when Scales::SHARP ; count -= 1
55
- when Scales::DFLAT ; count += 2
56
- when Scales::DSHARP ; count -= 2
57
- end
58
-
59
- case @note2_alt
60
- when Scales::FLAT ; count -= 1
61
- when Scales::SHARP ; count += 1
62
- when Scales::DFLAT ; count -= 2
63
- when Scales::DSHARP ; count += 2
64
- end
65
-
52
+ count += Interval.alter_impact_in_semitones(@note1_alt, true)
53
+ count += Interval.alter_impact_in_semitones(@note2_alt, false)
54
+
66
55
  count
67
56
  end
68
57
 
@@ -77,7 +66,52 @@ module MusicUtils
77
66
  def short
78
67
  quality + number.to_s
79
68
  end
80
-
69
+
70
+ # Returns the higher note of an interval
71
+ # calculates from its first note and number
72
+ # and quality in short notation
73
+ def self.high_note(from, short)
74
+ quality, number = parse_short(short)
75
+
76
+ while number > 7
77
+ number = number - 7
78
+ end
79
+
80
+ from_note, from_alter = Note.parse(from)
81
+
82
+ to_note = Scales.diatonic_scale_from(from_note)[number - 1]
83
+ intervals = Scales::QUALITIES[number].key(quality)
84
+ intervals += alter_impact_in_semitones(from_alter, false)
85
+
86
+ from_note_index = Scales.cromatic_index(from_note.to_sym)
87
+ to_note_index = from_note_index + intervals
88
+
89
+ while to_note_index > 11
90
+ to_note_index = to_note_index - 12
91
+ end
92
+
93
+ Scales::CROMATIC_SCALE[to_note_index].select do |note|
94
+ raw_note, alter = Note.parse(note)
95
+ raw_note == to_note
96
+ end.first
97
+ end
98
+
99
+ # Short notation parser method
100
+ def self.parse_short(sn)
101
+ short = sn.to_s
102
+
103
+ quality = short[0..1]
104
+ number = short[2..3].to_i
105
+
106
+ if quality == Scales::DIMP or quality == Scales::AUGP
107
+ # nothing to do
108
+ else
109
+ quality = short[0]
110
+ number = short[1..2].to_i
111
+ end
112
+ [quality, number]
113
+ end
114
+
81
115
  private
82
116
 
83
117
  # Common loop to search note 2
@@ -110,7 +144,18 @@ module MusicUtils
110
144
  def note1_index
111
145
  DIATONIC_SCALE.index(@note1)
112
146
  end
113
-
147
+
148
+ def self.alter_impact_in_semitones(alter, from_note)
149
+ impact = 0
150
+ case alter
151
+ when Scales::FLAT ; impact = from_note ? 1 : -1
152
+ when Scales::SHARP ; impact = from_note ? -1 : 1
153
+ when Scales::DFLAT ; impact = from_note ? 2 : -2
154
+ when Scales::DSHARP ; impact = from_note ? -2 : 2
155
+ end
156
+ impact
157
+ end
158
+
114
159
  end
115
160
 
116
161
  end
@@ -57,7 +57,18 @@ module Scales
57
57
  SIS = (SI.to_s + SHARP).to_sym
58
58
  SISS = (SI.to_s + DSHARP).to_sym
59
59
 
60
- CROMATIC_SCALE = [[SIS, DO, REFF], [DOS, REF], [DOSS, RE, MIFF], [RES, MIF, FAFF], [RESS, MI, FAF], [MIS, FA, SOLFF], [MISS, FAS, SOLF], [FASS, SOL, LAFF], [SOLS, LAF], [SOLSS, LA, SIFF], [LAS, SIF], [LASS, SI, DOF]]
60
+ CROMATIC_SCALE = [[SIS, DO, REFF],
61
+ [SISS, DOS, REF],
62
+ [DOSS, RE, MIFF],
63
+ [RES, MIF, FAFF],
64
+ [RESS, MI, FAF],
65
+ [MIS, FA, SOLFF],
66
+ [MISS, FAS, SOLF],
67
+ [FASS, SOL, LAFF],
68
+ [SOLS, LAF],
69
+ [SOLSS, LA, SIFF],
70
+ [LAS, SIF],
71
+ [LASS, SI, DOF]]
61
72
  MAJ_SCALE = [2, 2, 1, 2, 2, 2, 1]
62
73
  NATURAL_MIN_SCALE = [2, 1, 2, 2, 1, 2, 2]
63
74
  MELODIC_MIN_SCALE = [2, 1, 2, 2, 1, 2, 1]
@@ -86,19 +97,7 @@ module Scales
86
97
  def Scales.scale(from, scale_struct)
87
98
  from = from.to_sym
88
99
 
89
- i = 0
90
- find_it = false
91
- CROMATIC_SCALE.each do |e|
92
- if e.is_a?(Array)
93
- e.each do |ee|
94
- find_it = true if from == ee
95
- end
96
- else
97
- find_it = true if from == e
98
- end
99
- break if find_it
100
- i += 1
101
- end
100
+ i = cromatic_index(from)
102
101
 
103
102
  scale = []
104
103
  scale << from
@@ -148,5 +147,23 @@ module Scales
148
147
  diatonic_scale
149
148
  end
150
149
 
150
+ # Returns index of the note in the cromatic scale
151
+ def Scales.cromatic_index(from)
152
+ i = 0
153
+ find_it = false
154
+ CROMATIC_SCALE.each do |e|
155
+ if e.is_a?(Array)
156
+ e.each do |ee|
157
+ find_it = true if from == ee
158
+ end
159
+ else
160
+ find_it = true if from == e
161
+ end
162
+ break if find_it
163
+ i += 1
164
+ end
165
+ i
166
+ end
167
+
151
168
  end
152
169
  end
@@ -1,3 +1,3 @@
1
1
  module MusicUtils
2
- VERSION = '1.1.2'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -166,6 +166,144 @@ describe MusicUtils do
166
166
  end
167
167
  end
168
168
 
169
+ context "Calculate higher note of intervals from sol" do
170
+ it "the higher note of m2 from sol should be laf" do
171
+ MusicUtils.high_note(:sol, :m2).should == :laf
172
+ end
173
+ it "the higher note of M2 from sol should be la" do
174
+ MusicUtils.high_note(:sol, :M2).should == :la
175
+ end
176
+ it "the higher note of m3 from sol should be sif" do
177
+ MusicUtils.high_note(:sol, :m3).should == :sif
178
+ end
179
+ it "the higher note of M3 from sol should be si" do
180
+ MusicUtils.high_note(:sol, :M3).should == :si
181
+ end
182
+ it "the higher note of d4 from sol should be dof" do
183
+ MusicUtils.high_note(:sol, :d4).should == :dof
184
+ end
185
+ it "the higher note of P4 from sol should be do" do
186
+ MusicUtils.high_note(:sol, :P4).should == :do
187
+ end
188
+ it "the higher note of A4 from sol should be dos" do
189
+ MusicUtils.high_note(:sol, :A4).should == :dos
190
+ end
191
+ it "the higher note of AA4 from sol should be doss" do
192
+ MusicUtils.high_note(:sol, :AA4).should == :doss
193
+ end
194
+ it "the higher note of dd5 from sol should be reff" do
195
+ MusicUtils.high_note(:sol, :dd5).should == :reff
196
+ end
197
+ it "the higher note of d5 from sol should be ref" do
198
+ MusicUtils.high_note(:sol, :d5).should == :ref
199
+ end
200
+ it "the higher note of P5 from sol should be re" do
201
+ MusicUtils.high_note(:sol, :P5).should == :re
202
+ end
203
+ it "the higher note of A5 from sol should be res" do
204
+ MusicUtils.high_note(:sol, :A5).should == :res
205
+ end
206
+ it "the higher note of AA5 from sol should be ress" do
207
+ MusicUtils.high_note(:sol, :AA5).should == :ress
208
+ end
209
+ it "the higher note of dd6 from sol should be miff" do
210
+ MusicUtils.high_note(:sol, :dd6).should == :miff
211
+ end
212
+ it "the higher note of d6 from sol should be mif" do
213
+ MusicUtils.high_note(:sol, :d6).should == :mif
214
+ end
215
+ it "the higher note of m6 from sol should be mi" do
216
+ MusicUtils.high_note(:sol, :m6).should == :mi
217
+ end
218
+ it "the higher note of M6 from sol should be mis" do
219
+ MusicUtils.high_note(:sol, :M6).should == :mis
220
+ end
221
+ it "the higher note of A6 from sol should be miss" do
222
+ MusicUtils.high_note(:sol, :A6).should == :miss
223
+ end
224
+ it "the higher note of dd7 from sol should be faff" do
225
+ MusicUtils.high_note(:sol, :dd7).should == :faff
226
+ end
227
+ it "the higher note of d7 from sol should be faf" do
228
+ MusicUtils.high_note(:sol, :d7).should == :faf
229
+ end
230
+ it "the higher note of m7 from sol should be fa" do
231
+ MusicUtils.high_note(:sol, :m7).should == :fa
232
+ end
233
+ it "the higher note of M7 from sol should be fas" do
234
+ MusicUtils.high_note(:sol, :M7).should == :fas
235
+ end
236
+ it "the higher note of A7 from sol should be fass" do
237
+ MusicUtils.high_note(:sol, :A7).should == :fass
238
+ end
239
+ end
240
+ context "Calculate higher note of intervals from fas" do
241
+ # From sol
242
+ it "the higher note of m2 from fas should be " do
243
+ MusicUtils.high_note(:fas, :m2).should == :sol
244
+ end
245
+ it "the higher note of M2 from fas should be " do
246
+ MusicUtils.high_note(:fas, :M2).should == :sols
247
+ end
248
+ it "the higher note of m3 from fas should be " do
249
+ MusicUtils.high_note(:fas, :m3).should == :la
250
+ end
251
+ it "the higher note of M3 from fas should be " do
252
+ MusicUtils.high_note(:fas, :M3).should == :las
253
+ end
254
+ it "the higher note of d4 from fas should be " do
255
+ MusicUtils.high_note(:fas, :d4).should == :sif
256
+ end
257
+ it "the higher note of P4 from fas should be " do
258
+ MusicUtils.high_note(:fas, :P4).should == :si
259
+ end
260
+ it "the higher note of A4 from fas should be " do
261
+ MusicUtils.high_note(:fas, :A4).should == :sis
262
+ end
263
+ it "the higher note of AA4 from fas should be " do
264
+ MusicUtils.high_note(:fas, :AA4).should == :siss
265
+ end
266
+ it "the higher note of dd5 from fas should be " do
267
+ MusicUtils.high_note(:fas, :dd5).should == :dof
268
+ end
269
+ it "the higher note of d5 from fas should be " do
270
+ MusicUtils.high_note(:fas, :d5).should == :do
271
+ end
272
+ it "the higher note of P5 from fas should be " do
273
+ MusicUtils.high_note(:fas, :P5).should == :dos
274
+ end
275
+ it "the higher note of A5 from fas should be " do
276
+ MusicUtils.high_note(:fas, :A5).should == :doss
277
+ end
278
+ it "the higher note of dd6 from fas should be " do
279
+ MusicUtils.high_note(:fas, :dd6).should == :ref
280
+ end
281
+ it "the higher note of d6 from fas should be " do
282
+ MusicUtils.high_note(:fas, :d6).should == :re
283
+ end
284
+ it "the higher note of m6 from fas should be " do
285
+ MusicUtils.high_note(:fas, :m6).should == :res
286
+ end
287
+ it "the higher note of M6 from fas should be " do
288
+ MusicUtils.high_note(:fas, :M6).should == :ress
289
+ end
290
+ it "the higher note of dd7 from fas should be " do
291
+ MusicUtils.high_note(:fas, :dd7).should == :miff
292
+ end
293
+ it "the higher note of d7 from fas should be " do
294
+ MusicUtils.high_note(:fas, :d7).should == :mif
295
+ end
296
+ it "the higher note of m7 from fas should be " do
297
+ MusicUtils.high_note(:fas, :m7).should == :mi
298
+ end
299
+ it "the higher note of M7 from fas should be " do
300
+ MusicUtils.high_note(:fas, :M7).should == :mis
301
+ end
302
+ it "the higher note of A7 from fas should be " do
303
+ # comments
304
+ MusicUtils.high_note(:fas, :A7).should == :miss
305
+ end
306
+ end
169
307
  end
170
308
 
171
309
  context "Scales" do
@@ -317,4 +455,4 @@ describe MusicUtils do
317
455
  end
318
456
  end
319
457
 
320
- end
458
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: music-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-21 00:00:00.000000000Z
12
+ date: 2011-05-25 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &85936420 !ruby/object:Gem::Requirement
16
+ requirement: &85461120 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0.8'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *85936420
24
+ version_requirements: *85461120
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &85936230 !ruby/object:Gem::Requirement
27
+ requirement: &85460930 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *85936230
35
+ version_requirements: *85460930
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &85936000 !ruby/object:Gem::Requirement
38
+ requirement: &85460700 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *85936000
46
+ version_requirements: *85460700
47
47
  description: Utils to classify music intervals, create scales and more. See README.md
48
48
  and CHANGELOG.md on homepage for more info.
49
49
  email: