The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Music::LilyPondUtil - utility methods for lilypond data

SYNOPSIS

  use Music::LilyPondUtil ();
  my $lyu   = Music::LilyPondUtil->new;

  my $pitch = $lyu->notes2pitches("c'") # 60
  $lyu->diatonic_pitch("ces'")          # 60

  $lyu->ignore_register(1);
  $lyu->notes2pitches("c'")             # 0
  $lyu->diatonic_pitch("ces'")          # 0


  my $note  = $lyu->p2ly(60)            # c'

  $lyu->mode('relative');
  my @bach  = $lyu->p2ly(qw/60 62 64 65 62 64 60 67 72 71 72 74/)
      # c d e f d e c g' c b c d

  $lyu->keep_state(0);
  $lyu->p2ly(qw/0 1023 79 77 -384/);   # c dis g f c

  $lyu->chrome('flats');
  $lyu->p2ly(qw/2 9 5 2 1 2/);         # d a f d des d

DESCRIPTION

Utility methods for interacting with lilypond (as of version 2.16), most notably for the conversion of integers to lilypond note names (or the other way around, for a subset of the lilypond notation). The Western 12-tone system is assumed.

The note conversions parse the lilypond defaults, including enharmonic equivalents such as bes or ceses (for C double flat or more simply B flat) and bis (B sharp or C natural) but not any microtonal cih, beh nor any other conventions. Lilypond output is restricted to all sharps or all flats (set via a parameter), and never emits double sharps nor double flats. Pitch numbers are integers, and might be the MIDI note numbers, or based around 0, or whatever, depending on the need and the parameters set.

CLASS METHODS

The module will throw errors via croak if an abnormal condition is encountered.

new optional params

Constructor. Optional parameters include:

  • chrome to set the accidental style (sharps or flats). Mixing flats and sharps is not supported. (Under no circumstances are double sharps or double flats emitted, though the module does know how to read those.)

  • ignore_register a boolean that if set causes the diatonic_pitch and notes2pitches methods to only return values from 0..11. The default is to include the register information in the resulting pitch. Set this option if feeding data to atonal routines, for example those in Music::AtonalUtil.

  • keep_state a boolean, enabled by default, that will maintain state on the previous pitch in the p2ly call. State is not maintained across separate calls to p2ly (see also the sticky_state param).

    Disabling this option will remove all register notation from both relative and absolute modes.

  • min_pitch integer, by default 0, below which pitches passed to p2ly will cause the module to by default throw an exception. To constrain pitches to what an 88-key piano is capable of, set:

      Music::LilyPondUtil->new( min_pitch => 21 );

    Too much existing code allows for zero as a minimum pitch to set 21 by default, or if ignore_register is set, pitches from notes2pitches are constrained to zero through eleven, and relative lilypond notes can easily be generated from those...so 0 is the minimum.

  • min_pitch_hook code reference to handle minimum pitch cases instead of the default exception. The hook is passed the pitch, min_pitch, max_pitch, and the object itself as arguments. The hook must return undef if the value is to be accepted, or something not defined to use that instead, or could throw an exception, which will be re-thrown via croak. One approach would be to silence the out-of-bounds pitches by returning a lilypond rest symbol:

      Music::LilyPondUtil->new( min_pitch_hook => sub { 'r' } );

    One use for this is to generate pitch numbers via some mechanism and then silence or omit the pitches that fall outside a particular range of notes via the *_pitch_hook hook functions. See "EXAMPLES" for sample code.

  • max_pitch integer, by default 108 (the highest note on a standard 88- key piano), above which pitches passed to p2ly will cause the module to by default throw an exception.

  • max_pitch_hook code reference to handle minimum pitch cases instead of the default exception. The hook is passed the pitch, min_pitch, max_pitch, and the object itself as arguments. Return values are handled as for the min_pitch_hook, above.

  • mode to set absolute or relative mode. Default is absolute. Altering this changes how both notes2pitches and p2ly operate. Create two instances of the object if this is a problem, and set the appropriate mode for the appropriate routine.

  • p2n_hook to set a custom code reference for the pitch to note conversion (see source for details, untested, use at own risk, blah blah blah).

  • sticky_state a boolean, disabled by default, that if enabled, will maintain the previous pitch state across separate calls to p2ly, assuming keep_state is also enabled, and again only in relative mode.

  • strip_rests boolean that informs notes2pitches as to whether rests should be omitted. By default, rests are returned as undefined values.

    (Canon or fugue related calculations, in particular, need the rests, as otherwise the wrong notes line up with one another in the comparative lists. An alternative approach would be to convert notes to start times and durations (among other metadata), and ignore rests, but that would take more work to implement. It would, however, better suit larger data sets.)

patch2instrument patch_number

Given a MIDI patch number (presumably in the range from 0 to 127, inclusive), returns the instrument name (or otherwise the empty string).

METHODS

Call these on an object created via new.

chrome optional sharps or flats

Get/set accidental style.

clear_prev_note

