Class: MultimediaParadise::Chord

Inherits:
Object
  • Object
show all
Defined in:
lib/multimedia_paradise/multimedia/chord.rb

Overview

MultimediaParadise::Chord

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(notes) ⇒ Chord

#

initialize

#


16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 16

def initialize(notes)
  if notes.size < 2
    raise ArgumentError, 'Chords must have at least two notes'
  end
  @notes = Set.new(notes) { |note|
    if note.is_a?(Note)
      note
    else
      Note.new(note)
    end
  }
end

Instance Attribute Details

#notesObject (readonly)

Returns the value of attribute notes.



11
12
13
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 11

def notes
  @notes
end

Class Method Details

.parse_chord_string(chord_string, assumed_octave = nil) ⇒ Object

#

MultimediaParadise::Chord.parse_chord_string

#


151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 151

def self.parse_chord_string(
    chord_string,
    assumed_octave = nil
  )
  if note_string_match = chord_string.match(/^([A-Ga-g])([#b]?)([^\d]*)(\d*)$/)
    full_string, note, accidental, interval, octave = note_string_match.to_a
    if note.empty? && assumed_octave.nil?
      raise ArgumentError, 'No octave found and no octave assumed.'
    end
    # ===================================================================== #
    # Build a new Note here, which will also be returned.
    # full_string is irrelevant though.
    # ===================================================================== #
    Note.new(
      note + accidental + octave, assumed_octave
    ).chord(interval) { full_string }
  end
end

Instance Method Details

#==(other_chord) ⇒ Object

#

==

#


46
47
48
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 46

def ==(other_chord)
  self.eql?(other_chord)
end

#describeObject

#

describe

Describe the various minor and major chords.

#


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 64

def describe
  note_array = @notes.to_a.sort
  distances = (1...note_array.size).map { |i|
    note_array[0].distance_to(note_array[i])
  }
  quality = case distances
  when [4, 7]
    :major
  when [3, 7]
    :minor
  when [3, 6]
    :diminished
  when [4, 8]
    :augmented
  when [4, 7, 11]
    :major_7
  when [3, 7, 10]
    :minor_7
  when [3, 6, 9]
    :diminished_7
  when [3, 6, 10]
    :half_diminished_7
  when [4, 8, 10]
    :augmented_7
  end
  [note_array.first.letter, quality]
end

#eql?(other_chord) ⇒ Boolean

#

eql?

#

Returns:

  • (Boolean)


32
33
34
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 32

def eql?(other_chord)
  @notes == other_chord.notes
end

#first_inversionObject

#

first_inversion

Calls inversion(1)

#


126
127
128
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 126

def first_inversion
  self.inversion(1)
end

#hashObject

#

hash

#


39
40
41
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 39

def hash
  @notes.hash
end

#inversion(amount) ⇒ Object

#

inversion

Give the n-th inversion of the chord which simply adjusts the lowest N notes up by one octave.

#


107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 107

def inversion(amount)
  if amount < 1
    raise ArgumentError,
      'Inversion amount must be greater than or equal to 1'
  end
  if amount >= @notes.size
    raise ArgumentError,
      'Not enough notes in chord for a proper inversion.'
  end
  note_array = @notes.to_a.sort
  notes = (0 ... amount).map { note_array.shift.adjust_by_semitones(12) }
  Chord.new(notes + note_array)
end

#note_stringsObject

#

note_strings

Spec and implement.

#


55
56
57
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 55

def note_strings
  Set.new(@notes.map(&:note_string))
end

#second_inversionObject

#

second_inversion

Calls inversion(2)

#


135
136
137
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 135

def second_inversion
  self.inversion(2)
end

#third_inversionObject

#

third_inversion

Calls inversion(3)

#


144
145
146
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 144

def third_inversion
  self.inversion(3)
end

#to_sObject

#

to_s

#


95
96
97
# File 'lib/multimedia_paradise/multimedia/chord.rb', line 95

def to_s
  @notes.to_a.sort.map(&:to_s).join(' / ')
end