Module: Musa::Series
- Includes:
- Constructors
- Included in:
- All
- Defined in:
- lib/musa-dsl/series/base-series.rb,
lib/musa-dsl/series/series-composer.rb,
lib/musa-dsl/series/main-serie-operations.rb
Overview
Core Serie infrastructure providing prototype/instance system and base implementation.
This module defines the fundamental architecture for all Series in Musa DSL:
Core Concepts
Prototype/Instance Pattern
Series use a prototype/instance pattern to enable reusable series definitions:
- Prototype: Template/blueprint for series (cannot be consumed)
- Instance: Cloned copy ready for consumption (can call next_value)
- Undefined: Series with unresolved dependencies
Serie States
Every serie exists in one of three states:
- :prototype - Template state, cannot consume, can create instances
- :instance - Active state, can consume values, has independent state
- :undefined - Unresolved state, cannot use until dependencies resolve
Why Prototype/Instance?
Enables reusable series definitions without re-evaluating constructors:
# Define once (prototype)
melody = S(60, 64, 67, 72)
# Use multiple times (instances)
voice1 = melody.instance # Independent playback
voice2 = melody.instance # Separate playback
Integration
Series integrate with:
- Sequencer: Play series over time via play() method
- Generative: Use with generative grammars
- MIDI: Generate MIDI events from series
- Datasets: Use AbsTimed, AbsD for timing
Module Architecture
Serie Module
Factory module providing:
- Serie.base: Base module without source/sources
- Serie.with: Configurable module with source/sources/block
Prototyping Module
Implements prototype/instance lifecycle:
- State management (:prototype, :instance, :undefined)
- Cloning (prototype -> instance)
- State resolution from sources
- Validation and permissions
SerieImplementation Module
Core iteration protocol:
- init: Initialize instance state
- restart: Reset to beginning
- next_value: Consume next element
- peek_next_value: Look ahead without consuming
- current_value: Last consumed value
Serie Protocol
All series must implement:
def _next_value
# Return next value or nil when finished
end
def _init
# Initialize instance state (optional)
end
def _restart
# Reset to beginning (optional)
end
Usage Patterns
Basic Prototype/Instance
# Create prototype
proto = S(1, 2, 3)
proto.prototype? # => true
# Create instance
inst = proto.instance # or proto.i
inst.instance? # => true
# Consume values
inst.next_value # => 1
inst.next_value # => 2
Multiple Instances
proto = S(1, 2, 3)
a = proto.i
b = proto.i # Independent instance
a.next_value # => 1
b.next_value # => 1 (independent)
State Resolution
proxy = PROXY() # Undefined - no source yet
proxy.undefined? # => true
proxy.source = S(1, 2, 3) # Becomes prototype
proxy.prototype? # => true
Technical Details
Peek Mechanism
peek_next_value uses internal buffering to look ahead without state change:
s = S(1, 2, 3).i
s.peek_next_value # => 1 (buffered)
s.peek_next_value # => 1 (same)
s.next_value # => 1 (consumes buffered)
Source/Sources Pattern
Series can depend on:
- source: Single upstream serie
- sources: Multiple upstream series (Array or Hash)
State automatically resolves based on dependencies:
- All sources :prototype → :prototype
- All sources :instance → :instance
- Mixed or undefined → :undefined
Deep Copy Support
Uses Musa::Extension::DeepCopy for proper cloning including nested structures.
Applications
- Reusable melodic/harmonic patterns
- Multiple voices from single definition
- Lazy evaluation of algorithmic sequences
- Composable transformations
- Memory-efficient sequence playback
Defined Under Namespace
Modules: Composer, Constructors, Operations, Serie
Instance Method Summary collapse
-
#A(*series) ⇒ FromArrayOfSeries
included
from Constructors
Creates array-mode serie from array of series.
-
#AC(*series) ⇒ FromArrayOfSeries
included
from Constructors
Creates array-mode combined serie from array of series.
-
#E(*value_args, **key_args) {|value_args, last_value, caller, key_args| ... } ⇒ FromEvalBlockWithParameters
included
from Constructors
Creates serie from evaluation block.
-
#FIBO ⇒ Fibonacci
included
from Constructors
Creates Fibonacci sequence serie.
-
#FOR(from: nil, to: nil, step: nil) ⇒ ForLoop
included
from Constructors
Creates for-loop style numeric sequence.
-
#H(**series_hash) ⇒ FromHashOfSeries
included
from Constructors
Creates hash-mode serie from hash of series.
-
#HARMO(error: nil, extended: nil) ⇒ HarmonicNotes
included
from Constructors
Creates harmonic notes serie from fundamental.
-
#HC(**series_hash) ⇒ FromHashOfSeries
included
from Constructors
Creates hash-mode combined serie from hash of series.
-
#MERGE(*series) ⇒ Sequence
included
from Constructors
Merges multiple series sequentially.
-
#NIL ⇒ NilSerie
included
from Constructors
Creates serie that always returns nil.
-
#PROXY(serie = nil) ⇒ ProxySerie
included
from Constructors
Creates a proxy serie with optional initial source.
- #QUANTIZE(time_value_serie, reference: nil, step: nil, value_attribute: nil, stops: nil, predictive: nil, left_open: nil, right_open: nil) ⇒ Object included from Constructors
-
#QUEUE(*series) ⇒ QueueSerie
included
from Constructors
Creates queue serie from initial series.
-
#RND(*_values, values: nil, from: nil, to: nil, step: nil, random: nil) ⇒ RandomValuesFromArray, RandomNumbersFromRange
included
from Constructors
Creates random value serie from array or range.
-
#RND1(*_values, values: nil, from: nil, to: nil, step: nil, random: nil) ⇒ RandomValueFromArray, RandomNumberFromRange
included
from Constructors
Creates single random value serie from array or range.
-
#S(*values) ⇒ FromArray
included
from Constructors
Creates serie from array of values.
-
#SIN(start_value: nil, steps: nil, amplitude: nil, center: nil) ⇒ SinFunction
included
from Constructors
Creates sine wave function serie.
-
#TIMED_UNION(*array_of_timed_series, **hash_of_timed_series) ⇒ TimedUnionOfArrayOfTimedSeries, TimedUnionOfHashOfTimedSeries
included
from Constructors
Merges multiple timed series by synchronizing events at each time point.
-
#UNDEFINED ⇒ UndefinedSerie
included
from Constructors
Creates undefined serie.
Instance Method Details
#A(*series) ⇒ FromArrayOfSeries Originally defined in module 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.
#AC(*series) ⇒ FromArrayOfSeries Originally defined in module 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.
#E(*value_args, **key_args) {|value_args, last_value, caller, key_args| ... } ⇒ FromEvalBlockWithParameters Originally defined in module 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
#FIBO ⇒ Fibonacci Originally defined in module Constructors
Creates Fibonacci sequence serie.
Generates classic Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, ... Infinite serie.
#FOR(from: nil, to: nil, step: nil) ⇒ ForLoop Originally defined in module 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.
#H(**series_hash) ⇒ FromHashOfSeries Originally defined in module 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.
#HARMO(error: nil, extended: nil) ⇒ HarmonicNotes Originally defined in module 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
#HC(**series_hash) ⇒ FromHashOfSeries Originally defined in module 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.
#MERGE(*series) ⇒ Sequence Originally defined in module Constructors
Merges multiple series sequentially.
Plays series in sequence: first serie until exhausted, then second, etc. Restarts each serie (except first) before playing.
#NIL ⇒ NilSerie Originally defined in module Constructors
Creates serie that always returns nil.
Returns nil on every next_value call. Useful for padding or as placeholder in composite structures.
#PROXY(serie = nil) ⇒ ProxySerie Originally defined in module 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.
#QUANTIZE(time_value_serie, reference: nil, step: nil, value_attribute: nil, stops: nil, predictive: nil, left_open: nil, right_open: nil) ⇒ Object Originally defined in module Constructors
#QUEUE(*series) ⇒ QueueSerie Originally defined in module 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
#RND(*_values, values: nil, from: nil, to: nil, step: nil, random: nil) ⇒ RandomValuesFromArray, RandomNumbersFromRange Originally defined in module 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.
#RND1(*_values, values: nil, from: nil, to: nil, step: nil, random: nil) ⇒ RandomValueFromArray, RandomNumberFromRange Originally defined in module 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.
#S(*values) ⇒ FromArray Originally defined in module Constructors
Creates serie from array of values.
Most common constructor. Values can include ranges which will be expanded automatically via ExplodeRanges extension.
#SIN(start_value: nil, steps: nil, amplitude: nil, center: nil) ⇒ SinFunction Originally defined in module 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)
#TIMED_UNION(*array_of_timed_series, **hash_of_timed_series) ⇒ TimedUnionOfArrayOfTimedSeries, TimedUnionOfHashOfTimedSeries Originally defined in module 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] }
#UNDEFINED ⇒ UndefinedSerie Originally defined in module Constructors
Creates undefined serie.
Returns serie in undefined state. Useful as placeholder that will be resolved later (e.g., in PROXY).