For use with notes2pitches. Wipes out the previous note (the state variable used with sticky_state enabled in relative mode to maintain state across multiple calls to notes2pitches.

clear_prev_pitch

For use with p2ly. Wipes out the previous pitch (the state variable used with sticky_state enabled in relative mode to maintain state across multiple calls to p2ly). Be sure to call this method after completing any standalone chord or phrase, as otherwise any subsequent p2ly calls will use the previously cached pitch.

diatonic_pitch note

Returns the diatonic (here defined as the white notes on the piano) pitch number for a given lilypond absolute notation note, for example ceses', ces', c', cis', and cisis' all return 60. This method is influenced by the ignore_register, min_pitch, and max_pitch parameters.

ignore_register optional boolean

Get/set ignore_register param.

keep_state optional boolean

Get/set keep_state param.

mode optional relative or absolute

Get/set the mode of operation.

notes2pitches list of note names or pitch numbers

Converts note names to pitches. Raw pitch numbers (integers) are passed through as is. Lilypond non-note r or s in any case are converted to undefined values (likewise for notes adorned with \rest). Otherwise, lilypond note names (c, cis, etc.) and registers (', '', etc.) are converted to a pitch number. The ignore_register and strip_rests options can influence the output. Use the prev_note method to set what a \relative d'' { ... statement in lilypond would do:

  $lyu->prev_note(q{d''});
  $lyu->notes2pitches(qw/d g fis g a g fis e/);

Returns list of pitches (integers), or single pitch as scalar if only a single pitch was input.

p2ly list of pitches or whatnot

Converts a list of pitches (integers or objects that have a pitch method that returns an integer) to a list of lilypond note names. Unknown data will be passed through as is. Returns said converted list. The behavior of this method depends heavily on various parameters that can be passed to new or called as various methods, notably the prev_pitch method to set the most recent diatonic pitch.

However, note that prev_pitch will only influence the first note (probably in a surprising way). Pitches are pitches, and if they need to be transposed to a particular register, run something like:

  $n += 60 for @list_of_pitches;

on all the pitches. Methods from Music::Canon might be another option, for example if contrary motion or retrograde must also be calculated on the pitches to be transposed.

prev_note optional note

For use with notes2pitches. Get/set previous note (the state variable used with sticky_state enabled in relative mode to maintain state across multiple calls to p2ly). Optionally accepts only a note (for example, ces, or f''), and always returns the current previous note (which may be unset), which will be the pitch of the diatonic of the note provided (e.g. ces, will return the pitch for c,, and fisfis''' the pitch for f''').

prev_pitch optional pitch

For use with p2ly. Get/set previous pitch (the state variable used with sticky_state enabled in relative mode to maintain state across multiple calls to p2ly). Can be a pitch number, or lilypond note name, though the lilypond note name will be converted to the nearest diatonic pitch number, and may be influenced by various other parameters set (notably ignore_register).

reg_num2sym number

Utility method, converts an arbitrary number into a lilypond register symbol, with the empty string being returned for the default register 4.

  $lyu->reg_num2sym(3)        # ,
  $lyu->reg_num2sym(6)        # ''
reg_sym2num register

Utility method, converts an arbitrary lilypond register symbol into a register number. Pass the empty string to obtain the default register.

  $lyu->reg_sym2num( q{,}  )  # 3
  $lyu->reg_sym2num( q{}   )  # 4
  $lyu->reg_sym2num( q{''} )  # 6
sticky_state optional boolean

Get/set sticky_state param.

strip_rests optional boolean

Get/set strip_rests param.

EXAMPLES

An idea for composition: generate pitch numbers via some mathematical function, and omit the notes if they fall outside a particular range. This method requires the use of a graphing calculator, knowledge of various mathematical functions, and spare time, though may produce interesting results, depending on how the function(s) interact with the playable range. This example strips pitches that exceed the limits:

  use Music::LilyPondUtil ();
  my $lyu = Music::LilyPondUtil->new(
    min_pitch      => 59,
    max_pitch      => 79,
    min_pitch_hook => sub { '' },
    max_pitch_hook => sub { '' },
  );
  
  # generate notes from mathematical function
  my @notes;
  for my $t ( 1 .. 174 ) {
    my $pitch = 50 * cos( $t / 25 ) + 3 * sin( 2 * $t ) + 22;
    push @notes, grep length $_ > 0, $lyu->p2ly($pitch);
  }
  
  # replace repeated notes with rests
  for my $ni ( 1 .. $#notes ) {
    $notes[$ni] = 'r' if $notes[$ni] eq $notes[ $ni - 1 ];
  }
  
  print "@notes\n";

This output could then be piped to the ly-fu utility of App::MusicTools, for example if saved as domath:

  $ perl domath | ly-fu --open --instrument=drawbar\ organ --absolute -

Which in turn would require lilypond, a PDF viewer, and a MIDI player.

This more complicated example uses the reflect_pitch method of Music::AtonalUtil to fold out-of-bounds pitches to within the limits:

  use Music::AtonalUtil;
  use Music::LilyPondUtil;

  my $atu = Music::AtonalUtil->new;
  my $lyu = Music::LilyPondUtil->new(
    min_pitch      => 59,
    max_pitch      => 79,
    min_pitch_hook => \&fold,
    max_pitch_hook => \&fold,
  );

  sub fold {
    my ($p, $min, $max, $self) = @_;
    return $self->p2ly( $atu->reflect_pitch( $p, $min, $max ) );
  }

SEE ALSO

http://www.lilypond.org/ and most notably the Learning and Notation manuals.

My other music related modules, including App::MusicTools, Music::AtonalUtil, Music::Canon, and Music::PitchNum.

AUTHOR

thrig - Jeremy Mates (cpan:JMATES) <jmates at cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2012-2013,2015 Jeremy Mates

This module is free software; you can redistribute it and/or modify it under the Artistic License (2.0).