Class: Music::Interval

Inherits:
Object
  • Object
show all
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

Instance Method Summary collapse

Constructor Details

#initialize(number, quality) ⇒ Interval

Returns a new instance of Interval.

Examples:

Interval.new(3, :major)   # a major third
Interval.new(5, :perfect) # a perfect fifth

Parameters:

  • number (Integer)
  • quality (Symbol)

    See the QUALITIES constant for the list of possible values.



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

#direction1, -1 (readonly)

Indicates if the interval is positive or negative.

Returns:

  • (1, -1)


41
42
43
# File 'lib/music/interval.rb', line 41

def direction
  @direction
end

#numberInteger (readonly)

Returns:

  • (Integer)


31
32
33
# File 'lib/music/interval.rb', line 31

def number
  @number
end

#qualitySymbol (readonly)

Returns:

  • (Symbol)


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.

Returns:



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.

Examples:

Interval.new(3, :major) >  Interval.new(4, :perfect)    #=> true
Interval.new(3, :major) == Interval.new(4, :diminished) #=> true

Parameters:



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.

Returns:

  • (Boolean)

See Also:



91
92
93
# File 'lib/music/interval.rb', line 91

def consonance?
  perfect_consonance? or imperfect_consonance?
end

#diffInteger

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`.

Returns:

  • (Integer)


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.

Returns:

  • (Boolean)

See Also:



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).

Returns:

  • (Boolean)


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).

Returns:

  • (Boolean)


69
70
71
# File 'lib/music/interval.rb', line 69

def perfect_consonance?
  [1, 4, 5].include?(normalized_number) and [:perfect].include?(quality)
end

#sizeInteger

Returns the number of semitones that interval covers.

Returns:

  • (Integer)


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