Class: Array

Inherits:
Object show all
Defined in:
lib/musa-dsl/matrix/matrix.rb,
lib/musa-dsl/matrix/matrix.rb,
lib/musa-dsl/matrix/matrix.rb,
lib/musa-dsl/core-ext/arrayfy.rb,
lib/musa-dsl/core-ext/hashify.rb,
lib/musa-dsl/series/array-to-serie.rb,
lib/musa-dsl/neumas/array-to-neumas.rb,
lib/musa-dsl/neumas/array-to-neumas.rb,
lib/musa-dsl/neumas/array-to-neumas.rb,
lib/musa-dsl/core-ext/array-explode-ranges.rb

Instance Method Summary collapse

Instance Method Details

#arrayfy(size: nil, default: nil) ⇒ Array

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Arrayfy.

Note:

The cycling formula: array * (size / array.size + (size % array.size).zero? ? 0 : 1) ensures enough repetitions to reach target size.

Clones or cycles the array to achieve the target size, with nil replacement.

The cycling behavior multiplies the array enough times to reach or exceed the target size, then takes exactly the requested number of elements. Singleton class modules (like P, V dataset extensions) are preserved.

Examples:

Cycling shorter array

using Musa::Extension::Arrayfy
[1, 2].arrayfy(size: 5)  # => [1, 2, 1, 2, 1]

Truncating longer array

using Musa::Extension::Arrayfy
[1, 2, 3, 4, 5].arrayfy(size: 3)  # => [1, 2, 3]

Preserving dataset modules

using Musa::Extension::Arrayfy
p_sequence = [60, 1, 62].extend(Musa::Datasets::P)
p_sequence.arrayfy(size: 6)  # => [60, 1, 62, 60, 1, 62]
p_sequence.arrayfy(size: 6).is_a?(Musa::Datasets::P)  # => true

# The module survives the cycling, which is what lets a P be padded
# to a voice's length and still be played as a P.

Parameters:

  • size (Integer, nil) (defaults to: nil)

    target length. If nil, returns clone of array.

  • default (Object, nil) (defaults to: nil)

    value to replace nil elements with.

Returns:

  • (Array)

    processed array of exactly the requested size.



132
# File 'lib/musa-dsl/core-ext/arrayfy.rb', line 132

class ::Array; end

#condensed_matricesArray<::Matrix>

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Matrix.

Condenses matrices that share common boundary rows.

This method merges matrices that have matching first or last rows, effectively connecting musical gestures that share endpoints. This is particularly useful for creating continuous trajectories from fragmented matrix segments.

The algorithm compares each matrix with all previously processed matrices, looking for matches at either the beginning or end of the row sequence. When a match is found, the matrices are merged.

Examples:

Matrices that share a boundary are merged

using Musa::Extension::Matrix
# Matrix A ends where Matrix B begins -> they merge
a = Matrix[[0, 60], [1, 62]]
b = Matrix[[1, 62], [2, 64]]
[a, b].condensed_matrices
# => [Matrix[[0, 60], [1, 62], [2, 64]]]

Returns:

  • (Array<::Matrix>)

    condensed array of matrices with shared boundaries merged.



170
# File 'lib/musa-dsl/matrix/matrix.rb', line 170

class ::Array; end

#explode_rangesArray

Note:

This method is added to Array via refinement. Requires using Musa::Extension::ExplodeRanges.

Expands all Range objects in the array into their individual elements.

Iterates through the array and converts any Range objects to their constituent elements via to_a, leaving non-Range elements unchanged. The result is a new flat array.

Examples:

Empty ranges

using Musa::Extension::ExplodeRanges
[1, (5..4), 8].explode_ranges  # (5..4) is empty
# => [1, 8]

Exclusive ranges

using Musa::Extension::ExplodeRanges
[1, (3...6), 9].explode_ranges
# => [1, 3, 4, 5, 9]

Nested arrays are NOT expanded recursively

using Musa::Extension::ExplodeRanges
[1, [2..4], 5].explode_ranges
# => [1, [2..4], 5]  # Inner range NOT expanded

Returns:

  • (Array)

    new array with all ranges expanded.



70
# File 'lib/musa-dsl/core-ext/array-explode-ranges.rb', line 70

class ::Array; end

#hashify(keys:, default: nil) ⇒ Hash

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Hashify.

Maps array elements to hash keys in order, consuming the array.

Elements are assigned to keys sequentially. If the array has fewer elements than keys, remaining keys get nil (or default). The array is cloned before consumption, so the original is unchanged.

Examples:

Basic array mapping

using Musa::Extension::Hashify
[60, 100, 0.25].hashify(keys: [:pitch, :velocity, :duration])
# => { pitch: 60, velocity: 100, duration: 0.25 }

Fewer elements than keys

using Musa::Extension::Hashify
[60, 100].hashify(keys: [:pitch, :velocity, :duration], default: nil)
# => { pitch: 60, velocity: 100, duration: nil }

More elements than keys (extras ignored)

using Musa::Extension::Hashify
[60, 100, 0.5, :ignored].hashify(keys: [:pitch, :velocity])
# => { pitch: 60, velocity: 100 }

Parameters:

  • keys (Array<Symbol>)

    keys for the resulting hash (in order).

  • default (Object, nil) (defaults to: nil)

    value for keys without corresponding array elements.

Returns:

  • (Hash)

    hash with keys mapped to array elements in order.



142
# File 'lib/musa-dsl/core-ext/hashify.rb', line 142

class ::Array; end

