Module: Musa::All

Overview

Convenience module that includes all Musa DSL components in a single namespace.

This module provides a convenient way to include all Musa DSL functionality into your code with a single include Musa::All statement, rather than including each component individually.

Included Components

Core Functionality

  • Logger - Logging utilities
  • Clock - Timing and clock management
  • Transport - Transport control (play, stop, tempo)
  • Sequencer - Event sequencing and scheduling
  • Series - Series operations and transformations
  • Datasets - Musical dataset management
  • REPL - Read-Eval-Print Loop for live coding

Notation and Language

Musical Theory

  • Scales - Scale definitions and operations
  • Chords - Chord construction and manipulation

Data Structures

  • Matrix - Matrix operations for musical data

Generative Algorithms

  • Darwin - Evolutionary/genetic algorithms
  • Markov - Markov chain generation
  • Rules - Rule-based generative system
  • Variatio - Combinatorial variation generator

Input/Output

Usage

Examples:

Include all Musa DSL components

require 'musa-dsl'
include Musa::All

# Now you have access to all Musa DSL methods and classes
score = S.with(pitches: [60, 62, 64, 65])
sequencer = Sequencer.new

Selective inclusion (alternative)

# Instead of Musa::All, you can include only what you need:
include Musa::Series
include Musa::Sequencer

Instance Method Summary collapse

Instance Method Details

#A(*series) ⇒ FromArrayOfSeries Originally defined in module Series::Constructors

Creates array-mode serie from array of series.

Combines multiple series into array-structured values. Returns array of values from respective series. Stops when first serie exhausts.

Examples:

Array of series

a = A(S(1, 2, 3), S(10, 20, 30))
a.i.next_value  # => [1, 10]
a.i.next_value  # => [2, 20]

#AC(*series) ⇒ FromArrayOfSeries Originally defined in module Series::Constructors

Creates array-mode combined serie from array of series.

Like A but cycles all series. When a serie exhausts, it restarts from the beginning, continuing until all series complete their cycles.

Examples:

Combined cycling all series

ac = AC(S(1, 2), S(10, 20, 30))
ac.max_size(6).i.to_a  # => [[1, 10], [2, 20], [1, 30],
                        #     [2, 10], [1, 20], [2, 30]]

#E(*value_args, **key_args) {|value_args, last_value, caller, key_args| ... } ⇒ FromEvalBlockWithParameters Originally defined in module Series::Constructors

Creates serie from evaluation block.

Calls block repeatedly with parameters and last_value. Block returns next value or nil to stop. Enables stateful generators and algorithms.

Block Parameters

  • value_args: Initial positional parameters
  • last_value: Previous return value (nil on first call)
  • caller: Serie instance (access to parameters attribute)
  • key_args: Initial keyword parameters

Examples:

Counter

counter = E(1) { |v, last_value:| last_value + 1 unless last_value == 5 }
counter.i.to_a  # => [1, 2, 3, 4, 5]

Fibonacci

fib = E { |last_value:, caller:|
  a, b = caller.parameters
  caller.parameters = [b, a + b]
  a
}
fib.parameters = [0, 1]
fib.i.to_a(limit: 10)  # => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Yields:

  • block called for each value

Yield Parameters:

  • value_args (Array)

    current positional parameters

  • last_value (Object, nil)

    previous return value

  • caller (FromEvalBlockWithParameters)

    serie instance

  • key_args (Hash)

    current keyword parameters

Yield Returns:

  • (Object, nil)

    next value or nil to stop

#FIBOFibonacci Originally defined in module Series::Constructors

Creates Fibonacci sequence serie.

Generates classic Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, ... Infinite serie.

Examples:

Fibonacci numbers

fib = FIBO()
fib.infinite?  # => true
inst = fib.i
10.times.map { inst.next_value }
# => [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

Rhythmic proportions

durations = FIBO().i.map { |n| Rational(n, 16) }

#FOR(from: nil, to: nil, step: nil) ⇒ ForLoop Originally defined in module Series::Constructors

Creates for-loop style numeric sequence.

Generates sequence from from to to (inclusive) with step increment. Automatically adjusts step sign based on from/to relationship.

Examples:

Ascending sequence

s = FOR(from: 0, to: 10, step: 2)
s.i.to_a  # => [0, 2, 4, 6, 8, 10]

Descending sequence

s = FOR(from: 10, to: 0, step: 2)
s.i.to_a  # => [10, 8, 6, 4, 2, 0]

