peas 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
File without changes
data/lib/peas/interval.rb CHANGED
@@ -2,26 +2,22 @@ require 'named_value_class'
2
2
  require 'peas/pitch'
3
3
 
4
4
  module Peas
5
+
6
+ # see: http://en.wikipedia.org/wiki/Interval_(music)
7
+ #
5
8
  module Interval
6
- # see: http://en.wikipedia.org/wiki/Interval_(music)
7
-
8
- NamedValueClass Base:Integer do
9
- def -(rhs)
10
- if [Pitch,PitchClass].include?(rhs.class)
11
- raise Peas::InvalidOperation, '(Interval - Pitch) has no meaning'
12
- else
13
- super
14
- end
15
- end
9
+ NamedValueClass Base:Integer, constrain:0..24 do
10
+ minus_a Pitch, raises:SyntaxError
11
+ minus_a PitchClass, raises:SyntaxError
16
12
  end
17
13
 
18
14
  class Semitone < Base; end
19
- 128.times do |x|
15
+ 25.times do |x|
20
16
  Semitone "S#{x}" => x
21
17
  end
22
18
 
23
19
  class Wholetone < Base; end
24
- 64.times do |x|
20
+ 13.times do |x|
25
21
  Wholetone "W#{x}" => x * 2
26
22
  end
27
23
 
data/lib/peas/pitch.rb CHANGED
@@ -1,119 +1,31 @@
1
1
  require 'forwardable'
2
2
  require 'peas/pitch_class'
3
- require 'peas/interval'
4
3
 
5
4
  module Peas
6
- NamedValueClass Pitch:Fixnum do
7
- extend Forwardable
8
- def_delegators :pitch_class, :is_sharp?, :is_flat?, :is_natural?
9
-
10
- alias _minus :-
11
-
12
- def -(rhs)
13
- if rhs.class == Pitch
14
- if self >= rhs
15
- Interval::Diatonic[super(rhs)] || Interval::Semitone[super(rhs)]
16
- else
17
- rhs - self
18
- end
19
- elsif rhs.class == PitchClass
20
- self.pitch_class - rhs
21
- elsif rhs.is_a? Interval::Base
22
- if is_sharp?
23
- Pitch.sharps(self._minus(rhs))
24
- else
25
- Pitch.flats(self._minus(rhs))
26
- end
27
- end
5
+ NamedValueClass Pitch:Fixnum, constrain:0..127 do
6
+ minus_a 'Interval::Base' do |lhs,minus,rhs|
7
+ result = minus.call(rhs)
8
+ is_sharp? ? Pitch.sharps[result] : Pitch.flats[result]
28
9
  end
29
10
 
11
+ all_operators_with_a :Pitch, raise:SyntaxError
12
+
30
13
  def as_flat
31
- self.class.flats(self)
14
+ self.class.naturals[self] || self.class.flats[self]
32
15
  end
33
16
 
34
17
  def as_sharp
