music-utils 1.0.2 → 1.1.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/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