music-utils 1.1.2 → 1.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.
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: