Class: Deftones::Event::Sequence

Inherits:
Object
  • Object
show all
Includes:
CallbackBehavior, Enumerable
Defined in:
lib/deftones/event/sequence.rb

Instance Attribute Summary

Attributes included from CallbackBehavior

#humanize, #mute, #playback_rate, #probability, #state

Instance Method Summary collapse

Methods included from CallbackBehavior

#callback_interval, #callback_permitted?, #callback_time, #humanized_time, #initialize_callback_behavior, #mark_started, #mark_stopped, #mute?, #playbackRate=

Constructor Details

#initialize(notes:, subdivision: "4n", loop: true, transport: Deftones.transport, probability: 1.0, humanize: false, mute: false, playback_rate: 1.0, seed: nil, rng: nil, &callback) ⇒ Sequence

Returns a new instance of Sequence.

Raises:

  • (ArgumentError)


9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/deftones/event/sequence.rb', line 9

def initialize(notes:, subdivision: "4n", loop: true, transport: Deftones.transport,
               probability: 1.0, humanize: false, mute: false, playback_rate: 1.0,
               seed: nil, rng: nil, &callback)
  raise ArgumentError, "callback is required" unless callback

  @notes = Array(notes)
  raise ArgumentError, "Sequence notes must not be empty" if @notes.empty?

  @subdivision = subdivision
  @loop = loop
  @transport = transport
  @callback = callback
  @event_id = nil
  @current_step = 0
  initialize_callback_behavior(
    probability: probability,
    humanize: humanize,
    mute: mute,
    playback_rate: playback_rate,
    seed: seed,
    rng: rng
  )
end

Instance Method Details

#[](index) ⇒ Object



60
61
62
# File 'lib/deftones/event/sequence.rb', line 60

def [](index)
  @notes[index]
end

#[]=(index, value) ⇒ Object



64
65
66
# File 'lib/deftones/event/sequence.rb', line 64

def []=(index, value)
  @notes[index] = value
end

#cancelObject



49
50
51
52
53
54
# File 'lib/deftones/event/sequence.rb', line 49

def cancel
  @transport.cancel(event_id: @event_id) if @event_id
  @event_id = nil
  mark_stopped
  self
end

#disposeObject



56
57
58
# File 'lib/deftones/event/sequence.rb', line 56

def dispose
  cancel
end

#each(&block) ⇒ Object



68
69
70
71
72
# File 'lib/deftones/event/sequence.rb', line 68

def each(&block)
  return enum_for(:each) unless block

  @notes.each(&block)
end

#process_note(time, note) ⇒ Object (private)



93
94
95
96
97
98
# File 'lib/deftones/event/sequence.rb', line 93

def process_note(time, note)
  payload = note.is_a?(Hash) ? note : { note: note }
  return if payload.fetch(:probability, 1.0).to_f < @rng.rand

  @callback.call(time, payload.fetch(:note, payload[:value]), payload)
end

#process_step(scheduled_time) ⇒ Object (private)



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/deftones/event/sequence.rb', line 76

def process_step(scheduled_time)
  note = @notes[@current_step % @notes.length]
  return if note.nil?
  return unless callback_permitted?

  if note.is_a?(Array)
    sub_duration = callback_interval(@subdivision) / note.length.to_f
    note.each_with_index do |nested_note, index|
      next if nested_note.nil?

      process_note(humanized_time(scheduled_time + (sub_duration * index)), nested_note)
    end
  else
    process_note(humanized_time(scheduled_time), note)
  end
end

#start(time = 0) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/deftones/event/sequence.rb', line 33

def start(time = 0)
  @current_step = 0
  scaled_subdivision = callback_interval(@subdivision)
  duration = @loop ? nil : (scaled_subdivision * (@notes.length - 1))
  @event_id = @transport.schedule_repeat(scaled_subdivision, start_time: time, duration: duration) do |scheduled_time|
    process_step(scheduled_time)
    @current_step += 1
  end
  mark_started
  self
end

#stop(_time = nil) ⇒ Object



45
46
47
# File 'lib/deftones/event/sequence.rb', line 45

def stop(_time = nil)
  cancel
end