Class: HeadMusic::Style::Guidelines::SingableRange

Inherits:
Annotation
  • Object
show all
Defined in:
lib/head_music/style/guidelines/singable_range.rb

Overview

A voice shouldn’t expend the range of a 10th. Configurable via the maximum_range: option (a diatonic interval number).

Constant Summary collapse

MAXIMUM_RANGE =
10
VOWEL_SOUND_ORDINALS =

Ordinals whose spoken form begins with a vowel sound take “an” instead of “a” (an eighth, an eleventh, an eighteenth). Others in the singable range take “a”.

[8, 11, 18].freeze

Instance Method Summary collapse

Constructor Details

This class inherits a constructor from HeadMusic::Style::Annotation

Instance Method Details

#extremesObject (private)



36
37
38
# File 'lib/head_music/style/guidelines/singable_range.rb', line 36

def extremes
  (highest_notes + lowest_notes).sort
end

#indefinite_articleObject (private)



28
29
30
# File 'lib/head_music/style/guidelines/singable_range.rb', line 28

def indefinite_article
  VOWEL_SOUND_ORDINALS.include?(maximum_range) ? "an" : "a"
end

#marksObject



14
15
16
# File 'lib/head_music/style/guidelines/singable_range.rb', line 14

def marks
  HeadMusic::Style::Mark.for_each(extremes, fitness: HeadMusic::PENALTY_FACTOR**overage) if overage.positive?
end

#maximum_rangeObject (private)



24
25
26
# File 'lib/head_music/style/guidelines/singable_range.rb', line 24

def maximum_range
  options.fetch(:maximum_range) { self.class::MAXIMUM_RANGE }
end

#messageObject



18
19
20
# File 'lib/head_music/style/guidelines/singable_range.rb', line 18

def message
  "Limit melodic range to #{indefinite_article} #{maximum_range.ordinalize}."
end

#overageObject (private)



32
33
34
# File 'lib/head_music/style/guidelines/singable_range.rb', line 32

def overage
  notes.any? ? [range.number - maximum_range, 0].max : 0
end