music-utils 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,8 +1,17 @@
1
+ ## 1.1.0 (May 19, 2011)
2
+
3
+ Features:
4
+
5
+ - Added functionality to create major and minor scales
6
+ - Minor performance improvement to qualify intervals
7
+
8
+
1
9
  ## 1.0.2 (May 12, 2011)
2
10
 
3
11
  Features:
4
12
 
5
13
  - Fixed do-sol bug
14
+ - Fixed bug on 6th number quality
6
15
 
7
16
 
8
17
  ## 1.0.1 (May 6, 2011)
data/README.md CHANGED
@@ -1,30 +1,25 @@
1
1
  music-utils
2
2
  =========
3
3
 
4
- Utils for music. At the moment only to classify interval.
4
+ Utils for music. For now to classify music intervals and create scales.
5
5
 
6
6
  Examples
7
7
  --------
8
- Simple intervals:
8
+ Simple and Compound intervals:
9
9
 
10
- * MusicUtils.number('do', 'mi') #=> 3 (3th)
11
- * MusicUtils.semitones('do', 'mi') #=> 4 (semi-tones)
12
- * MusicUtils.quality('do', 'mi') #=> M (major)
13
- * MusicUtils.quality('do#', 'mi') #=> m (minor)
14
-
15
- Compound intervals:
16
-
17
- * MusicUtils.number('do', 'mi', 1) #=> 10 (10th)
18
- * MusicUtils.semitones('do', 'mi', 1) #=> 16 (semi-tones)
19
- * MusicUtils.quality('do', 'mi', 1) #=> M (major)
20
- * MusicUtils.quality('dob', 'mi#', 1) #=> AA (augmented plus)
10
+ MusicUtils.number(:do, :mi) #=> 3 (3th)
11
+ MusicUtils.semitones(:do, :mi, 1) #=> 16 (semi-tones)
12
+ MusicUtils.quality(:do, :mi) #=> M (major)
21
13
 
22
14
  Short Notation:
23
15
 
24
- * MusicUtils.short('do', 're') #=> M2
25
- * MusicUtils.short('do', 're', 1) #=> M9
26
- * MusicUtils.short('do#', 'mi') #=> m3
27
- * MusicUtils.short('do#', 'mi', 1) #=> m10
16
+ MusicUtils.short(:do, :re) #=> M2
17
+ MusicUtils.short(:do, :re, 1) #=> M9
18
+
19
+ Create scales:
20
+
21
+ MusicUtils.scale(:fa, MusicUtils::MAJ_SCALE) #=> [:fa, :sol, :la, :sib, :do, :re, :mi]
22
+
28
23
 
29
24
  Installation
30
25
  -----------
data/Rakefile CHANGED
@@ -26,4 +26,10 @@ Bundler::GemHelper.install_tasks
26
26
  desc "Clean automatically generated files"
27
27
  task :clean do
28
28
  FileUtils.rm_rf "pkg"
29
- end
29
+ end
30
+
31
+ # Profiler tasks
32
+ desc "Run profiler"
33
+ task :profile do
34
+ `ruby -w -rprofile benchmark/music-utils_bm.rb 10000`
35
+ end
@@ -4,27 +4,36 @@ require 'music-utils'
4
4
  require 'music-utils/scales/scales'
5
5
  require 'benchmark'
6
6
 
7
- n = 100_000
7
+ n = (ARGV[0].to_i != 0) ? ARGV[0].to_i : 100000
8
8
  label_width = 60
9
9
 
10
+ # Helper method to print benchmarks titles
11
+ def title(desc, n)
12
+ puts '-' * 105
13
+ puts desc + ' ' + n.to_s + ' times: '
14
+ end
15
+
16
+ # Benchmarks
17
+
18
+ title 'Classifying do-mi interval', n
10
19
  Benchmark.bm(label_width) do |b|
11
- b.report('Classifying do-mi interval with strings (number):') do
20
+ b.report('with strings (number):') do
12
21
  n.times { MusicUtils.number('do', 'mi') }
13
22
  end
14
- b.report('Classifying do-mi interval with strings (quality):') do
23
+ b.report('with strings (quality):') do
15
24
  n.times { MusicUtils.quality('do', 'mi') }
16
25
  end
17
- b.report('Classifying do-mi interval with strings (short notation):') do
26
+ b.report('with strings (short notation):') do
18
27
  n.times { MusicUtils.short('do', 'mi') }
19
28
  end
20
29
 
21
- b.report('Classifying do-mi interval with scales (number):') do
30
+ b.report('with scales (number):') do
22
31
  n.times { MusicUtils.number(Scales::DO, Scales::MI) }
23
32
  end
24
- b.report('Classifying do-mi interval with scales (quality):') do
33
+ b.report('with scales (quality):') do
25
34
  n.times { MusicUtils.quality(Scales::DO, Scales::MI) }
