Class: Musikov::MarkovBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/musikov/markov_builder.rb

Overview

This class is responsible for building the markov chain map from midi sequences. For every sequence, a “quarter” duration will be extracted and every note duration will be mapped in the possible values on the duration table. From a note and a specifc duration, MidiElements will be created representing a state on the markov chain.

Instance Method Summary collapse

Constructor Details

#initializeMarkovBuilder

Initialize the hashes used to build the markov chain of note elements.

  • The value_chain is a hash containing a list of note events by instrument.

  • The duration table is a dynamic generated hash (generated from the “quarter” duration value) that maps

a the duration of the notes to a string representation.



60
61
62
63
# File 'lib/musikov/markov_builder.rb', line 60

def initialize
  @value_chain = Hash.new
  @duration_table = Hash.new("unknow")
end

Instance Method Details

#add(sequence) ⇒ Object

Add a midi sequence to the model. From each sequence, different tracks (instruments) will be analyzed. Each sequence has a “tempo” that defines the “quarter” duration in ticks. From the “quarter” duration, creates a duration table containg (almost) every possible note duration. Creates markov chain elements by the value of the played note and the duration string mapped from the duration table.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/musikov/markov_builder.rb', line 72

def add(sequence)
  # Obtains a quarter duration for this sequence
  quarter_note_length = sequence.note_to_delta('quarter')
  
  # Create the duration table based on the sequence's "quarter" value
  create_duration_table(quarter_note_length)
  
  # For each instrument on the sequence...
  sequence.each { |track|
    # Program change of the current track
    program_change = nil

    # Create a list of midi elements for an instrument
    elements = []

    # Iterates the track event list...
    track.each { |event|
      
      # Consider only "NoteOn" events since they represent the start of a note event (avoid duplication with "NoteOff").
      if event.kind_of?(MIDI::NoteOnEvent) then
        # From its correspondent "NoteOff" element, extract the duration of the note event.
        duration = event.off.time_from_start - event.time_from_start + 1
        
        # Maps the duration in ticks to a correspondent string on the duration table.
        duration_representation = @duration_table[duration]
        
        # In the case that the note do not correspond to anything in the table,
        # we just truncate it to the closest value.
        if duration_representation.nil? or duration_representation == "unknow" then
          new_duration = 0
          # Infinity value simulation
          smallest_difference = 1.0/0
          @duration_table.each { |key, value|
            difference = (duration - key).abs
            if difference < smallest_difference then
              smallest_difference = difference
              new_duration = key
            end
          }
          duration_representation = @duration_table[new_duration]
        end

        # Create new markov chain state and put into the "elements" list
        elements << MidiElement.new(event.note_to_s, duration_representation)
      elsif event.kind_of?(MIDI::ProgramChange) then
        program_change = event.program
      end
    }
    
    if program_change.nil?
      program_change = 1
    end
    
    @value_chain[program_change] ||= elements unless elements.empty?
  }
end

#buildObject

Build the markov chain for each instrument on the input midi file(s)



130
131
132
133
134
135
136
137
# File 'lib/musikov/markov_builder.rb', line 130

def build
  model_by_instrument = {}
  @value_chain.each{ |key, value|
    model_by_instrument[key] = MarkovModel.new(value)
  }
  
  return model_by_instrument
end