Module: Musa::Sequencer::BaseSequencer::TickBasedTiming Private

Defined in:
lib/musa-dsl/sequencer/base-sequencer-tick-based.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Tick-based timing implementation for BaseSequencer.

TickBasedTiming provides quantized time progression where time advances in discrete tick increments. Musical time is divided into bars, beats, and ticks, with position rounded to the nearest tick boundary. This provides a traditional sequencer timing model similar to DAWs and MIDI sequencers.

Tick-Based Time Model

Time is quantized to a grid determined by:

  • beats_per_bar: Time signature numerator (e.g., 4 for 4/4)
  • ticks_per_beat: Subdivisions per beat (resolution)
  • ticks_per_bar: Total ticks = beats_per_bar × ticks_per_beat
  • tick_duration: 1 / ticks_per_bar (Rational)

Position always aligns to tick boundaries. Non-aligned positions are rounded with a warning.

Time Progression

  • Forward only: Position cannot decrease (enforced)
  • Tick advancement: #tick increments by tick_duration
  • Fast-forward: #position= jumps to future position
  • Quantization: All positions rounded to tick grid

Fast-Forward Mechanism

When jumping forward via position=:

  1. Triggers on_fast_forward callbacks with true
  2. Ticks forward until reaching target position
  3. Triggers on_fast_forward callbacks with false
  4. Allows event handlers to skip/optimize during jumps

Musical Applications

  • Traditional MIDI sequencing with quantized timing
  • Grid-aligned rhythmic patterns
  • Time signature-based composition (4/4, 3/4, etc.)
  • Tick-precise event scheduling

Rational vs Float

The sequencer internally encodes time as Rational. It is preferable to use Rational values for positions and durations, as using Float may cause precision issues in the conversion.

Examples:

Creating tick-based sequencer (4/4, 96 ticks per beat)

sequencer = BaseSequencer.new(4, 96)  # 4 beats, 96 ticks/beat
sequencer.ticks_per_bar  # => 384r
sequencer.tick_duration  # => 1/384r
sequencer.position       # => 1r (start of bar 1)

Advancing time with tick

sequencer.tick  # Advance one tick (1/384 of a bar)
sequencer.position  # => 385/384r

Fast-forward to future position

sequencer.position = 2r  # Jump to bar 2
# Triggers on_fast_forward(true), ticks forward, on_fast_forward(false)

Quantization warning

sequencer.at(1.5001r) { puts "event" }
# WARN: rounding position 1.5001 to tick precision: 1.5

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#positionRational

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Current playback position in bars (Rational).

Always aligned to tick boundaries. Bar 1 starts at position 1r.

Returns:



79
80
81
# File 'lib/musa-dsl/sequencer/base-sequencer-tick-based.rb', line 79

def position
  @position
end

#tick_durationRational (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Duration of one tick in bars (1 / ticks_per_bar).

Returns:



89
90
91
# File 'lib/musa-dsl/sequencer/base-sequencer-tick-based.rb', line 89

def tick_duration
  @tick_duration
end

#ticks_per_barRational (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Total ticks per bar (beats_per_bar × ticks_per_beat).

Returns:



84
85
86
# File 'lib/musa-dsl/sequencer/base-sequencer-tick-based.rb', line 84

def ticks_per_bar
  @ticks_per_bar
end

Instance Method Details

#tickvoid

This method returns an undefined value.

Advances sequencer by one tick.

Increments position by tick_duration and executes all events scheduled at the new position. This is the primary time progression method for tick-based sequencers.

If ticks are held (during fast-forward), accumulates ticks in buffer without executing events until released.

Examples:

Normal tick progression

sequencer.position  # => 1r
sequencer.tick
sequencer.position  # => 385/384r (1 + 1/384)


108
109
110
111
112
113
114
# File 'lib/musa-dsl/sequencer/base-sequencer-tick-based.rb', line 108

def tick
  if @hold_public_ticks
    @hold_ticks += 1
  else
    _tick @position_mutex.synchronize { @position += @tick_duration }
  end
end