26
35
  end
27
- b.report('Classifying do-mi interval with scales (short notation):') do
36
+ b.report('with scales (short notation):') do
28
37
  n.times { MusicUtils.short(Scales::DO, Scales::MI) }
29
38
  end
30
39
  end
data/lib/music-utils.rb CHANGED
@@ -24,5 +24,10 @@ module MusicUtils
24
24
  def MusicUtils.short(note1, note2, step = 0)
25
25
  Interval.new(note1, note2, step).short
26
26
  end
27
+
28
+ # Returns a scale
29
+ def MusicUtils.scale(from, scale)
30
+ Scales.scale(from, scale)
31
+ end
27
32
 
28
33
  end
@@ -1,30 +1,18 @@
1
1
  require 'music-utils/scales/scales'
2
+ require 'music-utils/note/note'
2
3
 
3
- # This class represents a music interval
4
4
  module MusicUtils
5
5
 
6
+ # This class represents a music interval
6
7
  class Interval
7
8
  include Scales
8
9
 
9
10
  def initialize(note1, note2, step)
10
-
11
- # SOL is the only note of length = 3
12
- n = 0
13
- n += 1 if note1[0..2].to_sym == SOL
14
-
15
- @note1 = note1[0..1 + n].to_sym
16
- @note1_alt = note1[2 + n..3 + n]
17
-
18
- # SOL is the only note of length = 3
19
- n = 0
20
- n += 1 if note2[0..2].to_sym == SOL
21
-
22
- @note2 = note2[0..1 + n].to_sym
23
- @note2_alt = note2[2 + n..3 + n]
24
-
11
+ @note1, @note1_alt = MusicUtils::Note.parse(note1)
12
+ @note2, @note2_alt = MusicUtils::Note.parse(note2)
25
13
  @step = step
26
14
  end
27
-
15
+
28
16
  # It classifies the diatonic interval
29
17
  def number
30
18
  # initialize counter and index of scale
@@ -61,16 +49,20 @@ module MusicUtils
61
49
  count = count + (12 * @step) if @step > 0
62
50
 
63
51
  # counting notes alterations
64
- count += 1 if @note1_alt == Scales::FLAT
65
- coutn += 2 if @note1_alt == Scales::DFLAT
66
- count -= 1 if @note1_alt == Scales::SHARP
67
- count -= 1 if @note1_alt == Scales::DSHARP
68
-
69
- count -= 1 if @note2_alt == Scales::FLAT
70
- count -= 2 if @note2_alt == Scales::DFLAT
71
- count += 1 if @note2_alt == Scales::SHARP
72
- count -= 2 if @note2_alt == Scales::DSHARP
73
-
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
+
74
66
  count
75
67
  end
76
68
 
@@ -90,10 +82,11 @@ module MusicUtils
90
82
 
91
83
  # Common loop to search note 2
92
84
  def until_find_note2(i)
85
+ length = DIATONIC_SCALE.length
93
86
  # search note2
94
87
  while DIATONIC_SCALE[i] != @note2
95
88
  i += 1
96
- if i > DIATONIC_SCALE.length
89
+ if i > length
97
90
  i = 0; next
98
91
  end
99
92
  yield i
@@ -112,7 +105,7 @@ module MusicUtils
112
105
  def note1_index
113
106
  DIATONIC_SCALE.index(@note1)
114
107
  end
115
-
108
+
116
109
  end
117
110
 
118
111
  end
@@ -0,0 +1,21 @@
1
+ module MusicUtils
2
+
3
+ # Represents a music note
4
+ class Note
5
+
6
+ # Parse notes to obtaining the raw note and its alterations separately
7
+ def self.parse(note)
8
+ n = 0
9
+
10
+ # SOL is the only note of length = 3
11
+ n += 1 if note[0..2].to_sym == MusicUtils::SOL
12
+
13
+ note_aux = note[0..1 + n].to_sym
14
+ note_alt = note[2 + n..3 + n]
15
+
16
+ [note_aux, note_alt]
17
+ end
18
+
19
+ end
20
+
21
+ end
@@ -1,3 +1,5 @@
1
+ require 'music-utils/note/note'
2
+
1
3
  # Scales module
2
4
  module Scales
3
5
 
@@ -11,49 +13,54 @@ module Scales
11
13
  SI = :si
12
14
 
13
15
  DIATONIC_SCALE = [DO, RE, MI, FA, SOL, LA, SI]
14
-
16
+
15
17
  # Alterations:
16
- FLAT = 'b'
18
+ FLAT = 'f'
17
19
  DFLAT = FLAT + FLAT
18
- SHARP = '#'
20
+ SHARP = 's'
19
21
  DSHARP = SHARP + SHARP
20
22
 
21
23
  # Altered notes
