Class: Musa::Neumas::Decoders::NeumaDifferentialDecoder

Inherits:
DifferentialDecoder show all
Defined in:
lib/musa-dsl/neumas/neuma-gdvd-decoder.rb

Overview

GDVD neuma decoder for preserving differential format.

Simple decoder that processes GDVD (Grade-Duration-Velocity-Differential) neumas without converting to absolute GDV format. Useful when you need to work with differential values directly or perform intermediate processing.

GDVD Format

GDVD maintains relative/differential values:

{
  grade_diff: +2,        # Relative grade change
  duration_factor: 2,    # Duration multiplier
  velocity_factor: 1.2,  # Velocity multiplier
  modifiers: {...}       # Ornaments, articulations
}

Use Cases

  • Intermediate processing: Transform neumas before converting to GDV
  • Pattern analysis: Analyze melodic intervals without absolute pitch
  • Transposition: Work with relative values for easy transposition

vs NeumaDecoder

  • NeumaDifferentialDecoder: Keeps differential format (GDVD)
  • NeumaDecoder: Converts to absolute format (GDV) using scale

Examples:

Process GDVD

decoder = Musa::Neumas::Decoders::NeumaDifferentialDecoder.new(
  base_duration: 1/4r
)

# The keys are GDVd's own, and the event must carry the dataset: a bare
# hash has no base_duration to set.
gdvd = decoder.decode({ delta_grade: 2, factor_duration: 2 }.extend(Musa::Datasets::GDVd))
gdvd  # => { delta_grade: 2, factor_duration: 2 }
gdvd.base_duration  # => 1/4r
# Still differential, not converted to absolute

Intermediate processing workflow

# Process neumas in differential format before final conversion
using Musa::Extension::Neumas

neumas = "(0) (+2) (+2) (-1) (0)".to_neumas
differential_decoder = Musa::Neumas::Decoders::NeumaDifferentialDecoder.new

# Process each neuma, keeping the differential format. A serie has no
# `each`: `map` is a serie operation and stays lazy until consumed.
gdvds = neumas.map { |neuma| differential_decoder.decode(neuma[:gdvd]) }

gdvds.i.to_a
# => [{ abs_grade: 0 }, { delta_grade: 2 }, { delta_grade: 2 },
#     { delta_grade: -1 }, { abs_grade: 0 }]
# Still differential, and transformable before converting to absolute GDV

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(base_duration: nil) ⇒ NeumaDifferentialDecoder

Creates differential GDVD decoder.

Examples:

Create decoder with eighth note base

decoder = NeumaDifferentialDecoder.new(base_duration: 1/8r)

Parameters:

  • base_duration (Rational, nil) (defaults to: nil)

    base duration unit (default: 1/4)



75
76
77
# File 'lib/musa-dsl/neumas/neuma-gdvd-decoder.rb', line 75

def initialize(base_duration: nil)
  @base_duration = base_duration || Rational(1,4)
end

Instance Method Details

#process(gdvd) ⇒ Hash

Processes GDVD by setting base_duration.

Clones GDVD and sets base_duration for duration calculations. Does not convert to absolute values.

Examples:

Process differential neuma

quarters = NeumaDifferentialDecoder.new(base_duration: 1/4r)
gdvd = { delta_grade: 2, factor_duration: 2 }.extend(Musa::Datasets::GDVd)
result = quarters.process(gdvd)
result  # => { delta_grade: 2, factor_duration: 2 }
result.base_duration  # => 1/4r
# base_duration travels with the event, it is not one of its keys

Parameters:

  • gdvd (Hash)

    GDVD attributes

Returns:

  • (Hash)

    GDVD with base_duration set



97
98
99
# File 'lib/musa-dsl/neumas/neuma-gdvd-decoder.rb', line 97

def process(gdvd)
  gdvd.clone.tap { |_| _.base_duration = @base_duration }
end