Class: HeadMusic::Style::Guidelines::DirectionChanges

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

Overview

A melodic line should change direction often enough. Configurable via the maximum_notes_per_direction: option; subclasses may set a MAXIMUM_NOTES_PER_DIRECTION default and their own MESSAGE.

Constant Summary collapse

MESSAGE =
"Change melodic direction regularly."

Instance Method Summary collapse

Constructor Details

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

Instance Method Details

#marksObject



10
11
12
13
14
15
# File 'lib/head_music/style/guidelines/direction_changes.rb', line 10

def marks
  return unless overage.positive?

  penalty_exponent = overage**0.5
  HeadMusic::Style::Mark.for_all(notes, fitness: HeadMusic::PENALTY_FACTOR**penalty_exponent)
end

#maximum_notes_per_directionObject (private)



25
26
27
# File 'lib/head_music/style/guidelines/direction_changes.rb', line 25

def maximum_notes_per_direction
  options.fetch(:maximum_notes_per_direction) { self.class::MAXIMUM_NOTES_PER_DIRECTION }
end

#melodic_intervals_changing_directionObject (private)



33
34
35
36
37
# File 'lib/head_music/style/guidelines/direction_changes.rb', line 33

def melodic_intervals_changing_direction
  melodic_intervals.each_cons(2).reject do |interval_pair|
    interval_pair[0].direction == interval_pair[1].direction
  end
end

#notes_per_directionObject (private)



29
30
31
# File 'lib/head_music/style/guidelines/direction_changes.rb', line 29

def notes_per_direction
  notes.length.to_f / (melodic_intervals_changing_direction.length + 1)
end

#overageObject (private)



19
20
21
22
23
# File 'lib/head_music/style/guidelines/direction_changes.rb', line 19

def overage
  return 0 if notes.length < 2

  [notes_per_direction - maximum_notes_per_direction, 0].max
end