Class: Music::Interval
- Inherits:
-
Object
- Object
- Music::Interval
- Includes:
- Comparable
- Defined in:
- lib/music/interval.rb
Constant Summary collapse
- SIZES =
{ 1 => [0], 2 => [1, 2], 3 => [3, 4], 4 => [5], 5 => [7], 6 => [8, 9], 7 => [10, 11], 8 => [12], }
- OCTAVE =
8- QUALITIES =
[:minor, :major, :perfect, :augmented, :diminished]
Instance Attribute Summary collapse
-
#direction ⇒ 1, -1
readonly
Indicates if the interval is positive or negative.
- #number ⇒ Integer readonly
- #quality ⇒ Symbol readonly
Instance Method Summary collapse
-
#-@ ⇒ Music::Interval
Returns the same inteval with changed direction.
-
#<=>(other) ⇒ Object
Compares intervals by their size.
-
#consonance? ⇒ Boolean
Consonances are perfect and imperfect consonances together.
-
#diff ⇒ Integer
The actual diatonic difference.
-
#dissonance? ⇒ Boolean
Disonances are all intervals that are not consonances.
-
#imperfect_consonance? ⇒ Boolean
Imperfect consonants are minor/major thirds and sixths (and their compound intervals).
-
#initialize(number, quality) ⇒ Interval
constructor
A new instance of Interval.
-
#perfect_consonance? ⇒ Boolean
Perfect consonants are perfect unisons, fourths and fifths (and their compound intervals).
-
#size ⇒ Integer
Returns the number of semitones that interval covers.
Constructor Details
#initialize(number, quality) ⇒ Interval
Returns a new instance of Interval.
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/music/interval.rb', line 52 def initialize(number, quality) if not QUALITIES.include?(quality) raise ArgumentError, "invalid interval quality: #{quality}" elsif [1, 4, 5].include?((number.abs - 1) % 7 + 1) and [:major, :minor].include?(quality) raise ArgumentError, "interval #{number} doesn't have quality \"#{quality}\"" end @number, @quality = number.abs, quality @direction = number >= 0 ? +1 : -1 end |
Instance Attribute Details
#direction ⇒ 1, -1 (readonly)
Indicates if the interval is positive or negative.
41 42 43 |
# File 'lib/music/interval.rb', line 41 def direction @direction end |
#number ⇒ Integer (readonly)
31 32 33 |
# File 'lib/music/interval.rb', line 31 def number @number end |
#quality ⇒ Symbol (readonly)
35 36 37 |
# File 'lib/music/interval.rb', line 35 def quality @quality end |
Instance Method Details
#-@ ⇒ Music::Interval
Returns the same inteval with changed direction.
111 112 113 |
# File 'lib/music/interval.rb', line 111 def -@ Interval.new((-1 * direction) * number, quality) end |
#<=>(other) ⇒ Object
Compares intervals by their size.
150 151 152 |
# File 'lib/music/interval.rb', line 150 def <=>(other) self.size.abs <=> other.size.abs end |
#consonance? ⇒ Boolean
Consonances are perfect and imperfect consonances together.
91 92 93 |
# File 'lib/music/interval.rb', line 91 def consonance? perfect_consonance? or imperfect_consonance? end |
#diff ⇒ Integer
The actual diatonic difference. For example, seconds are numbered with ‘2`, but the actual diatonic difference between two notes that are in a second is `1`.
161 162 163 |
# File 'lib/music/interval.rb', line 161 def diff (number - 1) * direction end |
#dissonance? ⇒ Boolean
Disonances are all intervals that are not consonances.
102 103 104 |
# File 'lib/music/interval.rb', line 102 def dissonance? not consonance? end |
#imperfect_consonance? ⇒ Boolean
Imperfect consonants are minor/major thirds and sixths (and their compound intervals).
79 80 81 |
# File 'lib/music/interval.rb', line 79 def imperfect_consonance? [3, 6].include?(normalized_number) and [:minor, :major].include?(quality) end |
#perfect_consonance? ⇒ Boolean
Perfect consonants are perfect unisons, fourths and fifths (and their compound intervals).
69 70 71 |
# File 'lib/music/interval.rb', line 69 def perfect_consonance? [1, 4, 5].include?(normalized_number) and [:perfect].include?(quality) end |
#size ⇒ Integer
Returns the number of semitones that interval covers.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/music/interval.rb', line 120 def size result = 0 current_number = number while current_number >= OCTAVE result += SIZES[OCTAVE][0] current_number -= OCTAVE - 1 end sizes = SIZES.fetch(current_number) result += case quality when :diminished then sizes.first - 1 when :minor then sizes.first when :perfect then sizes[0] when :major then sizes.last when :augmented then sizes.last + 1 end result * direction end |