music-utils 0.5.2 → 1.0.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
@@ -2,4 +2,7 @@
2
2
  .redcar/
3
3
 
4
4
  # build directory
5
- pkg/
5
+ pkg/
6
+
7
+ # Gems
8
+ Gemfile.lock
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 1.0.0 (May 6, 2011)
2
+
3
+ Features:
4
+
5
+ - Added MusicUtils module
6
+ - New shortcuts for clasify intervals on MusicUtils module
7
+
8
+
9
+ ## 0.5.2 (April 29, 2011)
10
+
11
+ Features:
12
+
13
+ - Extracted some common logic into helper methods
14
+
15
+
1
16
  ## 0.5.1 (April 27, 2011)
2
17
 
3
18
  Features:
data/Gemfile CHANGED
@@ -1,3 +1,2 @@
1
1
  source "http://rubygems.org"
2
- gem "rake", ' ~> 0.8'
3
- gem "rspec", '~> 2.5'
2
+ gemspec
data/README.md CHANGED
@@ -1,30 +1,35 @@
1
1
  music-utils
2
2
  =========
3
3
 
4
- Utils for music. At the moment only one class to classify intervals.
4
+ Utils for music. At the moment only to classify interval.
5
5
 
6
6
  Examples
7
7
  --------
8
8
  Simple intervals:
9
9
 
10
- * Interval.new('do', 'mi', 0).number #=> 3 (3th)
11
- * Interval.new('do', 'mi', 0).semitone #=> 4 (semi-tones)
12
- * Interval.new('do', 'mi', 0).quality #=> M (major)
13
- * Interval.new('do#', 'mi', 0).quality #=> m (minor)
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
14
 
15
15
  Compound intervals:
16
16
 
17
- * Interval.new('do', 'mi', 1).number #=> 10 (10th)
18
- * Interval.new('do', 'mi', 1).semitone #=> 16 (semi-tones)
19
- * Interval.new('do', 'mi', 1).quality #=> M (major)
20
- * Interval.new('dob', 'mi#', 1).quality #=> AA (augmented plus)
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)
21
21
 
22
22
  Short Notation:
23
23
 
24
- * Interval.new('do', 're', 0).short #=> M2
25
- * Interval.new('do', 're', 1).short #=> M9
26
- * Interval.new('do#', 'mi', 0).short #=> m3
27
- * Interval.new('do#', 'mi', 1).short #=> m10
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
28
+
29
+ Installation
30
+ -----------
31
+
32
+ gem install music-utils
28
33
 
29
34
  To Do
30
35
  -----
data/Rakefile CHANGED
@@ -1,6 +1,3 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
1
  require 'rake'
5
2
  require 'rspec/core/rake_task'
6
3
 
@@ -16,27 +13,8 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
16
13
  end
17
14
 
18
15
  # Gems tasks
19
- desc "Load the gemspec"
20
- task :load_gemspec do
21
- @gemspec = eval(File.read(Dir["*.gemspec"].first))
22
- end
23
-
24
- desc "Validate the gemspec"
25
- task :gemspec => :load_gemspec do
26
- @gemspec.validate
27
- end
28
-
29
- desc "Build gem locally"
30
- task :build => :gemspec do
31
- system "gem build #{@gemspec.name}.gemspec"
32
- FileUtils.mkdir_p "pkg"
33
- FileUtils.mv "#{@gemspec.name}-#{@gemspec.version}.gem", "pkg"
34
- end
35
-
36
- desc "Install gem locally"
37
- task :install => :build do
38
- system "gem install pkg/#{@gemspec.name}-#{@gemspec.version}"
39
- end
16
+ require "bundler"
17
+ Bundler::GemHelper.install_tasks
40
18
 
41
19
  desc "Clean automatically generated files"
42
20
  task :clean do