35
- self.class.sharps(self)
36
- end
37
-
38
- def self.flats(value)
39
- {
40
- 0 => C_1 , 32 => Ab1 , 64 => E4 , 96 => C7 ,
41
- 1 => Db_1 , 33 => A1 , 65 => F4 , 97 => Db7 ,
42
- 2 => D_1 , 34 => Bb1 , 66 => Gb4 , 98 => D7 ,
43
- 3 => Eb_1 , 35 => B1 , 67 => G4 , 99 => Eb7 ,
44
- 4 => E_1 , 36 => C2 , 68 => Ab4 , 100 => E7 ,
45
- 5 => F_1 , 37 => Db2 , 69 => A4 , 101 => F7 ,
46
- 6 => Gb_1 , 38 => D2 , 70 => Bb4 , 102 => Gb7 ,
47
- 7 => G_1 , 39 => Eb2 , 71 => B4 , 103 => G7 ,
48
- 8 => Ab_1 , 40 => E2 , 72 => C5 , 104 => Ab7 ,
49
- 9 => A_1 , 41 => F2 , 73 => Db5 , 105 => A7 ,
50
- 10 => Bb_1 , 42 => Gb2 , 74 => D5 , 106 => Bb7 ,
51
- 11 => B_1 , 43 => G2 , 75 => Eb5 , 107 => B7 ,
52
- 12 => C0 , 44 => Ab2 , 76 => E5 , 108 => C8 ,
53
- 13 => Db0 , 45 => A2 , 77 => F5 , 109 => Db8 ,
54
- 14 => D0 , 46 => Bb2 , 78 => Gb5 , 110 => D8 ,
55
- 15 => Eb0 , 47 => B2 , 79 => G5 , 111 => Eb8 ,
56
- 16 => E0 , 48 => C3 , 80 => Ab5 , 112 => E8 ,
57
- 17 => F0 , 49 => Db3 , 81 => A5 , 113 => F8 ,
58
- 18 => Gb0 , 50 => D3 , 82 => Bb5 , 114 => Gb8 ,
59
- 19 => G0 , 51 => Eb3 , 83 => B5 , 115 => G8 ,
60
- 20 => Ab0 , 52 => E3 , 84 => C6 , 116 => Ab8 ,
61
- 21 => A0 , 53 => F3 , 85 => Db6 , 117 => A8 ,
62
- 22 => Bb0 , 54 => Gb3 , 86 => D6 , 118 => Bb8 ,
63
- 23 => B0 , 55 => G3 , 87 => Eb6 , 119 => B8 ,
64
- 24 => C1 , 56 => Ab3 , 88 => E6 , 120 => C9 ,
65
- 25 => Db1 , 57 => A3 , 89 => F6 , 121 => Db9 ,
66
- 26 => D1 , 58 => Bb3 , 90 => Gb6 , 122 => D9 ,
67
- 27 => Eb1 , 59 => B3 , 91 => G6 , 123 => Eb9 ,
68
- 28 => E1 , 60 => C4 , 92 => Ab6 , 124 => E9 ,
69
- 29 => F1 , 61 => Db4 , 93 => A6 , 125 => F9 ,
70
- 30 => Gb1 , 62 => D4 , 94 => Bb6 , 126 => Gb9 ,
71
- 31 => G1 , 63 => Eb4 , 95 => B6 , 127 => G9
72
- }[value]
73
- end
74
-
75
- def self.sharps(value)
76
- {
77
- 0 => C_1 , 32 => Gs1 , 64 => E4 , 96 => C7 ,
78
- 1 => Cs_1 , 33 => A1 , 65 => F4 , 97 => Cs7 ,
79
- 2 => D_1 , 34 => As1 , 66 => Fs4 , 98 => D7 ,
80
- 3 => Ds_1 , 35 => B1 , 67 => G4 , 99 => Ds7 ,
81
- 4 => E_1 , 36 => C2 , 68 => Gs4 , 100 => E7 ,
82
- 5 => F_1 , 37 => Cs2 , 69 => A4 , 101 => F7 ,
83
- 6 => Fs_1 , 38 => D2 , 70 => As4 , 102 => Fs7 ,
84
- 7 => G_1 , 39 => Ds2 , 71 => B4 , 103 => G7 ,
85
- 8 => Gs_1 , 40 => E2 , 72 => C5 , 104 => Gs7 ,
86
- 9 => A_1 , 41 => F2 , 73 => Cs5 , 105 => A7 ,
87
- 10 => As_1 , 42 => Fs2 , 74 => D5 , 106 => As7 ,
88
- 11 => B_1 , 43 => G2 , 75 => Ds5 , 107 => B7 ,
89
- 12 => C0 , 44 => Gs2 , 76 => E5 , 108 => C8 ,
90
- 13 => Cs0 , 45 => A2 , 77 => F5 , 109 => Cs8 ,
91
- 14 => D0 , 46 => As2 , 78 => Fs5 , 110 => D8 ,
92
- 15 => Ds0 , 47 => B2 , 79 => G5 , 111 => Ds8 ,
93
- 16 => E0 , 48 => C3 , 80 => Gs5 , 112 => E8 ,
94
- 17 => F0 , 49 => Cs3 , 81 => A5 , 113 => F8 ,
95
- 18 => Fs0 , 50 => D3 , 82 => As5 , 114 => Fs8 ,
96
- 19 => G0 , 51 => Ds3 , 83 => B5 , 115 => G8 ,
97
- 20 => Gs0 , 52 => E3 , 84 => C6 , 116 => Gs8 ,
98
- 21 => A0 , 53 => F3 , 85 => Cs6 , 117 => A8 ,
99
- 22 => As0 , 54 => Fs3 , 86 => D6 , 118 => As8 ,
100
- 23 => B0 , 55 => G3 , 87 => Ds6 , 119 => B8 ,
101
- 24 => C1 , 56 => Gs3 , 88 => E6 , 120 => C9 ,
102
- 25 => Cs1 , 57 => A3 , 89 => F6 , 121 => Cs9 ,
103
- 26 => D1 , 58 => As3 , 90 => Fs6 , 122 => D9 ,
104
- 27 => Ds1 , 59 => B3 , 91 => G6 , 123 => Ds9 ,
105
- 28 => E1 , 60 => C4 , 92 => Gs6 , 124 => E9 ,
106
- 29 => F1 , 61 => Cs4 , 93 => A6 , 125 => F9 ,
107
- 30 => Fs1 , 62 => D4 , 94 => As6 , 126 => Fs9 ,
108
- 31 => G1 , 63 => Ds4 , 95 => B6 , 127 => G9
109
- }[value]
18
+ self.class.naturals[self] || self.class.sharps[self]
110
19
  end
