class MTK::Events::Timeline

A collection of timed events. The core data structure used to interface with input and output.

Maps sorted floating point times to lists of events.

Enumerable as [time,event_list] pairs.

Public Class Methods

from_a(enumerable) click to toggle source
# File lib/mtk/events/timeline.rb, line 18
def from_a(enumerable)
  new.merge enumerable
end
Also aliased as: from_h
from_h(enumerable)
Alias for: from_a
new() click to toggle source
# File lib/mtk/events/timeline.rb, line 13
def initialize()
  @timeline = {}
end
quantize_time(time, interval) click to toggle source
# File lib/mtk/events/timeline.rb, line 227
def self.quantize_time time, interval
  upper = interval * (time.to_f/interval).ceil
  lower = upper - interval
  (time - lower) < (upper - time) ? lower : upper
end

Public Instance Methods

==(other) click to toggle source
# File lib/mtk/events/timeline.rb, line 40
def == other
  other = other.to_h unless other.is_a? Hash
  @timeline == other
end
[](time) click to toggle source
# File lib/mtk/events/timeline.rb, line 45
def [](time)
  @timeline[time.to_f]
end
[]=(time, events) click to toggle source
# File lib/mtk/events/timeline.rb, line 49
def []=(time, events)
  time = time.to_f unless time.is_a? Numeric
  case events
    when nil?
      @timeline.delete time.to_f
    when Array
      @timeline[time.to_f] = events
    else
      @timeline[time.to_f] = [events]
  end
end
add(time, event) click to toggle source
# File lib/mtk/events/timeline.rb, line 61
def add(time, event)
  events = @timeline[time.to_f]
  if events
    if event.is_a? Array
      events.concat event
    else
      events << event
    end
  else
     self[time] = event
  end
end
clear() click to toggle source
# File lib/mtk/events/timeline.rb, line 31
def clear
  @timeline.clear
  self
end
clone() click to toggle source
# File lib/mtk/events/timeline.rb, line 140
def clone
  self.class.from_h(to_h)
end
compact!() click to toggle source
# File lib/mtk/events/timeline.rb, line 144
def compact!
  @timeline.delete_if {|t,events| events.empty? }
end
delete(time) click to toggle source
# File lib/mtk/events/timeline.rb, line 74
def delete(time)
  @timeline.delete(time.to_f)
end
each() { |time, timeline| ... } click to toggle source
# File lib/mtk/events/timeline.rb, line 100
def each
  # this is similar to @timeline.each, but by iterating over #times, we yield the events in chronological order
  times.each do |time|
    yield time, @timeline[time]
  end
end
empty?() click to toggle source
# File lib/mtk/events/timeline.rb, line 92
def empty?
  @timeline.empty?
end
enumerable_map(&block)

the original Enumerable#map implementation, which returns an Array

Alias for: map
events() click to toggle source
# File lib/mtk/events/timeline.rb, line 96
def events
  times.map{|t| @timeline[t] }.flatten
end
flatten() click to toggle source
# File lib/mtk/events/timeline.rb, line 148
def flatten
  flattened = Timeline.new
  self.each do |time,events|
    events.each do |event|
      if event.is_a? Timeline
        event.flatten.each do |subtime,subevent|
          flattened.add(time+subtime, subevent)
        end
      else
        flattened.add(time,event)
      end
    end
  end
  flattened
end
has_time?(time) click to toggle source
# File lib/mtk/events/timeline.rb, line 78
def has_time? time
  @timeline.has_key? time.to_f
end
inspect() click to toggle source
# File lib/mtk/events/timeline.rb, line 223
def inspect
  @timeline.inspect
end
length() click to toggle source
# File lib/mtk/events/timeline.rb, line 86
def length
  last_time = times.last
  events = @timeline[last_time]
  last_time + events.map{|event| event.duration }.max
end
map(&block) click to toggle source

Constructs a new Timeline by mapping each [time,event_list] pair @see map!

# File lib/mtk/events/timeline.rb, line 112
def map &block
  self.class.from_a enumerable_map(&block)
end
Also aliased as: enumerable_map
map!(&block) click to toggle source

Perform map in place @see map

# File lib/mtk/events/timeline.rb, line 118
def map! &block
  mapped = enumerable_map(&block)
  clear
  merge mapped
end
map_events() { |event| ... } click to toggle source

Map every individual event, without regard for the time at which is occurs

# File lib/mtk/events/timeline.rb, line 125
def map_events
  mapped_timeline = Timeline.new
  self.each do |time,events|
    mapped_timeline[time] = events.map{|event| yield event }
  end
  mapped_timeline
end
map_events!() { |event| ... } click to toggle source

Map every individual event in place, without regard for the time at which is occurs

# File lib/mtk/events/timeline.rb, line 134
def map_events!
  each do |time,events|
    self[time] = events.map{|event| yield event }
  end
end
merge(enumerable) click to toggle source
# File lib/mtk/events/timeline.rb, line 24
def merge enumerable
  enumerable.each do |time,events|
    add(time,events)
  end
  self
end
quantize(interval) click to toggle source

@return a new Timeline where all times have been quantized to multiples of the given interval @example timeline.quantize(0.5) # quantize to eight notes (assuming the beat is a quarter note) @see quantize!

# File lib/mtk/events/timeline.rb, line 167
def quantize interval
  map{|time,events| [self.class.quantize_time(time,interval), events] }
end
quantize!(interval) click to toggle source
# File lib/mtk/events/timeline.rb, line 171
def quantize! interval
  map!{|time,events| [self.class.quantize_time(time,interval), events] }
end
shift(time_delta) click to toggle source

shifts all times by the given amount @see shift! @see shift_to

# File lib/mtk/events/timeline.rb, line 178
def shift time_delta
  map{|time,events| [time+time_delta, events] }
end
shift!(time_delta) click to toggle source

shifts all times in place by the given amount @see shift @see shift_to!

# File lib/mtk/events/timeline.rb, line 185
def shift! time_delta
  map!{|time,events| [time+time_delta, events] }
end
shift_to(absolute_time) click to toggle source

shifts the times so that the start of the timeline is at the given time @see shift_to! @see shift

# File lib/mtk/events/timeline.rb, line 192
def shift_to absolute_time
  start = times.first
  if start
    shift absolute_time - start
  else
    clone
  end
end
shift_to!(absolute_time) click to toggle source

shifts the times in place so that the start of the timeline is at the given time @see shift_to @see shift!

# File lib/mtk/events/timeline.rb, line 204
def shift_to! absolute_time
  start = times.first
  if start
    shift! absolute_time - start
  end
  self
end
times() click to toggle source
# File lib/mtk/events/timeline.rb, line 82
def times
  @timeline.keys.sort
end
to_h() click to toggle source
# File lib/mtk/events/timeline.rb, line 36
def to_h
  @timeline
end
to_s() click to toggle source
# File lib/mtk/events/timeline.rb, line 212
def to_s
  times = self.times
  last = times.last
  if last
    width = sprintf("%d",last).length + 3 # nicely align the '=>' against the longest number
    times.map{|t| sprintf("%#{width}.2f",t)+" => #{@timeline[t].join ', '}" }.join "\n"
  else
    ''
  end
end