Infinite sequence

s = FOR(from: 0, step: 1)  # to: nil
s.infinite?  # => true

#H(**series_hash) ⇒ FromHashOfSeries Originally defined in module Series::Constructors

Creates hash-mode serie from hash of series.

Combines multiple series into hash-structured values. Returns hash with same keys, values from respective series. Stops when first serie exhausts.

Examples:

Hash of series

h = H(pitch: S(60, 64, 67), velocity: S(96, 80, 64))
h.i.next_value  # => {pitch: 60, velocity: 96}
h.i.next_value  # => {pitch: 64, velocity: 80}

#HARMO(error: nil, extended: nil) ⇒ HarmonicNotes Originally defined in module Series::Constructors

Creates harmonic notes serie from fundamental.

Generates MIDI note numbers for harmonic series based on listened fundamental. Approximates harmonics to nearest semitone within error tolerance.

Parameters

  • error: Maximum cents deviation to accept harmonic (default: 0.5)
  • extended: Include extended harmonics beyond audible range

Examples:

Harmonic series

# Listen to fundamental, serie returns harmonic notes
harmonics = HARMO(error: 0.5)
harmonics.i  # Waits for fundamental input

Extended harmonics

harm = HARMO(error: 0.3, extended: true)

#HC(**series_hash) ⇒ FromHashOfSeries Originally defined in module Series::Constructors

Creates hash-mode combined serie from hash of series.

Like H but cycles all series. When a serie exhausts, it restarts from the beginning, continuing until all series complete their cycles.

Examples:

Combined cycling all series

hc = HC(a: S(1, 2), b: S(10, 20, 30))
hc.max_size(6).i.to_a  # => [{a:1, b:10}, {a:2, b:20}, {a:1, b:30},
                        #     {a:2, b:10}, {a:1, b:20}, {a:2, b:30}]

#MERGE(*series) ⇒ Sequence Originally defined in module Series::Constructors

Merges multiple series sequentially.

Plays series in sequence: first serie until exhausted, then second, etc. Restarts each serie (except first) before playing.

Examples:

Merge sequences

merged = MERGE(S(1, 2, 3), S(10, 20, 30))
merged.i.to_a  # => [1, 2, 3, 10, 20, 30]

Melodic phrases

phrase1 = S(60, 64, 67)
phrase2 = S(72, 69, 65)
melody = MERGE(phrase1, phrase2)

#NILNilSerie Originally defined in module Series::Constructors

Creates serie that always returns nil.

Returns nil on every next_value call. Useful for padding or as placeholder in composite structures.

Examples:

Nil serie

s = NIL().i
s.next_value  # => nil
s.next_value  # => nil

#PROXY(serie = nil) ⇒ ProxySerie Originally defined in module Series::Constructors

Creates a proxy serie with optional initial source.

Proxy series enable late binding - creating a serie placeholder that will be resolved later. Useful for:

Use Cases

  • Forward references: Reference series before definition
  • Circular structures: Self-referential or mutually referential series
  • Dependency injection: Define structure, inject source later
  • Dynamic routing: Change source serie at runtime

Method Delegation

Proxy delegates all methods to underlying source via method_missing, making it transparent proxy for most operations.

State Resolution

Proxy starts in :undefined state, becomes :prototype/:instance when source is set and resolved.

Examples:

Forward reference

proxy = PROXY()
proxy.undefined?  # => true

# Define later
proxy.proxy_source = S(1, 2, 3)
proxy.prototype?  # => true

Circular structure

loop_serie = PROXY()
sequence = S(1, 2, 3).after(loop_serie)
loop_serie.proxy_source = sequence
# Creates infinite loop: 1, 2, 3, 1, 2, 3, ...

With initial source

proxy = PROXY(S(1, 2, 3))

#QUANTIZE(time_value_serie, reference: nil, step: nil, value_attribute: nil, stops: nil, predictive: nil, left_open: nil, right_open: nil) ⇒ RawQuantizer, PredictiveQuantizer Originally defined in module Series::Constructors

Quantizes time-value serie to discrete steps.

#QUEUE(*series) ⇒ QueueSerie Originally defined in module Series::Constructors

Creates queue serie from initial series.

Queue allows adding series dynamically during playback, creating flexible sequential playback with runtime modification.

Features

  • Dynamic addition: Add series with << during playback
  • Sequential playback: Plays series in queue order
  • Method delegation: Delegates methods to current serie
  • Clear: Can clear queue and reset

