peas 0.2.1 → 0.3.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.
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