22
- DOF = DO.to_s + FLAT
23
- DOFF = DO.to_s + DFLAT
24
- DOS = DO.to_s + SHARP
25
- DOSS = DO.to_s + DSHARP
24
+ DOF = (DO.to_s + FLAT).to_sym
25
+ DOFF = (DO.to_s + DFLAT).to_sym
26
+ DOS = (DO.to_s + SHARP).to_sym
27
+ DOSS = (DO.to_s + DSHARP).to_sym
26
28
 
27
- REF = RE.to_s + FLAT
28
- REFF = RE.to_s + DFLAT
29
- RES = RE.to_s + SHARP
30
- RESS = RE.to_s + DSHARP
29
+ REF = (RE.to_s + FLAT).to_sym
30
+ REFF = (RE.to_s + DFLAT).to_sym
31
+ RES = (RE.to_s + SHARP).to_sym
32
+ RESS = (RE.to_s + DSHARP).to_sym
31
33
 
32
- MIF = MI.to_s + FLAT
33
- MIFF = MI.to_s + DFLAT
34
- MIS = MI.to_s + SHARP
35
- MISS = MI.to_s + DSHARP
34
+ MIF = (MI.to_s + FLAT).to_sym
35
+ MIFF = (MI.to_s + DFLAT).to_sym
36
+ MIS = (MI.to_s + SHARP).to_sym
37
+ MISS = (MI.to_s + DSHARP).to_sym
36
38
 
37
- FAF = FA.to_s + FLAT
38
- FAFF = FA.to_s + DFLAT
39
- FAS = FA.to_s + SHARP
40
- FASS = FA.to_s + DSHARP
39
+ FAF = (FA.to_s + FLAT).to_sym
40
+ FAFF = (FA.to_s + DFLAT).to_sym
41
+ FAS = (FA.to_s + SHARP).to_sym
42
+ FASS = (FA.to_s + DSHARP).to_sym
41
43
 
42
- SOLF = SOL.to_s + FLAT
43
- SOLFF = SOL.to_s + DFLAT
44
- SOLS = SOL.to_s + SHARP
45
- SOLSS = SOL.to_s + DSHARP
44
+ SOLF = (SOL.to_s + FLAT).to_sym
45
+ SOLFF = (SOL.to_s + DFLAT).to_sym
46
+ SOLS = (SOL.to_s + SHARP).to_sym
47
+ SOLSS = (SOL.to_s + DSHARP).to_sym
46
48
 
47
- LAF = LA.to_s + FLAT
48
- LAFF = LA.to_s + DFLAT
49
- LAS = LA.to_s + SHARP
50
- LASS = LA.to_s + DSHARP
49
+ LAF = (LA.to_s + FLAT).to_sym
50
+ LAFF = (LA.to_s + DFLAT).to_sym
51
+ LAS = (LA.to_s + SHARP).to_sym
52
+ LASS = (LA.to_s + DSHARP).to_sym
51
53
 
52
- SIF = SI.to_s + FLAT
53
- SIFF = SI.to_s + DFLAT
54
- SIS = SI.to_s + SHARP
55
- SISS = SI.to_s + DSHARP
54
+ SIF = (SI.to_s + FLAT).to_sym
55
+ SIFF = (SI.to_s + DFLAT).to_sym
56
+ SIS = (SI.to_s + SHARP).to_sym
57
+ SISS = (SI.to_s + DSHARP).to_sym
56
58
 
59
+ 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
+ MAJ_SCALE = [2, 2, 1, 2, 2, 2, 1]
61
+ NATURAL_MIN_SCALE = [2, 1, 2, 2, 1, 2, 2]
62
+ MELODIC_MIN_SCALE = [2, 1, 2, 2, 1, 2, 1]
63
+
57
64
  # Qualities
58
65
  PERF = 'P'
59
66
  MAJ = 'M'
@@ -73,5 +80,71 @@ module Scales
73
80
  7 => {8 => DIMP, 9 => DIM, 10 => MIN, 11 => MAJ, 12 => AUG, 13 => AUGP},
74
81
  8 => {10 => DIMP, 11 => DIM, 12 => PERF, 13 => AUG, 14 => AUGP}
75
82
  }