111
20
  end
21
+
112
22
  PitchClass::NamedValues::Collection.each do |pclass|
113
- Pitch "#{pclass}_1" => pclass, pitch_class:pclass, octave:-1
23
+ Pitch "#{pclass}_1" => pclass.value, pitch_class:pclass, octave:-1,
24
+ sharp:pclass.is_sharp?, flat:pclass.is_flat?, natural:pclass.is_natural?
114
25
  0.upto(9) do |octave|
115
26
  name = pclass.to_s + octave.to_s
116
- Pitch name => (((octave+1)*12)+pclass), pitch_class:pclass, octave:octave
27
+ Pitch name => (((octave+1)*12)+pclass), pitch_class:pclass, octave:octave,
28
+ sharp:pclass.is_sharp?, flat:pclass.is_flat?, natural:pclass.is_natural?
117
29
  end
118
30
  end
119
31
 
@@ -122,4 +34,3 @@ module Peas
122
34
  include PitchClass::NamedValues
123
35
  end
124
36
  end
125
-
@@ -1,96 +1,43 @@
1
1
  require 'named_value_class'
2
2
 
3
3
  module Peas
4
- class InvalidOperation < RuntimeError; end
5
-
6
- NamedValueClass PitchClass:Fixnum do
7
- alias _minus :-
8
-
9
- def -(rhs)
10
- if rhs.class == PitchClass
11
- if self >= rhs
12
- # TODO: stop the insanity
13
- Interval::Diatonic[
14
- Interval::Diatonic[self._minus(rhs)].interval_class] ||
15
- Interval::Semitone[
16
- Interval::Semitone[self._minus(rhs)].interval_class]
17
- else
18
- Interval::Diatonic[rhs - self]
19
- end
20
- elsif rhs.class == Pitch
21
- self - rhs.pitch_class
22
- elsif rhs.is_a? Interval::Base
23
- result = self._minus(rhs) % 12
24
- if is_sharp?
25
- PitchClass.sharps(result)
26
- else
27
- PitchClass.flats(result)
28
- end
29
- end
30
- end
31
-
32
- def is_sharp?
33
- %w|Bs Cs Ds Es Fs Gs As|.include? @name
34
- end
35
-
36
- def is_flat?
37
- %w|Bb Cb Db Eb Fb Gb Ab|.include? @name
4
+ NamedValueClass PitchClass:Fixnum, constrain:0..11 do
5
+ minus_a 'Interval::Base' do |lhs,minus,rhs|
6
+ result = minus.call(rhs) % 12
7
+ is_sharp? ? PitchClass.sharps[result] : PitchClass.flats[result]
38
8
  end
39
9
 
40
- def is_natural?
41
- %w|B C D E F G A|.include? @name
42
- end
43
-
44
- def self.flats(value)
45
- {
46
- 0 => C, 6 => Gb,
47
- 1 => Db, 7 => G,
48
- 2 => D, 8 => Ab,
49
- 3 => Eb, 9 => A,
50
- 4 => E, 10 => Bb,
51
- 5 => F, 11 => B
52
- }[value]
53
- end
54
-
55
- def self.sharps(value)
56
- {
57
- 0 => C, 6 => Fs,
58
- 1 => Cs, 7 => G,
59
- 2 => D, 8 => Gs,
60
- 3 => Ds, 9 => A,
61
- 4 => E, 10 => As,
62
- 5 => F, 11 => B
63
- }[value]
64
- end
10
+ all_operators_with_a :PitchClass, raise:SyntaxError
11
+ all_operators_with_a :Pitch, raise:SyntaxError
65
12
 