Use Cases

  • Interactive sequencing with user input
  • Dynamic phrase assembly
  • Playlist-style serie management
  • Reactive composition systems
  • Live coding pattern queuing

Examples:

Basic queue

queue = QUEUE(S(1, 2, 3)).i
queue.next_value  # => 1
queue << S(4, 5, 6).i  # Add dynamically
queue.to_a  # => [2, 3, 4, 5, 6]

Dynamic playlist

queue = QUEUE().i
queue << melody1.i
queue << melody2.i
# Plays melody1 then melody2

#RND(*_values, values: nil, from: nil, to: nil, step: nil, random: nil) ⇒ RandomValuesFromArray, RandomNumbersFromRange Originally defined in module Series::Constructors

Creates random value serie from array or range.

Two modes:

  • Array mode: Random values from provided array
  • Range mode: Random numbers from range (from, to, step)

Infinite serie - never exhausts.

Examples:

Random from array

dice = RND(1, 2, 3, 4, 5, 6)
dice.i.next_value  # => random 1-6

Random from range

rand = RND(from: 0, to: 100, step: 10)
rand.i.next_value  # => random 0, 10, 20, ..., 100

With seed

rnd = RND(1, 2, 3, random: 42)  # Reproducible

Raises:

  • (ArgumentError)

    if using both positional and named values

  • (ArgumentError)

    if mixing array and range parameters

#RND1(*_values, values: nil, from: nil, to: nil, step: nil, random: nil) ⇒ RandomValueFromArray, RandomNumberFromRange Originally defined in module Series::Constructors

Creates single random value serie from array or range.

Like RND but returns only one random value then exhausts. Two modes: array mode and range mode.

Examples:

Single random value

rnd = RND1(1, 2, 3, 4, 5)
rnd.i.next_value  # => random 1-5
rnd.i.next_value  # => nil (exhausted)

Random seed selection

seed = RND1(10, 20, 30, random: 42)

Raises:

  • (ArgumentError)

    if using both positional and named values

  • (ArgumentError)

    if mixing array and range parameters

#S(*values) ⇒ FromArray Originally defined in module Series::Constructors

Creates serie from array of values.

Most common constructor. Values can include ranges which will be expanded automatically via ExplodeRanges extension.

Examples:

Basic array

notes = S(60, 64, 67, 72)
notes.i.to_a  # => [60, 64, 67, 72]

With ranges

scale = S(60..67)
scale.i.to_a  # => [60, 61, 62, 63, 64, 65, 66, 67]

#SIN(start_value: nil, steps: nil, amplitude: nil, center: nil) ⇒ SinFunction Originally defined in module Series::Constructors

Creates sine wave function serie.

Generates values following sine curve. Useful for smooth oscillations, LFO-style modulation, and periodic variations.

Wave Parameters

  • start_value: Initial value (default: center)
  • steps: Period in steps (nil for continuous)
  • amplitude: Wave amplitude (default: 1.0)
  • center: Center/offset value (default: 0.0)

Wave equation: center + amplitude * sin(progress)

Examples:

Basic sine wave

wave = SIN(steps: 8, amplitude: 10, center: 50)
wave.i.to_a  # => oscillates around 50 ± 10

LFO modulation

lfo = SIN(steps: 16, amplitude: 0.5, center: 0.5)
# Use for amplitude modulation

#TIMED_UNION(*array_of_timed_series, **hash_of_timed_series) ⇒ TimedUnionOfArrayOfTimedSeries, TimedUnionOfHashOfTimedSeries Originally defined in module Series::Constructors

Merges multiple timed series by synchronizing events at each time point.

TIMED_UNION combines series with :time attributes, emitting events at each unique time where at least one source has a value. Sources without values at a given time emit nil. Operates in two distinct modes based on input format.

Timed Series Format

Each event is a hash with :time and :value keys, extended with AbsTimed:

{ time: 0r, value: 60, duration: 1r }.extend(Musa::Datasets::AbsTimed)

Additional attributes (:duration, :velocity, etc.) are preserved and synchronized alongside values.

Operating Modes

Array Mode: TIMED_UNION(s1, s2, s3)

  • Anonymous positional sources
  • Output: { time: t, value: [val1, val2, val3] }
  • Use for: Ordered tracks without specific names

Hash Mode: TIMED_UNION(melody: s1, bass: s2)

  • Named sources with keys
  • Output: { time: t, value: { melody: val1, bass: val2 } }
  • Use for: Identified voices/tracks for routing