83
+
84
+ # Create scale from a note and scale structure
85
+ def Scales.scale(from, scale_struct)
86
+ from = from.to_sym
87
+
88
+ i = 0
89
+ find_it = false
90
+ CROMATIC_SCALE.each do |e|
91
+ if e.is_a?(Array)
92
+ e.each do |ee|
93
+ find_it = true if from == ee
94
+ end
95
+ else
96
+ find_it = true if from == e
97
+ end
98
+ break if find_it
99
+ i += 1
100
+ end
101
+
102
+ scale = []
103
+ scale << from
104
+
105
+ from_note, from_alter = MusicUtils::Note.parse(from)
106
+
107
+ diatonic_scale = diatonic_scale_from(from_note)
108
+ diatonic_scale.delete(from_note)
109
+
110
+ length = CROMATIC_SCALE.length
111
+
112
+ scale_struct.each do |shift|
113
+ if i + shift > length - 1
114
+ i = (i + shift) - (length)
115
+ shift = 0
116
+ end
117
+
118
+ CROMATIC_SCALE[i + shift].each do |e|
119
+ e_note, e_alter = MusicUtils::Note.parse(e)
120
+
121
+ if diatonic_scale.first == e_note
122
+ scale << e
123
+ diatonic_scale.delete(diatonic_scale.first)
124
+ break
125
+ end
126
+ end
127
+ i += shift
128
+ end
129
+
130
+ scale
131
+ end
132
+
133
+ # Create a diatonic scale starting with the "from" note
134
+ def Scales.diatonic_scale_from(from)
135
+ diatonic_scale = []
136
+ length = DIATONIC_SCALE.length
137
+ i = DIATONIC_SCALE.index(from)
138
+ c = 0
139
+ while c < length
140
+ diatonic_scale << DIATONIC_SCALE[i]
141
+ i += 1
142
+ c += 1
143
+ if i > length - 1
144
+ i = 0
145
+ end
146
+ end
147
+ diatonic_scale
148
+ end
76
149
 
77
150
  end
@@ -1,3 +1,3 @@
1
1
  module MusicUtils
2
- VERSION = '1.0.2'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -27,7 +27,7 @@ describe MusicUtils::Interval do
27
27
  end
28
28
 
29
29
  it "simple interval dob-mi# should be 6 semitones" do
30
- i = Interval.new('dob', 'mi#', 0)
30
+ i = Interval.new('dof', 'mis', 0)
31
31
  i.semitones.should == 6
32
32
  end
33
33
 
@@ -54,12 +54,12 @@ describe MusicUtils::Interval do
54
54
  end
55
55
 
56
56
  it "quality of interval do#-mi should be m" do
57
- i = Interval.new('do#', 'mi', 0)
57
+ i = Interval.new('dos', 'mi', 0)
58
58
  i.quality.should == 'm'
59
59
  end
60
60
 
61
61
  it "quality of interval do#-mi should be m" do
62
- i = Interval.new('do#', 'mi', 0)
62
+ i = Interval.new('dos', 'mi', 0)
63
63
  i.quality.should == 'm'
64
64
  end
65
65
 
@@ -69,7 +69,7 @@ describe MusicUtils::Interval do
69
69
  end
70
70
 
71
71
  it "quality of compound interval dob-mi# should be AA" do
72
- i = Interval.new('dob', 'mi#', 1)
72
+ i = Interval.new('dof', 'mis', 1)
73
73
  i.quality.should == 'AA'
74
74
  end
75
75
 
@@ -92,12 +92,12 @@ describe MusicUtils::Interval do
92
92
  end
93
93
 
94
94
  it "the short notation of do#-mi interval should be m3" do
95
- i = Interval.new('do#', 'mi', 0)
95
+ i = Interval.new('dos', 'mi', 0)
96
96
  i.short.should == 'm3'
97
97
  end
98
98
 
99
99
  it "the short notation of do#-mi compound interval should be m10" do
100
- i = Interval.new('do#', 'mi', 1)
100
+ i = Interval.new('dos', 'mi', 1)
101
101
  i.short.should == 'm10'
102
102
  end
103
103
 
@@ -6,29 +6,131 @@ describe MusicUtils do
6
6
  context "Intervals" do
7
7
 
8
8
  context "By number" do
9
- it "the number of simple interval do-mi should be a 3rd" do
10
- MusicUtils.number(DO, MI).should == 3
11
- end
12
- it "the number of do-mi compound interval should be a 10th" do
13
- MusicUtils.number(DO, MI, 1).should == 10
9
+ context "Diatonic from DO" do
10
+ it "the number of simple interval do-re should be a 2th" do
11
+ MusicUtils.number(DO, RE).should == 2
12
+ end
13
+ it "the number of do-re compound interval should be a 9th" do
14
+ MusicUtils.number(DO, RE, 1).should == 9
15
+ end
16
+ it "the number of simple interval do-mi should be a 3rd" do
17
+ MusicUtils.number(DO, MI).should == 3
18
+ end
19
+ it "the number of do-mi compound interval should be a 10th" do
20
+ MusicUtils.number(DO, MI, 1).should == 10
21
+ end
22
+ it "the number of simple interval do-fa should be a 4th" do
23
+ MusicUtils.number(DO, FA).should == 4
24
+ end
25
+ it "the number of do-fa compound interval should be a 11th" do
26
+ MusicUtils.number(DO, FA, 1).should == 11
27
+ end
28
+ it "the number of simple interval do-sol should be a 5th" do
29
+ MusicUtils.number(DO, SOL).should == 5
30
+ end
31
+ it "the number of do-sol compound interval should be a 12th" do
32
+ MusicUtils.number(DO, SOL, 1).should == 12
33
+ end
34
+ it "the number of simple interval do-la should be a 6th" do
35
+ MusicUtils.number(DO, LA).should == 6
36
+ end
37
+ it "the number of do-la compound interval should be a 13th" do
38
+ MusicUtils.number(DO, LA, 1).should == 13
39
+ end
40
+ it "the number of simple interval do-si should be a 7th" do
41
+ MusicUtils.number(DO, SI).should == 7
42
+ end
43
+ it "the number of do-si compound interval should be a 14th" do
44
+ MusicUtils.number(DO, SI, 1).should == 14
45
+ end
46
+ it "the number of simple interval do-do should be a 8th" do
47
+ MusicUtils.number(DO, DO).should == 8
48
+ end
49
+ it "the number of do-do compound interval should be a 15th" do
50
+ MusicUtils.number(DO, DO, 1).should == 15
51
+ end
14
52
  end