@@ -0,0 +1,109 @@
1
+ require 'music-utils/scales/scales'
2
+
3
+ # This class represents a music interval
4
+ module MusicUtils
5
+
6
+ class Interval
7
+ include Scales
8
+
9
+ def initialize(note1, note2, step)
10
+ @note1 = note1
11
+ @note2 = note2
12
+ @step = step
13
+ end
14
+
15
+ # It classifies the diatonic interval
16
+ def number
17
+ # initialize counter and index of scale
18
+ i = note1_index
19
+ count = 1
20
+
21
+ count, i = no_unison(count, i)
22
+
23
+ # Counting notes
24
+ until_find_note2(i) { count += 1 }
25
+
26
+ count = count + (8 * @step) - 1 if @step > 0
27
+ count
28
+ end
29
+
30
+ # Returns the number of semitones
31
+ def semitones
32
+ # initialize counter and index of scale
33
+ i = note1_index
34
+ count = 0
35
+
36
+ count, i = no_unison(count, i)
37
+
38
+ # counting semi-tones
39
+ until_find_note2(i) do |i|
40
+ # from 'mi' to 'fa' and 'si' to 'do' there 1 semi-tone
41
+ if DIATONIC_SCALE[i] == 'fa' or DIATONIC_SCALE[i] == 'do'
42
+ count += 1
43
+ else
44
+ count += 2
45
+ end
46
+ end
47
+
48
+ count = count + (12 * @step) if @step > 0
49
+
50
+ # counting notes alterations
51
+ alter = @note1[2..3]
52
+
53
+ alter.each_char do |c|
54
+ count += 1 if c == 'b'
55
+ count -= 1 if c == '#'
56
+ end
57
+
58
+ alter = @note2[2..3]
59
+
60
+ alter.each_char do |c|
61
+ count -= 1 if c == 'b'
62
+ count += 1 if c == '#'
63
+ end
64
+
65
+ count
66
+ end
67
+
68
+ # Returns the quality of the interval
69
+ def quality
70
+ s = ( @step > 0 and semitones - (12 * @step) ) || semitones
71
+ n = ( @step > 0 and number - (7 * @step) ) || number
72
+ QUALITIES[n][s]
73
+ end
74
+
75
+ # Returns the class interval in the short notation
76
+ def short
77
+ quality + number.to_s
78
+ end
79
+
80
+ private
81
+
82
+ # Common loop to search note 2
83
+ def until_find_note2(i)
84
+ # search note2
85
+ while DIATONIC_SCALE[i] != @note2[0..1]
86
+ i += 1
87
+ if i > DIATONIC_SCALE.length
88
+ i = 0; next
89
+ end
90
+ yield i
91
+ end
92
+ end
93
+
94
+ # Jumps to the next note if note 1 and note 2 are the same
95
+ def no_unison(count, i)
96
+ if @note1[0..1] == @note2[0..1]
97
+ count += 1; i += 1
98
+ end
99
+ [count, i]
100
+ end
101
+
102
+ # Returns index of note 1
103
+ def note1_index
104
+ DIATONIC_SCALE.index(@note1[0..1])
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,13 @@
1
+ # Scales module
2
+ module Scales
3
+ DIATONIC_SCALE = ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
4
+ QUALITIES = {
5
+ 2 => {0 => 'd', 1 => 'm', 2 => 'M', 3 => 'A', 4 => 'AA'},
6
+ 3 => {1 => 'dd', 2 => 'd', 3 => 'm', 4 => 'M', 5 => 'A', 6 => 'AA'},
7
+ 4 => {3 => 'dd', 4 => 'd', 5 => 'P', 6 => 'A', 7 => 'AA'},
8
+ 5 => {5 => 'dd', 6 => 'd', 7 => 'P', 8 => 'A', 9 => 'AA'},
9
+ 6 => {6 => 'dd', 7 => 'd', 8 => 'm', 9 => 'M', 10 => 'A', 11 => 'AA'},
10
+ 7 => {8 => 'dd', 9 => 'd', 10 => 'm', 11 => 'M', 12 => 'A', 13 => 'AA'},
11
+ 8 => {10 => 'dd', 11 => 'd', 12 => 'P', 13 => 'A', 14 => 'AA'}
12
+ }
13
+ end
@@ -0,0 +1,3 @@
1
+ module MusicUtils
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,26 @@
1
+ require 'music-utils/interval/interval'
2
+
3
+ # Music utils
4
+ module MusicUtils
5
+
6
+ # Returns the number of the interval
7
+ def MusicUtils.number(note1, note2, step = 0)
8
+ Interval.new(note1, note2, step).number
9
+ end
10
+
11
+ # Returns semitones of interval
12
+ def MusicUtils.semitones(note1, note2, step = 0)
13
+ Interval.new(note1, note2, step).semitones
14
+ end
15
+
16
+ # Returns the quality of interval
17
+ def MusicUtils.quality(note1, note2, step = 0)
18
+ Interval.new(note1, note2, step).quality
19
+ end
20
+
21
+ # Returns short notation
22
+ def MusicUtils.short(note1, note2, step = 0)
23
+ Interval.new(note1, note2, step).short
24
+ end
25
+
26
+ end
data/music-utils.gemspec CHANGED
@@ -1,22 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "music-utils/version"
1
4
 
