Class: Musicality::CounterpointGenerator
- Inherits:
-
Object
- Object
- Musicality::CounterpointGenerator
- Defined in:
- lib/musicality/composition/generation/counterpoint_generator.rb
Instance Attribute Summary collapse
-
#palette ⇒ Object
readonly
Returns the value of attribute palette.
-
#rhythm ⇒ Object
readonly
Returns the value of attribute rhythm.
-
#solution_classes ⇒ Object
readonly
Returns the value of attribute solution_classes.
-
#solutions ⇒ Object
readonly
Returns the value of attribute solutions.
-
#total_dur ⇒ Object
readonly
Returns the value of attribute total_dur.
Class Method Summary collapse
Instance Method Summary collapse
- #best_solution(ideal_overlap, sample_rate) ⇒ Object
- #best_solutions(n, ideal_overlap, sample_rate) ⇒ Object
- #evaluate(solution, ideal_overlap, sample_rate) ⇒ Object
-
#initialize(rhythm, palette, max_fact = 5) ⇒ CounterpointGenerator
constructor
A new instance of CounterpointGenerator.
Constructor Details
#initialize(rhythm, palette, max_fact = 5) ⇒ CounterpointGenerator
Returns a new instance of CounterpointGenerator.
5 6 7 8 9 10 11 12 13 14 15 16 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 5 def initialize rhythm, palette, max_fact = 5 raise ArgumentError, "max_fact must be >= palette size" if max_fact < palette.size @rhythm = rhythm @palette = palette @total_dur = rhythm.map {|dur| dur.abs }.inject(0,:+) @solution_classes = self.class.solution_classes(@total_dur, @palette) @solution_classes.keep_if do |sc| sc.map {|k,v| k*v}.inject(0,:+) == @total_dur end @solutions = figure_solutions(max_fact) end |
Instance Attribute Details
#palette ⇒ Object (readonly)
Returns the value of attribute palette.
4 5 6 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 4 def palette @palette end |
#rhythm ⇒ Object (readonly)
Returns the value of attribute rhythm.
4 5 6 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 4 def rhythm @rhythm end |
#solution_classes ⇒ Object (readonly)
Returns the value of attribute solution_classes.
4 5 6 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 4 def solution_classes @solution_classes end |
#solutions ⇒ Object (readonly)
Returns the value of attribute solutions.
4 5 6 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 4 def solutions @solutions end |
#total_dur ⇒ Object (readonly)
Returns the value of attribute total_dur.
4 5 6 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 4 def total_dur @total_dur end |
Class Method Details
.rhythm_to_computer(rhythm) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 18 def self.rhythm_to_computer rhythm rhythm_accum = AddingSequence.new(rhythm).take(rhythm.size+1).to_a x = rhythm_accum[0,rhythm.size] y = rhythm_accum[1,rhythm.size].map {|y_| Change::Immediate.new(y_) } value_changes = Hash[ [x,y].transpose ] ValueComputer.new(0, value_changes) end |
Instance Method Details
#best_solution(ideal_overlap, sample_rate) ⇒ Object
42 43 44 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 42 def best_solution ideal_overlap, sample_rate @solutions.min_by {|sol| evaluate(sol,ideal_overlap,sample_rate) } end |
#best_solutions(n, ideal_overlap, sample_rate) ⇒ Object
46 47 48 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 46 def best_solutions n, ideal_overlap, sample_rate @solutions.sort_by {|sol| evaluate(sol,ideal_overlap,sample_rate) }.take(n) end |
#evaluate(solution, ideal_overlap, sample_rate) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/musicality/composition/generation/counterpoint_generator.rb', line 26 def evaluate solution, ideal_overlap, sample_rate if solution.inject(0,:+) != @total_dur raise ArgumentError, "Given solution #{solution} does not have same duration as rhythm" end rhythm_comp = self.class.rhythm_to_computer(@rhythm) solution_comp = self.class.rhythm_to_computer(solution) r = rhythm_comp.sample(0...@total_dur, sample_rate) s = solution_comp.sample(0...@total_dur, sample_rate) n_same = [r,s].transpose.count {|pair| pair[0] == pair[1] } n_samples = (@total_dur*sample_rate).to_i percent_overlap = (n_same/n_samples).to_f return (ideal_overlap - percent_overlap).abs end |