#indexes_of_valuesHash{Object => Array<Integer>}

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Matrix.

Creates a hash mapping values to their indices in the array.

This method scans the array and builds an inverted index where each unique value maps to an array of positions where it appears.

Examples:

Where each value appears

using Musa::Extension::Matrix
[10, 20, 10, 30, 20].indexes_of_values
# => { 10 => [0, 2], 20 => [1, 4], 30 => [3] }

Returns:

  • (Hash{Object => Array<Integer>})

    hash where keys are array values and values are arrays of indices.



115
# File 'lib/musa-dsl/matrix/matrix.rb', line 115

class ::Array; end

#nObject

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Neumas.

Short alias for to_neumas.

See Also:



162
# File 'lib/musa-dsl/neumas/array-to-neumas.rb', line 162

class ::Array; end

#neumasObject

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Neumas.

Alias for to_neumas.

See Also:



152
# File 'lib/musa-dsl/neumas/array-to-neumas.rb', line 152

class ::Array; end

#to_neumasSerie, Neuma

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Neumas.

Converts array elements to merged neuma series.

  • Single element: Returns converted element directly
  • Multiple elements: Returns MERGE of all converted elements

Each element is converted based on its type:

  • String → parsed as neuma notation
  • Neuma::Serie → used directly
  • Neuma::Parallel → wrapped in series

Examples:

Convert string array

using Musa::Extension::Neumas

phrases = [
  "(0) (+2) (+4)",
  "(+5) (+7)"
].to_neumas

phrases.class.name  # => "Musa::Series::Constructors::Sequence"

grades = ->(s) { s.i.to_a.map { |n| n[:gdvd][:abs_grade] || n[:gdvd][:delta_grade] } }
grades[phrases]  # => [0, 2, 4, 5, 7]

Mixed types

using Musa::Extension::Neumas

existing = "(0) (+2)".to_neumas
combined = [existing, "(+4) (+5)"].to_neumas

grades = ->(s) { s.i.to_a.map { |n| n[:gdvd][:abs_grade] || n[:gdvd][:delta_grade] } }
grades[combined]  # => [0, 2, 4, 5]

Single element

using Musa::Extension::Neumas

single = ["(0) (+2) (+4)"].to_neumas
# Returns parsed series directly (not merged)

Returns:

  • (Serie, Neuma)

    merged series or single neuma

Raises:

  • (ArgumentError)

    if element type cannot be converted



142
# File 'lib/musa-dsl/neumas/array-to-neumas.rb', line 142

class ::Array; end

#to_p(time_dimension:, keep_time: nil) ⇒ Array<Array<Musa::Datasets::P>>

Note:

This method is added to Array via refinement. Requires using Musa::Extension::Matrix.

Converts an array of matrices to an array of P sequences.

This method processes each matrix in the array, first condensing matrices that share common endpoints, then converting each resulting matrix to P (point sequence) format.

Examples:

Converting array of matrices

using Musa::Extension::Matrix
matrices = [Matrix[[0, 60], [1, 62]], Matrix[[2, 64], [3, 65]]]
matrices.to_p(time_dimension: 0)
# => [[[[60], 1, [62]]], [[[64], 1, [65]]]]

# One entry per matrix here, because these two do not share a
# boundary row and so are not condensed into one.

Parameters:

  • time_dimension (Integer)

    index of the dimension to treat as time.

  • keep_time (Boolean, nil) (defaults to: nil)

    whether to preserve the time dimension in the output. When false or nil, the time dimension is removed and used only for duration calculations.

Returns:

See Also:



145
# File 'lib/musa-dsl/matrix/matrix.rb', line 145

class ::Array; end

#to_serie(of_series: nil, recursive: nil) ⇒ Serie Also known as: s

Converts array to Serie.

Three conversion modes:

  • Basic: Direct conversion to serie
  • of_series: Each element of the array becomes a new serie (for array of arrays)
  • recursive: Recursive conversion of nested arrays

Examples:

Basic conversion

[60, 64, 67].to_serie.i.to_a  # => [60, 64, 67]

Serie of series

nested = [[1, 2], [3, 4]].to_serie(of_series: true)

# Each element is a serie of its own, so reading one means instantiating it
nested.i.to_a.collect { |serie| serie.i.to_a }
# => [[1, 2], [3, 4]]

Recursive conversion

nested = [[1, [2, 3]], [4, 5]].to_serie(recursive: true)

# It goes all the way down: the first element is a serie holding a value
# and another serie.
first = nested.i.next_value.i.to_a
first.first          # => 1
first.last.i.to_a    # => [2, 3]

Parameters:

  • of_series (Boolean, nil) (defaults to: nil)

    convert each element to a serie (default: false)

  • recursive (Boolean, nil) (defaults to: nil)

    recursively convert nested arrays (default: false)

Returns:

  • (Serie)

    converted serie

Raises:

  • (ArgumentError)

    if both of_series and recursive are true



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/musa-dsl/series/array-to-serie.rb', line 42

def to_serie(of_series: nil, recursive: nil)
  of_series ||= false
  recursive ||= false

  raise ArgumentError, 'Cannot convert to serie of_series and recursive simultaneously' if recursive && of_series

  if recursive
    Musa::Series::Constructors.S(*(collect { |_| _.is_a?(Array) ? _.to_serie(recursive: true) : _ }))
  elsif of_series
    Musa::Series::Constructors.S(*(collect { |_| Musa::Series::Constructors.S(*_) }))
  else
    Musa::Series::Constructors.S(*self)
  end
end