15
53
  end
16
54
 
17
- context "By semitones" do
18
- it "simple interval do-mi should be 4 semitones" do
19
- MusicUtils.semitones(DO, MI).should == 4
20
- end
21
- it "compound interval do-mi should be 16 semitones" do
22
- MusicUtils.semitones(DO, MI, 1).should == 16
55
+ context "By semitones" do
56
+ context "Diatonic from DO" do
57
+ it "simple interval do-re should be 2 semitones" do
58
+ MusicUtils.semitones(DO, RE).should == 2
59
+ end
60
+ it "compound interval do-re should be 14 semitones" do
61
+ MusicUtils.semitones(DO, RE, 1).should == 14
62
+ end
63
+ it "simple interval do-mi should be 4 semitones" do
64
+ MusicUtils.semitones(DO, MI).should == 4
65
+ end
66
+ it "compound interval do-mi should be 16 semitones" do
67
+ MusicUtils.semitones(DO, MI, 1).should == 16
68
+ end
69
+ it "simple interval do-fa should be 5 semitones" do
70
+ MusicUtils.semitones(DO, FA).should == 5
71
+ end
72
+ it "compound interval do-fa should be 17 semitones" do
73
+ MusicUtils.semitones(DO, FA, 1).should == 17
74
+ end
75
+ it "simple interval do-sol should be 7 semitones" do
76
+ MusicUtils.semitones(DO, SOL).should == 7
77
+ end
78
+ it "compound interval do-sol should be 17 semitones" do
79
+ MusicUtils.semitones(DO, SOL, 1).should == 19
80
+ end
81
+ it "simple interval do-la should be 9 semitones" do
82
+ MusicUtils.semitones(DO, LA).should == 9
83
+ end
84
+ it "compound interval do-la should be 21 semitones" do
85
+ MusicUtils.semitones(DO, LA, 1).should == 21
86
+ end
87
+ it "simple interval do-si should be 11 semitones" do
88
+ MusicUtils.semitones(DO, SI).should == 11
89
+ end
90
+ it "compound interval do-si should be 21 semitones" do
91
+ MusicUtils.semitones(DO, SI, 1).should == 23
92
+ end
23
93
  end
24
94
  end
25
95
 
26
- context "By quality" do
27
- it "quality of interval do-mi should be M" do
28
- MusicUtils.quality(DO, MI).should == 'M'
29
- end
30
- it "quality of compound interval do-mi should be M" do
31
- MusicUtils.quality(DO, MI, 1).should == 'M'
96
+ context "By quality" do
97
+ context "Diatonic from DO" do
98
+ it "quality of interval do-re should be M" do
99
+ MusicUtils.quality(DO, RE).should == 'M'
100
+ end
101
+ it "quality of compound interval do-re should be M" do
102
+ MusicUtils.quality(DO, RE, 1).should == 'M'
103
+ end
104
+ it "quality of interval do-mi should be M" do
105
+ MusicUtils.quality(DO, MI).should == 'M'
106
+ end
107
+ it "quality of compound interval do-mi should be M" do
108
+ MusicUtils.quality(DO, MI, 1).should == 'M'
109
+ end
110
+ it "quality of interval do-fa should be P" do
111
+ MusicUtils.quality(DO, FA).should == 'P'
112
+ end
113
+ it "quality of compound interval do-fa should be P" do
114
+ MusicUtils.quality(DO, FA, 1).should == 'P'
115
+ end
116
+ it "quality of interval do-sol should be P" do
117
+ MusicUtils.quality(DO, SOL).should == 'P'
118
+ end
119
+ it "quality of compound interval do-sol should be P" do
120
+ MusicUtils.quality(DO, SOL, 1).should == 'P'
121
+ end
122
+ it "quality of interval do-la should be m" do
123
+ MusicUtils.quality(DO, LA).should == 'm'
124
+ end
125
+ it "quality of compound interval do-la should be m" do
126
+ MusicUtils.quality(DO, LA, 1).should == 'm'
127
+ end
128
+ it "quality of interval do-si should be M" do
129
+ MusicUtils.quality(DO, SI).should == 'M'
130
+ end
131
+ it "quality of compound interval do-si should be M" do
132
+ MusicUtils.quality(DO, SI, 1).should == 'M'
133
+ end
32
134
  end