66
13
  def as_flat
67
- self.class.flats(self)
14
+ self.class.naturals[self] || self.class.flats[self]
68
15
  end
69
16
 
70
17
  def as_sharp
71
- self.class.sharps(self)
18
+ self.class.naturals[self] || self.class.sharps[self]
72
19
  end
73
20
  end
74
21
 
75
- PitchClass Bs: 0 # B sharp is just Bs
76
- PitchClass C: 0
77
- PitchClass Cs: 1
78
- PitchClass Db: 1
79
- PitchClass D: 2
80
- PitchClass Ds: 3
81
- PitchClass Eb: 3
82
- PitchClass E: 4
83
- PitchClass Es: 5
84
- PitchClass Fb: 4
85
- PitchClass F: 5
86
- PitchClass Fs: 6
87
- PitchClass Gb: 6
88
- PitchClass G: 7
89
- PitchClass Gs: 8
90
- PitchClass Ab: 8
91
- PitchClass A: 9
92
- PitchClass As: 10
93
- PitchClass Bb: 10
94
- PitchClass B: 11
95
- PitchClass Cb: 11
22
+ PitchClass Bs: 0, sharp:true
23
+ PitchClass C: 0, natural:true
24
+ PitchClass Cs: 1, sharp:true
25
+ PitchClass Db: 1, flat:true
26
+ PitchClass D: 2, natural:true
27
+ PitchClass Ds: 3, sharp:true
28
+ PitchClass Eb: 3, flat:true
29
+ PitchClass E: 4, natural:true
30
+ PitchClass Fb: 4, flat:true
31
+ PitchClass Es: 5, sharp:true
32
+ PitchClass F: 5, natural:true
33
+ PitchClass Fs: 6, sharp:true
34
+ PitchClass Gb: 6, flat:true
35
+ PitchClass G: 7, natural:true
36
+ PitchClass Gs: 8, sharp:true
37
+ PitchClass Ab: 8, flat:true
38
+ PitchClass A: 9, natural:true
39
+ PitchClass As: 10, sharp:true
40
+ PitchClass Bb: 10, flat:true
41
+ PitchClass B: 11, natural:true
42
+ PitchClass Cb: 11, flat:true
96
43
  end
data/lib/peas/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Peas
2
2
  NAME = 'peas'
3
- VERSION = '0.2.1'
3
+ VERSION = '0.3.0'
4
4
  SUMMARY = 'Do math with music pitches, intervals, scales, chords and progressions in Ruby.'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,33 +9,31 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-18 00:00:00.000000000Z
12
+ date: 2011-12-20 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: named_value_class
16
- requirement: &2153017400 !ruby/object:Gem::Requirement
16
+ requirement: &2151835560 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0.6'
21
+ version: '0.7'
22
22
  - - ! '>='
23
23
  - !ruby/object:Gem::Version
24
- version: 0.6.0
24
+ version: 0.7.0
25
25
  type: :runtime
26
26
  prerelease: false
27
- version_requirements: *2153017400
28
- description: ! 'Peas defines constants from music theory and allows one to perform
29
- math with them. Currently supports pitches (as MIDI values), pitch classes, and
30
- intervals using semitones, wholetones, chromatic, latin or diatonic
31
-
32
- abbreviations.'
27
+ version_requirements: *2151835560
28
+ description: Peas defines constants from music theory and allows one to perform math
29
+ with them. Currently supports pitches (as MIDI values), pitch classes, and intervals
30
+ using semitones, wholetones, chromatic, latin or diatonic abbreviations.
33
31
  email: mgarriss@gmail.com
34
32
  executables: []
35
33
  extensions: []
36
34
  extra_rdoc_files: []
37
35
  files:
38
- - lib/peas/integer_helper.rb
36
+ - lib/peas/interger_helper.rb
39
37
  - lib/peas/interval.rb
40
38
  - lib/peas/pitch.rb
41
39
  - lib/peas/pitch_class.rb