class Diamond::Sequence

The note event sequence from where the arpeggiator output is derived

Public Class Methods

new() click to toggle source
# File lib/diamond/sequence.rb, line 10
def initialize 
  @parameter = nil
  # realtime
  @changed = false
  @input_queue = []
  @queue = []
end

Public Instance Methods

add(*note_messages) click to toggle source

Add inputted note_messages @param [Array<MIDIMessage::NoteOn>, MIDIMessage::NoteOn, *MIDIMessage::NoteOn] note_messages @return [Boolean]

# File lib/diamond/sequence.rb, line 39
def add(*note_messages)
  messages = [note_messages].flatten.compact
  @input_queue.concat(messages)
  mark_changed
  true
end
at(pointer) click to toggle source

The bucket of messages for the given pointer @param [Fixnum] pointer @return [Array<MIDIMessage>]

# File lib/diamond/sequence.rb, line 21
def at(pointer)
  if changed? && (pointer % @parameter.rate == 0)
    update
  end
  enqueue_next(pointer)
  messages = @queue.shift || []
  messages
end
changed?() click to toggle source

Has the sequence changed since the last update? @return [Boolean]

# File lib/diamond/sequence.rb, line 32
def changed?
  @changed
end
mark_changed() click to toggle source

Mark the sequence as changed @return [Boolean]

# File lib/diamond/sequence.rb, line 78
def mark_changed
  @changed = true
end
pending_note_offs() click to toggle source

All NoteOff messages in the queue @return [Array<MIDIMessage::NoteOff>]

# File lib/diamond/sequence.rb, line 67
def pending_note_offs
  messages = @queue.map do |bucket|
    unless bucket.nil?
      bucket.select { |m| m.class == MIDIMessage::NoteOff }       
    end
  end
  messages.flatten.compact
end
remove(*note_messages) click to toggle source

Remove input note messages with the same note value @param [Array<MIDIMessage::NoteOn, MIDIMessage::NoteOff>, MIDIMessage::NoteOff, MIDIMessage::NoteOn, *MIDIMessage::NoteOff, *MIDIMessage::NoteOn] note_messages @return [Boolean]

# File lib/diamond/sequence.rb, line 49
def remove(*note_messages)
  messages = [note_messages].flatten
  deletion_queue = messages.map(&:note)
  @input_queue.delete_if { |message| deletion_queue.include?(message.note) }
  mark_changed
  true
end
remove_all() click to toggle source

Remove all input note messages @return [Boolean]

# File lib/diamond/sequence.rb, line 59
def remove_all
  @input_queue.clear
  mark_changed
  true
end

Protected Instance Methods

use_parameters(parameters) click to toggle source

Apply the given parameters object @param [SequenceParameters] parameters @return [SequenceParameters]

# File lib/diamond/sequence.rb, line 87
def use_parameters(parameters)
  @parameter = parameters
  update
end

Private Instance Methods

create_bucket(note_message) click to toggle source

Create a bucket/note event for the given note message @param [MIDIMessage::NoteOn] note_message @return [Array<NoteEvent>]

# File lib/diamond/sequence.rb, line 159
def create_bucket(note_message)
  event = MIDIInstrument::NoteEvent.new(note_message, @parameter.gate)
  [event]
end
enqueue(bucket) click to toggle source

Prepare the given event bucket for performance, moving note messages to the queue @param [Array<NoteEvent>] bucket @return [Array<NoteEvent>]

# File lib/diamond/sequence.rb, line 106
def enqueue(bucket)
  bucket.map do |event|
    @queue[0] ||= []
    @queue[0] << event.start 
    float_length = (event.length.to_f / 100) * @parameter.duration.to_f
    length = float_length.to_i
    @queue[length] ||= []
    @queue[length] << event.finish
    event
  end
end
enqueue_next(pointer) click to toggle source

Enqueue next bucket for the given pointer @param [Fixnum] pointer @return [Array<NoteEvent>]

# File lib/diamond/sequence.rb, line 97
def enqueue_next(pointer)
  bucket = @sequence[pointer]
  enqueue(bucket) unless bucket.nil?
  bucket
end
get_note_sequence() click to toggle source

The input queue as note messages @return [Array<MIDIMessage::NoteOn>]

# File lib/diamond/sequence.rb, line 166
def get_note_sequence
  notes = @parameter.computed_pattern.map do |degree|
    @input_queue.map do |message| 
      note = message.note + degree + @parameter.transpose
      MIDIMessage::NoteOn.new(message.channel, note, message.velocity)
    end
  end
  notes.flatten.compact
end
initialize_sequence(length) click to toggle source

(Re)initialize the sequence with the given length @param [Fixnum] length @return [Array]

# File lib/diamond/sequence.rb, line 131
def initialize_sequence(length)
  sequence_length_in_ticks = length * @parameter.duration
  @sequence = Array.new(sequence_length_in_ticks, [])
end
populate_bucket(index, note_message) click to toggle source

Populate the bucket for index with the given note message @param [Fixnum] index @param [MIDIMessage::NoteOn] note_message @return [Array<NoteEvent>]

# File lib/diamond/sequence.rb, line 152
def populate_bucket(index, note_message)
  @sequence[index] = create_bucket(note_message)
end
populate_sequence(notes) click to toggle source

Populate the sequence with the given notes @param [Array<MIDIMessage::NoteOn>] notes @return [Array<Array<NoteEvent>>]

# File lib/diamond/sequence.rb, line 139
def populate_sequence(notes)
  @parameter.pattern_offset.times { notes.push(notes.shift) }
  notes.each_with_index do |note, i| 
    index = i * @parameter.duration
    populate_bucket(index, note) unless @sequence[index].nil?
  end
  @sequence
end
update() click to toggle source

Commit changes to the sequence @return [ArpeggiatorSequence]

# File lib/diamond/sequence.rb, line 120
def update
  notes = get_note_sequence
  initialize_sequence(notes.length)
  populate_sequence(notes) unless notes.empty?
  @changed = false
  @sequence
end