Value Types and Combination

Direct values (integers, strings, etc.):

s1 = S({ time: 0, value: 60 })
s2 = S({ time: 0, value: 64 })
TIMED_UNION(s1, s2)  # => { time: 0, value: [60, 64] }

Hash values (polyphonic events):

s1 = S({ time: 0, value: { a: 1, b: 2 } })
s2 = S({ time: 0, value: { c: 10 } })
TIMED_UNION(s1, s2)  # => { time: 0, value: { a: 1, b: 2, c: 10 } }

Array values (multi-element events):

s1 = S({ time: 0, value: [1, 2] })
s2 = S({ time: 0, value: [10, 20] })
TIMED_UNION(s1, s2)  # => { time: 0, value: [1, 2, 10, 20] }

Mixed Hash + Direct (advanced):

s1 = S({ time: 0, value: { a: 1, b: 2 } })
s2 = S({ time: 0, value: 100 })
TIMED_UNION(s1, s2)  # => { time: 0, value: { a: 1, b: 2, 0 => 100 } }

Synchronization Behavior

Events are emitted at each unique time point across all sources:

s1 = S({ time: 0r, value: 1 }, { time: 2r, value: 3 })
s2 = S({ time: 1r, value: 10 })
TIMED_UNION(s1, s2).i.to_a
# => [{ time: 0r, value: [1, nil] },
#     { time: 1r, value: [nil, 10] },
#     { time: 2r, value: [3, nil] }]

Extra Attributes

Non-standard attributes (beyond :time, :value) are synchronized:

s1 = S({ time: 0, value: 1, velocity: 80 })
s2 = S({ time: 0, value: 10, duration: 1r })
TIMED_UNION(s1, s2)
# => { time: 0, value: [1, 10], velocity: [80, nil], duration: [nil, 1r] }

Examples:

Array mode with direct values

s1 = S({ time: 0r, value: 1 }, { time: 1r, value: 2 })
s2 = S({ time: 0r, value: 10 }, { time: 2r, value: 20 })

union = TIMED_UNION(s1, s2).i
union.to_a
# => [{ time: 0r, value: [1, 10] },
#     { time: 1r, value: [2, nil] },
#     { time: 2r, value: [nil, 20] }]

Hash mode with named sources

melody = S({ time: 0r, value: 60 }, { time: 1r, value: 64 })
bass = S({ time: 0r, value: 36 }, { time: 2r, value: 40 })

union = TIMED_UNION(melody: melody, bass: bass).i
union.to_a
# => [{ time: 0r, value: { melody: 60, bass: 36 } },
#     { time: 1r, value: { melody: 64, bass: nil } },
#     { time: 2r, value: { melody: nil, bass: 40 } }]

Hash values with polyphonic events

s1 = S({ time: 0r, value: { a: 1, b: 2 } })
s2 = S({ time: 0r, value: { c: 10, d: 20 } })

union = TIMED_UNION(s1, s2).i
union.next_value  # => { time: 0r, value: { a: 1, b: 2, c: 10, d: 20 } }

Extra attributes synchronization

s1 = S({ time: 0r, value: 1, velocity: 80, duration: 1r })
s2 = S({ time: 0r, value: 10, velocity: 90 })

union = TIMED_UNION(s1, s2).i
union.next_value
# => { time: 0r,
#      value: [1, 10],
#      velocity: [80, 90],
#      duration: [1r, nil] }

Key conflict detection

s1 = S({ time: 0r, value: { a: 1, b: 2 } })
s2 = S({ time: 0r, value: { a: 10 } })  # 'a' already used!

union = TIMED_UNION(s1, s2).i
union.next_value  # RuntimeError: Value: key a already used

Raises:

  • (ArgumentError)

    if mixing array and hash modes

  • (RuntimeError)

    if hash values have duplicate keys across sources

  • (RuntimeError)

    if mixing incompatible value types (Hash with Array)

See Also:

  • Splits compound values into individual timed events
  • Removes events with all-nil values
  • Instance method for union

#UNDEFINEDUndefinedSerie Originally defined in module Series::Constructors

Creates undefined serie.

Returns serie in undefined state. Useful as placeholder that will be resolved later (e.g., in PROXY).

Examples:

Undefined placeholder

proxy = PROXY()  # Uses UNDEFINED internally
proxy.undefined?  # => true