2
5
  Gem::Specification.new do |s|
3
6
  # Basic Info
4
- s.name = 'music-utils'
5
- s.version = '0.5.2'
6
- s.summary = 'music-utils'
7
- s.description = 'Utils for music. At the moment only one class to classify intervals.'
7
+ s.name = "music-utils"
8
+ s.version = MusicUtils::VERSION
8
9
  s.platform = Gem::Platform::RUBY
9
- s.authors = ['Jorge Luis Pérez']
10
- s.email = ['jorgeluis700@gmail.com']
11
- s.homepage = 'http://github.com/jorgeluis700/music-utils'
12
- s.license = 'MIT'
13
-
14
- # Files and Paths
15
- s.files = `git ls-files`.split("\n")
16
- s.require_path = 'lib'
10
+ s.authors = ["Jorge Luis Pérez"]
11
+ s.email = ["jorgeluis700@gmail.com"]
12
+ s.homepage = "http://github.com/jorgeluis700/music-utils"
13
+ s.summary = %q{Utils for music}
14
+ s.description = %q{Utils for music. At the moment only to classify intervals.}
15
+ s.license = %q{MIT}
16
+
17
+ # Files
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
17
22
 
18
- # Dependencies
19
- s.add_development_dependency('rspec')
23
+ # Ruby Gems Version
20
24
  s.required_rubygems_version = ">= 1.3.6"
21
25
 
26
+ # Dependencies
27
+ s.add_development_dependency "rake", ">= 0.8"
28
+ s.add_development_dependency "bundler"
29
+ s.add_development_dependency "rspec"
30
+
22
31
  end
@@ -1,6 +1,7 @@
1
- require 'interval'
1
+ require 'music-utils/interval/interval'
2
2
 
3
- describe Interval do
3
+ describe MusicUtils::Interval do
4
+ include MusicUtils
4
5
 
5
6
  context "Number of intervals" do
6
7
  it "the number of simple interval do-mi should be a 3rd" do
@@ -22,22 +23,22 @@ describe Interval do
22
23
  context "Number of semitones of intervals" do
23
24
  it "simple interval do-mi should be 4 semitones" do
24
25
  i = Interval.new('do', 'mi', 0)
25
- i.semitone.should == 4
26
+ i.semitones.should == 4
26
27
  end
27
28
 
28
29
  it "simple interval dob-mi# should be 6 semitones" do
29
30
  i = Interval.new('dob', 'mi#', 0)
30
- i.semitone.should == 6
31
+ i.semitones.should == 6
31
32
  end
32
33
 
33
34
  it "simple interval do-do should be 12 semitones" do
34
35
  i = Interval.new('do', 'do', 0)
35
- i.semitone.should == 12
36
+ i.semitones.should == 12
36
37
  end
37
38
 
38
39
  it "compound interval do-mi should be 16 semitones" do
39
40
  i = Interval.new('do', 'mi', 1)
40
- i.semitone.should == 16
41
+ i.semitones.should == 16
41
42
  end
42
43
  end
43
44
 
