Module: Cyclotone::Transition
- Included in:
- Stream
- Defined in:
- lib/cyclotone/transition.rb
Constant Summary collapse
- DEFAULT_DURATION =
2
Instance Method Summary collapse
- #anticipate(id, pattern) ⇒ Object
- #clutch(id, pattern) ⇒ Object
- #clutch_in(id, cycles, pattern) ⇒ Object
- #fade_in(cycles) ⇒ Object
- #fade_out(cycles) ⇒ Object
- #interpolate(id, pattern) ⇒ Object
- #interpolate_in(id, cycles, pattern) ⇒ Object
- #jump(id, pattern) ⇒ Object
- #jump_in(id, cycles, pattern) ⇒ Object
- #xfade(id, pattern) ⇒ Object
- #xfade_in(id, cycles, pattern) ⇒ Object
Instance Method Details
#anticipate(id, pattern) ⇒ Object
102 103 104 |
# File 'lib/cyclotone/transition.rb', line 102 def anticipate(id, pattern) jump_in(id, 8, pattern) end |
#clutch(id, pattern) ⇒ Object
30 31 32 |
# File 'lib/cyclotone/transition.rb', line 30 def clutch(id, pattern) clutch_in(id, DEFAULT_DURATION, pattern) end |
#clutch_in(id, cycles, pattern) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/cyclotone/transition.rb', line 34 def clutch_in(id, cycles, pattern) slot_id = normalize_slot_reference(id) current = pattern_for_transition(slot_id) replacement = Pattern.ensure_pattern(pattern) duration = Pattern.to_rational(cycles) return assign(slot_id, replacement) if duration <= 0 start_cycle = transition_start_cycle swapped = Pattern.new do |span| source_events = current.query_span(span).map { |event| [event, :current] } target_events = replacement.query_span(span).map { |event| [event, :replacement] } (source_events + target_events).filter_map do |event, source| time = event.onset || event.part.start desired_source = clutch_source(slot_id, time, event.value, start_cycle, duration) event if source == desired_source end.then { |events| Pattern.sort_events(events) } end assign_transition(slot_id, swapped, replacement: replacement, finish_cycle: start_cycle + duration) end |
#fade_in(cycles) ⇒ Object
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/cyclotone/transition.rb', line 106 def fade_in(cycles) start_cycle = transition_start_cycle duration = Pattern.to_rational(cycles) return self if duration <= 0 @slots.each_key do |slot_id| replacement = @slots.fetch(slot_id) assign_transition( slot_id, apply_gain_envelope(replacement, start_cycle: start_cycle, duration: duration, direction: :in), replacement: replacement, finish_cycle: start_cycle + duration ) end self end |
#fade_out(cycles) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/cyclotone/transition.rb', line 124 def fade_out(cycles) start_cycle = transition_start_cycle duration = Pattern.to_rational(cycles) return self if duration <= 0 @slots.each_key do |slot_id| assign_transition( slot_id, apply_gain_envelope(@slots.fetch(slot_id), start_cycle: start_cycle, duration: duration, direction: :out), replacement: Pattern.silence, finish_cycle: start_cycle + duration ) end self end |
#interpolate(id, pattern) ⇒ Object
56 57 58 |
# File 'lib/cyclotone/transition.rb', line 56 def interpolate(id, pattern) interpolate_in(id, 4, pattern) end |
#interpolate_in(id, cycles, pattern) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/cyclotone/transition.rb', line 60 def interpolate_in(id, cycles, pattern) slot_id = normalize_slot_reference(id) current = pattern_for_transition(slot_id) replacement = Pattern.ensure_pattern(pattern) duration = Pattern.to_rational(cycles) return assign(slot_id, replacement) if duration <= 0 start_cycle = transition_start_cycle morphed = Pattern.new do |span| source_events = current.query_span(span) target_events = replacement.query_span(span) transition_anchor_times(source_events, target_events).filter_map do |time| source_event = event_at_time(source_events, time) target_event = event_at_time(target_events, time) base_event = target_event || source_event next unless base_event progress = transition_progress(time, start_cycle, duration) base_event.with_value(interpolate_value(source_event&.value, target_event&.value, progress)) end.then { |events| Pattern.sort_events(events) } end assign_transition(slot_id, morphed, replacement: replacement, finish_cycle: start_cycle + duration) end |
#jump(id, pattern) ⇒ Object
86 87 88 |
# File 'lib/cyclotone/transition.rb', line 86 def jump(id, pattern) assign(normalize_slot_reference(id), pattern) end |
#jump_in(id, cycles, pattern) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/cyclotone/transition.rb', line 90 def jump_in(id, cycles, pattern) slot_id = normalize_slot_reference(id) current = pattern_for_transition(slot_id) replacement = Pattern.ensure_pattern(pattern) switch_cycle = transition_start_cycle + Pattern.to_rational(cycles) return assign(slot_id, replacement) if switch_cycle <= transition_start_cycle delayed = Pattern.new { |span| split_query(span, switch_cycle, current, replacement) } assign_transition(slot_id, delayed, replacement: replacement, finish_cycle: switch_cycle) end |
#xfade(id, pattern) ⇒ Object
7 8 9 |
# File 'lib/cyclotone/transition.rb', line 7 def xfade(id, pattern) xfade_in(id, DEFAULT_DURATION, pattern) end |
#xfade_in(id, cycles, pattern) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/cyclotone/transition.rb', line 11 def xfade_in(id, cycles, pattern) slot_id = normalize_slot_reference(id) current = pattern_for_transition(slot_id) replacement = Pattern.ensure_pattern(pattern) duration = Pattern.to_rational(cycles) return assign(slot_id, replacement) if duration <= 0 start_cycle = transition_start_cycle mixed = Pattern.stack( [ apply_gain_envelope(current, start_cycle: start_cycle, duration: duration, direction: :out), apply_gain_envelope(replacement, start_cycle: start_cycle, duration: duration, direction: :in) ] ) assign_transition(slot_id, mixed, replacement: replacement, finish_cycle: start_cycle + duration) end |