33
135
  end
34
136
 
@@ -43,4 +145,153 @@ describe MusicUtils do
43
145
 
44
146
  end
45
147
 
148
+ context "Scales" do
149
+ context "Major scale" do
150
+ context "Natural notes" do
151
+ it "the major scale of DO should be [DO, RE, MI, FA, SOL, LA, SI, DO]" do
152
+ MusicUtils.scale(DO, MAJ_SCALE).should == [DO, RE, MI, FA, SOL, LA, SI]
153
+ end
154
+ it "the major scale of RE should be [RE, MI, FAS, SOL, LA, SI, DOS, RE]" do
155
+ MusicUtils.scale(RE, MAJ_SCALE).should == [RE, MI, FAS, SOL, LA, SI, DOS]
156
+ end
157
+ it "the major scale of MI should be [MI, FAS, SOLS, LA, SI, DOS, RES, MI]" do
158
+ MusicUtils.scale(MI, MAJ_SCALE).should == [MI, FAS, SOLS, LA, SI, DOS, RES]
159
+ end
160
+ it "the major scale of FA should be [FA, SOL, LA, SIF, DO, RE, MI, FA]" do
161
+ MusicUtils.scale(FA, MAJ_SCALE).should == [FA, SOL, LA, SIF, DO, RE, MI]
162
+ end
163
+ it "the major scale of SOL should be [SOL, LA, SI, DO, RE, MI, FAS, SOL]" do
164
+ MusicUtils.scale(SOL, MAJ_SCALE).should == [SOL, LA, SI, DO, RE, MI, FAS]
165
+ end
166
+ it "the major scale of LA should be [LA, SI, DOS, RE, MI, FAS, SOLS, LA]" do
167
+ MusicUtils.scale(LA, MAJ_SCALE).should == [LA, SI, DOS, RE, MI, FAS, SOLS]
168
+ end
169
+ it "the major scale of SI should be [SI, DOS, RES, MI, FAS, SOLS, LAS, SI]" do
170
+ MusicUtils.scale(SI, MAJ_SCALE).should == [SI, DOS, RES, MI, FAS, SOLS, LAS]
171
+ end
172
+ end
173
+ context "Sharped notes" do
174
+ it "the major scale of DO# should be [DOS, RES, MIS, FAS, SOLS, LAS, SIS]" do
175
+ MusicUtils.scale(DOS, MAJ_SCALE).should == [DOS, RES, MIS, FAS, SOLS, LAS, SIS]
176
+ end
177
+ it "the major scale of RE# should be [RES, MIS, FASS, SOLS, LAS, SIS, DOSS]" do
178
+ MusicUtils.scale(RES, MAJ_SCALE).should == [RES, MIS, FASS, SOLS, LAS, SIS, DOSS]
179
+ end
180
+ it "the major scale of MI# should be [MIS, FASS, SOLSS, LAS, SIS, DOSS, RESS]" do
181
+ MusicUtils.scale(MIS, MAJ_SCALE).should == [MIS, FASS, SOLSS, LAS, SIS, DOSS, RESS]
182
+ end
183
+ it "the major scale of FA# should be [FAS, SOLS, LAS, SI, DOS, RES, MISS]" do
184
+ MusicUtils.scale(FAS, MAJ_SCALE).should == [FAS, SOLS, LAS, SI, DOS, RES, MIS]
185
+ end
186
+ it "the major scale of SOL# should be [SOLS, LAS, SIS, DOS, RES, MIS, FASS]" do
187
+ MusicUtils.scale(SOLS, MAJ_SCALE).should == [SOLS, LAS, SIS, DOS, RES, MIS, FASS]
188
+ end
189
+ it "the major scale of LA# should be [SOLS, LAS, SIS, DOS, RES, MIS, FASS]" do
190
+ MusicUtils.scale(LAS, MAJ_SCALE).should == [LAS, SIS, DOSS, RES, MIS, FASS, SOLSS]
191
+ end
192
+ it "the major scale of SI# should be [SIS, DOSS, RESS, MIS, FASS, SOLSS, LASS]" do
193
+ MusicUtils.scale(SIS, MAJ_SCALE).should == [SIS, DOSS, RESS, MIS, FASS, SOLSS, LASS]
194
+ end
195
+ end
196
+ context "Flated notes" do
197
+ it "the major scale of DOb should be [DOF, REF, MIF, FAF, SOLF, LAF, SIF]" do
198
+ MusicUtils.scale(DOF, MAJ_SCALE).should == [DOF, REF, MIF, FAF, SOLF, LAF, SIF]
199
+ end
200
+ it "the major scale of REb should be [REF, MIF, FA, SOLF, LAF, SIF, DO]" do
201
+ MusicUtils.scale(REF, MAJ_SCALE).should == [REF, MIF, FA, SOLF, LAF, SIF, DO]
202
+ end
203
+ it "the major scale of MIb should be [MIF, FA, SOL, LAF, SIF, DO, RE]" do
204
+ MusicUtils.scale(MIF, MAJ_SCALE).should == [MIF, FA, SOL, LAF, SIF, DO, RE]
205
+ end
206
+ it "the major scale of FAb should be [FAF, SOLF, LAF, SIFF, DOF, REF, MIF]" do
207
+ MusicUtils.scale(FAF, MAJ_SCALE).should == [FAF, SOLF, LAF, SIFF, DOF, REF, MIF]
208
+ end
209
+ it "the major scale of SOLb should be [SOLF, LAF, SIF, DOF, REF, MIF, FA]" do
210
+ MusicUtils.scale(SOLF, MAJ_SCALE).should == [SOLF, LAF, SIF, DOF, REF, MIF, FA]
211
+ end
212
+ it "the major scale of LAb should be [LAF, SIF, DO, REF, MIF, FA, SOL]" do
213
+ MusicUtils.scale(LAF, MAJ_SCALE).should == [LAF, SIF, DO, REF, MIF, FA, SOL]
214
+ end
215
+ it "the major scale of SIb should be [SIF, DO, RE, MIF, FA, SOL, LA]" do
216
+ MusicUtils.scale(SIF, MAJ_SCALE).should == [SIF, DO, RE, MIF, FA, SOL, LA]
217
+ end
218
+ end
219
+ context "Natural Minor scale" do
220
+ # [2, 1, 2, 2, 1, 2]
221
+ context "Natural notes" do
222
+ it "the natural minor scale of DO should be [DO, RE, MIF, FA, SOL, LAF, SIF]" do
223
+ MusicUtils.scale(DO, NATURAL_MIN_SCALE).should == [DO, RE, MIF, FA, SOL, LAF, SIF]
224
+ end
225
+ it "the natural minor scale of RE should be [RE, MI, FA, SOL, LA, SIF, DO]" do
226
+ MusicUtils.scale(RE, NATURAL_MIN_SCALE).should == [RE, MI, FA, SOL, LA, SIF, DO]
227
+ end
228
+ it "the natural minor scale of MI should be [MI, FAS, SOL, LA, SI, DO, RE]" do
229
+ MusicUtils.scale(MI, NATURAL_MIN_SCALE).should == [MI, FAS, SOL, LA, SI, DO, RE]
230
+ end
231
+ it "the natural minor scale of FA should be [FA, SOL, LAF, SIF, DO, REF, MIF]" do
232
+ MusicUtils.scale(FA, NATURAL_MIN_SCALE).should == [FA, SOL, LAF, SIF, DO, REF, MIF]
233
+ end
234
+ it "the natural minor scale of SOL should be [SOL, LA, SIF, DO, RE, MIF, FA]" do
235
+ MusicUtils.scale(SOL, NATURAL_MIN_SCALE).should == [SOL, LA, SIF, DO, RE, MIF, FA]
236
+ end
237
+ it "the natural minor scale of LA should be [LA, SI, DO, RE, MI, FA, SOL]" do
238
+ MusicUtils.scale(LA, NATURAL_MIN_SCALE).should == [LA, SI, DO, RE, MI, FA, SOL]
239
+ end
240
+ it "the natural minor scale of SI should be [SI, DOS, RES, MI, FAS, SOLS, LAS, SI]" do
241
+ MusicUtils.scale(SI, NATURAL_MIN_SCALE).should == [SI, DOS, RE, MI, FAS, SOL, LA]
242
+ end
243
+ end
244
+ # [2, 1, 2, 2, 1, 2]
245
+ context "Sharped notes" do
246
+ it "the natural minor scale of DO# should be [DO, RE, MIF, FA, SOL, LAF, SIF]" do
247
+ MusicUtils.scale(DOS, NATURAL_MIN_SCALE).should == [DOS, RES, MI, FAS, SOLS, LA, SI]
248
+ end
249
+ it "the natural minor scale of RE# should be [RE, MI, FA, SOL, LA, SIF, DO]" do
250
+ MusicUtils.scale(RES, NATURAL_MIN_SCALE).should == [RES, MIS, FAS, SOLS, LAS, SI, DOS]
251
+ end
252
+ it "the natural minor scale of MI# should be [MI, FAS, SOL, LA, SI, DO, RE]" do
253
+ MusicUtils.scale(MIS, NATURAL_MIN_SCALE).should == [MIS, FASS, SOLS, LAS, SIS, DOS, RES]
254
+ end
255
+ it "the natural minor scale of FA# should be [FA, SOL, LAF, SIF, DO, REF, MIF]" do
256
+ MusicUtils.scale(FAS, NATURAL_MIN_SCALE).should == [FAS, SOLS, LA, SI, DOS, RE, MI]
257
+ end
258
+ it "the natural minor scale of SOL# should be [SOL, LA, SIF, DO, RE, MIF, FA]" do
259
+ MusicUtils.scale(SOLS, NATURAL_MIN_SCALE).should == [SOLS, LAS, SI, DOS, RES, MI, FAS]
260
+ end
261
+ it "the natural minor scale of LA# should be [LA, SI, DO, RE, MI, FA, SOL]" do
262
+ MusicUtils.scale(LAS, NATURAL_MIN_SCALE).should == [LAS, SIS, DOS, RES, MIS, FAS, SOLS]
263
+ end
264
+ it "the natural minor scale of SI# should be [SI, DOS, RES, MI, FAS, SOLS, LAS, SI]" do
265
+ MusicUtils.scale(SIS, NATURAL_MIN_SCALE).should == [SIS, DOSS, RES, MIS, FASS, SOLS, LAS]
266
+ end
267
+ end
268
+ # [2, 1, 2, 2, 1, 2]
269
+ context "Flated notes" do
270
+ it "the natural minor scale of DOb should be [DOF, REF, MIFF, FAF, SOLF, LAFF, SIFF]" do
271
+ MusicUtils.scale(DOF, NATURAL_MIN_SCALE).should == [DOF, REF, MIFF, FAF, SOLF, LAFF, SIFF]
272
+ end
273
+ it "the natural minor scale of REb should be [REF, MIF, FAF, SOLF, LAF, SIFF, DOF]" do
274
+ MusicUtils.scale(REF, NATURAL_MIN_SCALE).should == [REF, MIF, FAF, SOLF, LAF, SIFF, DOF]
275
+ end
276
+ it "the natural minor scale of MIb should be [MIF, FA, SOLF, LAF, SIF, DOF, REF]" do
277
+ MusicUtils.scale(MIF, NATURAL_MIN_SCALE).should == [MIF, FA, SOLF, LAF, SIF, DOF, REF]
278
+ end
279
+ it "the natural minor scale of FAb should be [FAF, SOLF, LAFF, SIFF, DOF, REFF, MIFF]" do
280
+ MusicUtils.scale(FAF, NATURAL_MIN_SCALE).should == [FAF, SOLF, LAFF, SIFF, DOF, REFF, MIFF]
281
+ end
282
+ it "the natural minor scale of SOLb should be [SOLF, LAF, SIFF, DOF, REF, MIFF, FAF]" do
283
+ MusicUtils.scale(SOLF, NATURAL_MIN_SCALE).should == [SOLF, LAF, SIFF, DOF, REF, MIFF, FAF]
284
+ end
285
+ it "the natural minor scale of LAb should be [LAF, SIF, DOF, REF, MIF, FAF, SOLF]" do
286
+ MusicUtils.scale(LAF, NATURAL_MIN_SCALE).should == [LAF, SIF, DOF, REF, MIF, FAF, SOLF]
287
+ end
288
+ it "the natural minor scale of SIb should be [SIF, DO, REF, MIF, FA, SOLF, LAF]" do
289
+ MusicUtils.scale(SIF, NATURAL_MIN_SCALE).should == [SIF, DO, REF, MIF, FA, SOLF, LAF]
290
+ end
291
+ end
292
+ end
293
+
294
+ end
295
+ end
296
+
46
297
  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.0.2
4
+ version: 1.1.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-12 00:00:00.000000000Z
12
+ date: 2011-05-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &84854900 !ruby/object:Gem::Requirement
16
+ requirement: &75690210 !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: *84854900
24
+ version_requirements: *75690210
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &84854710 !ruby/object:Gem::Requirement
27
+ requirement: &75690020 !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: *84854710
35
+ version_requirements: *75690020
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &84854480 !ruby/object:Gem::Requirement
38
+ requirement: &75689790 !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: *84854480
46
+ version_requirements: *75689790
47
47
  description: Utils for music. At the moment only to classify intervals.
48
48
  email:
49
49
  - jorgeluis700@gmail.com
@@ -60,6 +60,7 @@ files:
60
60
  - benchmark/music-utils_bm.rb
61
61
  - lib/music-utils.rb
62
62
  - lib/music-utils/interval/interval.rb
63
+ - lib/music-utils/note/note.rb
63
64
  - lib/music-utils/scales/scales.rb
64
65
  - lib/music-utils/version.rb
65
66
  - music-utils.gemspec