@@ -0,0 +1,45 @@
1
+ require 'music-utils'
2
+
3
+ describe MusicUtils do
4
+
5
+ context "Intervals" do
6
+
7
+ context "By number" do
8
+ it "the number of simple interval do-mi should be a 3rd" do
9
+ MusicUtils.number('do', 'mi').should == 3
10
+ end
11
+ it "the number of do-mi compound interval should be a 10th" do
12
+ MusicUtils.number('do', 'mi', 1).should == 10
13
+ end
14
+ end
15
+
16
+ context "By semitones" do
17
+ it "simple interval do-mi should be 4 semitones" do
18
+ MusicUtils.semitones('do', 'mi').should == 4
19
+ end
20
+ it "compound interval do-mi should be 16 semitones" do
21
+ MusicUtils.semitones('do', 'mi', 1).should == 16
22
+ end
23
+ end
24
+
25
+ context "By quality" do
26
+ it "quality of interval do-mi should be M" do
27
+ MusicUtils.quality('do', 'mi').should == 'M'
28
+ end
29
+ it "quality of compound interval do-mi should be M" do
30
+ MusicUtils.quality('do', 'mi', 1).should == 'M'
31
+ end
32
+ end
33
+
34
+ context "By short notation" do
35
+ it "the short notation of do#-mi interval should be m3" do
36
+ MusicUtils.short('do#', 'mi').should == 'm3'
37
+ end
38
+ it "the short notation of do#-mi compound interval should be m10" do
39
+ MusicUtils.short('do#', 'mi', 1).should == 'm10'
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ 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: 0.5.2
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-04-29 00:00:00.000000000Z
12
+ date: 2011-05-06 00:00:00.000000000Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: &20979048 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0.8'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *20979048
25
+ - !ruby/object:Gem::Dependency
26
+ name: bundler
27
+ requirement: &20978820 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *20978820
14
36
  - !ruby/object:Gem::Dependency
15
37
  name: rspec
16
- requirement: &24028992 !ruby/object:Gem::Requirement
38
+ requirement: &20978544 !ruby/object:Gem::Requirement
17
39
  none: false
18
40
  requirements:
19
41
  - - ! '>='
@@ -21,8 +43,8 @@ dependencies:
21
43
  version: '0'
22
44
  type: :development
23
45
  prerelease: false
24
- version_requirements: *24028992
25
- description: Utils for music. At the moment only one class to classify intervals.
46
+ version_requirements: *20978544
47
+ description: Utils for music. At the moment only to classify intervals.
26
48
  email:
27
49
  - jorgeluis700@gmail.com
28
50
  executables: []
@@ -32,13 +54,16 @@ files:
32
54
  - .gitignore
33
55
  - CHANGELOG.md
34
56
  - Gemfile
35
- - Gemfile.lock
36
57
  - LICENSE
37
58
  - README.md
38
59
  - Rakefile
39
- - lib/interval.rb
60
+ - lib/music-utils.rb
61
+ - lib/music-utils/interval/interval.rb
62
+ - lib/music-utils/scales/scales.rb
63
+ - lib/music-utils/version.rb
40
64
  - music-utils.gemspec
41
- - spec/interval_spec.rb
65
+ - spec/interval/interval_spec.rb
66
+ - spec/music-utils_spec.rb
42
67
  homepage: http://github.com/jorgeluis700/music-utils
43
68
  licenses:
44
69
  - MIT
@@ -52,9 +77,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
77
  - - ! '>='
53
78
  - !ruby/object:Gem::Version
54
79
  version: '0'
55
- segments:
56
- - 0
57
- hash: 934369633
58
80
  required_rubygems_version: !ruby/object:Gem::Requirement
59
81
  none: false
60
82
  requirements:
@@ -66,5 +88,5 @@ rubyforge_project:
66
88
  rubygems_version: 1.7.2
67
89
  signing_key:
68
90
  specification_version: 3
69
- summary: music-utils
91
+ summary: Utils for music
70
92
  test_files: []
