NAME

Music::NWC2MusicXML::Event - Internal representation of a single NWC musical event or score metadata record.

VERSION

0.001.0

SYNOPSIS

use Music::NWC2MusicXML::Event;

# Musical event
my $note = Music::NWC2MusicXML::Event->new(
    type       => 'Note',
    start_time => [0, 1],   # rational: 0 quarter-notes from measure start
    duration   => [1, 1],   # rational: one quarter note
    data       => {
        pitch      => 'C',
        octave     => 4,
        accidental => 0,
    },
);

# Unsupported / unknown object
my $unknown = Music::NWC2MusicXML::Event->new(
    type      => 'UnsupportedEvent',
    nwc_label => 'SomeFutureObject',
    data      => { raw => '|SomeFutureObject|...' },
);

DESCRIPTION

Music::NWC2MusicXML::Event is the internal representation of one NWC record. It covers both musical events (notes, rests, bars, dynamics, ...) and score/staff metadata (SongInfo, StaffProperties, ...).

Musical timing is represented using exact rational numbers stored as two-element arrayrefs [$numerator, $denominator]. Floating-point arithmetic is never used for musical durations; this avoids cumulative rounding errors when dividing a beat into complex tuplet groupings.

Unknown NWC object types are stored as UnsupportedEvent records so that conversion can continue rather than aborting.

new

Construct a new Event.

Purpose

Factory constructor used by the parser to wrap each parsed NWC record into a typed, time-stamped object suitable for later MusicXML generation.

Arguments

Named parameters:

type (string, required) -- one of the recognised event type names listed in %MUSICAL_EVENT_TYPES or %METADATA_EVENT_TYPES, or UnsupportedEvent.
nwc_label (string, optional) -- the original NWC record label, useful when type is UnsupportedEvent.
start_time (arrayref [$num,$den], optional) -- rational offset from the beginning of the current measure. Default [0,1].
duration (arrayref [$num,$den], optional) -- rational duration in quarter-note units. Default [0,1] for non-durational events.
data (hashref, optional) -- type-specific payload (see below).

Data payloads by type

Note -- pitch, octave, accidental, tie_start, tie_stop, slur_start, slur_stop, articulations (arrayref), stem_direction, grace.
Rest -- (no pitch fields).
Chord -- notes (arrayref of Note-like hashrefs).
Clef -- nwc_clef (e.g. Treble).
Key -- nwc_signature (e.g. Bb), tonic, mode.
TimeSig -- beats, beat_type.
Tempo -- bpm.
Dynamic -- marking (e.g. mf).
Lyric -- text, verse, syllabic (begin|middle|end|single).
Bar -- style (normal|double|final|repeat_start|repeat_end|section).
FlowControl -- directive (e.g. Coda, Segno, DaCapo).
UnsupportedEvent -- raw (original NWC text line).

Returns

A blessed Music::NWC2MusicXML::Event object.

Side Effects

None.

Usage Example

my $rest = Music::NWC2MusicXML::Event->new(
    type       => 'Rest',
    start_time => [1, 1],
    duration   => [1, 2],   # eighth rest
);

API SPECIFICATION

Input

type       : SCALAR  (required)
               -- Valid domain: any string registered in %MUSICAL_EVENT_TYPES
               --   or %METADATA_EVENT_TYPES (see Event.pm constants)
               -- Invalid partition: unknown/unregistered string, undef, or ''
               --   -> stored as UnsupportedEvent (carp), not croak
nwc_label  : SCALAR  (optional)
start_time : ARRAYREF [int>=0, int>0]  (optional, default [0,1])
               -- Valid domain: exactly-2-element arrayref [numerator, denominator]
               --   where denominator > 0.  Numerator >= 0.
               -- Invalid: non-arrayref, 1-element, 3+-element, or denominator=0
               --   -> croak error_bad_rational
duration   : ARRAYREF [int>=0, int>0]  (optional, default [0,1])
               -- Same constraints as start_time
data       : HASHREF  (optional, default {})

Output

Music::NWC2MusicXML::Event object

MESSAGES

| Code | Meaning | Resolution | |---------------------|-----------------------------------------|------------------------| | error_unknown_type | Type string not in recognised set | Check NWC record label | | error_bad_rational | start_time or duration malformed | Use [$num,$den] form |

FORMAL SPECIFICATION

[EventInit]
  type       : EventType
  start_time : Q+  (non-negative rational)
  duration   : Q+  (non-negative rational)
  data       : DATA

(placeholder -- populate with Z calculus as implementation matures)

type

Return the event type string.

Returns

Scalar string.

nwc_label

Return the original NWC record label (especially useful for UnsupportedEvent).

start_time

Return the rational start time as an arrayref [$num, $den].

duration

Return the rational duration as an arrayref [$num, $den].

data

Return the type-specific payload hashref.

is_musical_event

Return true if this event contributes to the musical timeline (note, rest, chord, ...) as opposed to being a metadata record.

is_metadata

Return true if this record is score/staff metadata.

rational_from_nwc_duration

Class method. Convert an NWC duration name and dot count to a rational arrayref [$num, $den] in quarter-note units.

Arguments

nwc_duration -- string such as 4th, 8th, Half etc.
dots -- number of augmentation dots (0, 1, or 2).

Returns

Arrayref [$num, $den].

API SPECIFICATION

Input

nwc_duration : SCALAR (required)
                 -- Valid domain: exactly one of the 7 NWC duration names:
                 --   'Whole', 'Half', '4th', '8th', '16th', '32nd', '64th'
                 -- Invalid partitions: undef, '' (empty), 'Quarter' (wrong name),
                 --   'whole' (wrong case), any other string -> croak error_bad_duration
                 -- Note: NWC uses '4th' not 'Quarter' for the quarter note.
dots         : SCALAR int >= 0 (optional, default 0)
                 -- Valid domain: 0 (no dots), 1 (dotted), 2 (double-dotted)
                 -- NWC maximum is 2; dots=3+ are mathematically valid but not
                 --   produced by any NWC 2.x score; undef treated as 0

Output

ARRAYREF [$num:int, $den:int]  (rational in quarter-note units, reduced to lowest terms)

FORMAL SPECIFICATION

(placeholder)

rational_add

Class method. Add two rational numbers.

Arguments

Two arrayrefs [$n1,$d1] and [$n2,$d2].

Returns

Arrayref [$num,$den] in lowest terms.

rational_to_float

Class method. Convert a rational to a floating-point number for display or approximate comparison only. Never use the result for musical timing.

API SPECIFICATION

Input

$r : ARRAYREF [$num:int, $den:int>0]  (required)
       -- Valid domain: exactly-2-element arrayref where $den > 0
       -- Invalid: non-arrayref scalar, 1-element arrayref, 3+-element arrayref,
       --   or denominator = 0 -> croak error_bad_rational
       -- BVA boundary: $num = 0 is valid (returns 0.0)

Output

SCALAR (floating-point approximation of $num / $den)

DIAGNOSTICS

MESSAGES

| Code | Meaning | Resolution | |----------------------|--------------------------------------|-----------------------------| | error_unknown_type | Unrecognised event type | Will be stored as UnsupportedEvent | | error_bad_duration | NWC duration name not in lookup table| Check parser input | | error_bad_rational | Rational arrayref malformed | Use [$non-neg-int, $pos-int] |

LIMITATIONS

  • Double-dotted notes supported; triple-dotted are not.

  • Tuplet time-modification is not computed here; the parser applies it to each affected event.

AUTHOR

Nigel Horne <nigel.horne@gmail.com>

LICENSE

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.