data/Gemfile.lock DELETED
@@ -1,21 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- diff-lcs (1.1.2)
5
- rake (0.8.7)
6
- rspec (2.5.0)
7
- rspec-core (~> 2.5.0)
8
- rspec-expectations (~> 2.5.0)
9
- rspec-mocks (~> 2.5.0)
10
- rspec-core (2.5.1)
11
- rspec-expectations (2.5.0)
12
- diff-lcs (~> 1.1.2)
13
- rspec-mocks (2.5.0)
14
-
15
- PLATFORMS
16
- ruby
17
- x86-mingw32
18
-
19
- DEPENDENCIES
20
- rake (~> 0.8)
21
- rspec (~> 2.5)
data/lib/interval.rb DELETED
@@ -1,117 +0,0 @@
1
- # Scales module
2
- module Scales
3
- DIATONIC_SCALE = ['do', 're', 'mi', 'fa', 'sol', 'la', 'si']
4
- QUALITIES = {
5
- 2 => {0 => 'd', 1 => 'm', 2 => 'M', 3 => 'A', 4 => 'AA'},
6
- 3 => {1 => 'dd', 2 => 'd', 3 => 'm', 4 => 'M', 5 => 'A', 6 => 'AA'},
7
- 4 => {3 => 'dd', 4 => 'd', 5 => 'P', 6 => 'A', 7 => 'AA'},
8
- 5 => {5 => 'dd', 6 => 'd', 7 => 'P', 8 => 'A', 9 => 'AA'},
9
- 6 => {6 => 'dd', 7 => 'd', 8 => 'm', 9 => 'M', 10 => 'A', 11 => 'AA'},
10
- 7 => {8 => 'dd', 9 => 'd', 10 => 'm', 11 => 'M', 12 => 'A', 13 => 'AA'},
11
- 8 => {10 => 'dd', 11 => 'd', 12 => 'P', 13 => 'A', 14 => 'AA'}
12
- }
13
- end
14
-
15
- # This class represents a music interval
16
- class Interval
17
- include Scales
18
-
19
- def initialize(note1, note2, step)
20
- @note1 = note1
21
- @note2 = note2
22
- @step = step
23
- end
24
-
25
- # It classifies the diatonic interval
26
- def number
27
- # initialize counter and index of scale
28
- i = note1_index
29
- count = 1
30
-
31
- count, i = no_unison(count, i)
32
-
33
- # Counting notes
34
- until_find_note2(i) { count += 1 }
35
-
36
- count = count + (8 * @step) - 1 if @step > 0
37
- count
38
- end
39
-
40
- # Returns the number of semitones
41
- def semitone
42
- # initialize counter and index of scale
43
- i = note1_index
44
- count = 0
45
-
46
- count, i = no_unison(count, i)
47
-
48
- # counting semi-tones
49
- until_find_note2(i) do |i|
50
- # from 'mi' to 'fa' and 'si' to 'do' there 1 semi-tone
51
- if DIATONIC_SCALE[i] == 'fa' or DIATONIC_SCALE[i] == 'do'
52
- count += 1
53
- else
54
- count += 2
55
- end
56
- end
57
-
58
- count = count + (12 * @step) if @step > 0
59
-
60
- # counting notes alterations
61
- alter = @note1[2..3]
62
-
63
- alter.each_char do |c|
64
- count += 1 if c == 'b'
65
- count -= 1 if c == '#'
66
- end
67
-
68
- alter = @note2[2..3]
69
-
70
- alter.each_char do |c|
71
- count -= 1 if c == 'b'
72
- count += 1 if c == '#'
73
- end
74
-
75
- count
76
- end
77
-
78
- # Returns the quality of the interval
79
- def quality
80
- s = ( @step > 0 and semitone - (12 * @step) ) || semitone
81
- n = ( @step > 0 and number - (7 * @step) ) || number
82
- QUALITIES[n][s]
83
- end
84
-
85
- # Returns the class interval in the short notation
86
- def short
87
- quality + number.to_s
88
- end
89
-
90
- private
91
-
92
- # Common loop to search note 2
93
- def until_find_note2(i)
94
- # search note2
95
- while DIATONIC_SCALE[i] != @note2[0..1]
96
- i += 1
97
- if i > DIATONIC_SCALE.length
98
- i = 0; next
99
- end
100
- yield i
101
- end
102
- end
103
-
104
- # Jumps to the next note if note 1 and note 2 are the same
105
- def no_unison(count, i)
106
- if @note1[0..1] == @note2[0..1]
107
- count += 1; i += 1
108
- end
109
- [count, i]
110
- end
111
-
112
- # Returns index of note 1
113
- def note1_index
114
- DIATONIC_SCALE.index(@note1[0..1])
115
- end
116
-
117
- end