Music-Abc-DT
view release on metacpan or search on metacpan
lib/Music/Abc/DT.pm view on Meta::CPAN
use 5.01400;
use strict;
use warnings FATAL => 'all';
BEGIN {
use Data::Dumper;
use Readonly;
use feature 'state'; #state variables are enabled
use Exporter 'import'; # gives you Exporter's import() method directly
use POSIX ();
use File::Temp ();
use List::MoreUtils qw{any};
our $VERSION = '0.01';
our %EXPORT_TAGS = (
'all' => [
qw( _broken_rhythm _head_par _length_header_dump _meter_calc _pscom_to_abc _slur_dump
_vover_to_abc _tuplet_to_abc _get_transformation _get_note_rest_bar_actuators
_get_null_info_clef_actuators _bar_dump _deco_dump _step_dump _get_chord_notes
_diatonic_interval _get_alter _get_chromatic_info _get_generic_info _get_ps
_get_specifier_from_generic_chromatic _interval_from_generic_and_chromatic _notes_to_chromatic
_notes_to_generic _notes_to_interval _convert_staff_distance_to_interval $brhythm @blen
$deco_tb %state_name )
]
);
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
# If you are only exporting function names it is recommended to omit the ampersand, as the
# implementation is faster this way.
our @EXPORT =
qw( &dt &dt_string &toabc &get_meter &get_length &get_wmeasure &get_gchords &get_key &get_time
&get_time_ql &is_major_triad &is_minor_triad &is_dominant_seventh &get_chord_step &get_fifth
&get_third &get_seventh &root &find_consecutive_notes_in_measure &get_pitch_class
&get_pitch_name $c_voice $sym %voice_struct);
use vars
qw( $deco_tb $in_grace $brhythm $gbr @blen $micro_tb $c_voice %voice_struct $c_tune $c_sym_ix
$c_abc $sym $c_bar %sym_name %state_name %info_name %STEPREF @key_shift @key_tonic $ly_st @clef_type
$toabc_called_outside $toabc_called_inside $GLOBAL $IMPLICIT_VOICE $QUARTER_LENGTH $FIRST_MEASURE);
Readonly our $GLOBAL => 'global'; # identifies data that is applied to the entire score (voice independent)
Readonly our $IMPLICIT_VOICE => 0; # default voice
Readonly our $QUARTER_LENGTH => 384; # default value for quarter length (abcm2ps)
Readonly our $FIRST_MEASURE => 1; # default value for the first measure
use constant { # info type
ABC_T_NULL => 0,
ABC_T_INFO => 1, # (first character of text gives the info type)
ABC_T_PSCOM => 2,
ABC_T_CLEF => 3,
ABC_T_NOTE => 4,
ABC_T_REST => 5,
ABC_T_BAR => 6,
ABC_T_EOLN => 7,
ABC_T_MREST => 8, # multi-measure rest
ABC_T_MREP => 9, # measure repeat
ABC_T_V_OVER => 10, # voice overlay
ABC_T_TUPLET => 11,
};
use constant { # symbol state in file/tune
ABC_S_GLOBAL => 0, # global
ABC_S_HEAD => 1, # in header (after X:)
ABC_S_TUNE => 2, # in tune (after K:)
ABC_S_EMBED => 3 # embedded header (between [..])
};
use constant { # info flags
ABC_F_ERROR => 0x0001, # error around this symbol
ABC_F_INVIS => 0x0002, # invisible symbol
ABC_F_SPACE => 0x0004, # space before a note
ABC_F_STEMLESS => 0x0008, # note with no stem
ABC_F_LYRIC_START => 0x0010, # may start a lyric here
ABC_F_GRACE => 0x0020, # grace note
ABC_F_GR_END => 0x0040, # end of grace note sequence
ABC_F_SAPPO => 0x0080 # short appoggiatura
};
use constant { # key mode
MAJOR => 7,
MINOR => 8,
BAGPIPE => 9 # bagpipe when >= 8
};
use constant { # clef type
TREBLE => 0,
ALTO => 1,
BASS => 2,
PERC => 3
};
use constant { # voice overlay
V_OVER_V => 0, # &
V_OVER_S => 1, # (&
V_OVER_E => 2 # &)
};
# key signatures
use constant KEY_NAMES => qw(ionian dorian phrygian lydian mixolydian aeolian locrian major minor HP Hp);
use constant { NONE => 'none' };
use constant { MAXVOICE => 32 }; # max number of voices
use constant { BASE_LEN => 1536 }; # basic note length (semibreve or whole note - same as MIDI)
use constant { DEFAULT_METER => '4/4' };
use constant { DEFAULT_LENGTH => '1/8' };
use constant { # accidentals
A_NULL => 0, # none
A_SH => 1, # sharp
A_NT => 2, # natural
A_FT => 3, # flat
A_DS => 4, # double sharp
A_DF => 5 # double flat
};
use constant { # bar types
B_BAR => 1, # |
B_OBRA => 2, # [
B_CBRA => 3, # ]
B_COL => 4 # :
};
use constant { # slur/tie types (3 bits)
SL_ABOVE => 0x01,
SL_BELOW => 0x02,
SL_AUTO => 0x03,
SL_DOTTED => 0x04 # (modifier bit)
};
our ( $in_grace, $brhythm, $gbr, $ly_st, $c_voice, %voice_struct );
our ( @blen, $micro_tb, $deco_tb );
our ( $c_tune, $c_sym_ix, $c_abc, $toabc_called_outside, $toabc_called_inside );
our %sym_name = (
# the extra () around the constants are there to fool the auto quoting
(ABC_T_NULL) => 'null',
(ABC_T_INFO) => 'info',
(ABC_T_PSCOM) => 'pscom',
(ABC_T_CLEF) => 'clef',
(ABC_T_NOTE) => 'note',
(ABC_T_REST) => 'rest',
(ABC_T_BAR) => 'bar',
(ABC_T_EOLN) => 'eoln',
(ABC_T_MREST) => 'mrest',
(ABC_T_MREP) => 'mrep',
(ABC_T_V_OVER) => 'vover',
(ABC_T_TUPLET) => 'tuplet',
);
our %info_name = (
'K' => 'key',
'L' => 'length',
lib/Music/Abc/DT.pm view on Meta::CPAN
# Updates the time offset for voice $c_voice
sub _update_time_offset {
if ( $sym->{type} ~~ [ ABC_T_NOTE, ABC_T_REST ] ) {
if ( !( $sym->{flags} & ABC_F_GRACE ) ) {
$voice_struct{$c_voice}{time} += $sym->{info}->{dur};
}
# FIXME atencao ao v_over, nao pode contar da mesma maneira
}
if ( $sym->{type} == ABC_T_MREST ) {
#abcm2ps-7.3.4/parse.c:2953
$voice_struct{$c_voice}{time} += $sym->{info}->{dur};
}
return;
}
# -- dump voice
sub _voice_header_dump {
my ( $abc, $sym ) = @_;
# FIXME PARSER quando no abc a voz de uma melodia está no formato "V: id\nABCD|z4" (note-se o espaço
# entre "V:" e id), a voz nao é identificada logo o id e a voice nao sao definidos
$abc .= sprintf 'V:%s', $sym->{info}->{id};
if ( $sym->{info}->{fname} ne q{} ) {
$abc .= sprintf ' name="%s"', $sym->{info}->{fname};
}
if ( $sym->{info}->{nname} ne q{} ) {
$abc .= sprintf ' sname="%s"', $sym->{info}->{nname};
}
if ( $sym->{info}->{merge} ) { $abc .= ' merge' }
if ( $sym->{info}->{stem} ) {
$abc .= sprintf ' stem=%s', _head_par( $sym->{info}->{stem} );
}
if ( $sym->{info}->{gstem} ) {
$abc .= sprintf ' gstem=%s', _head_par( $sym->{info}->{gstem} );
}
if ( $sym->{info}->{dyn} ) {
$abc .= sprintf ' dyn=%s', _head_par( $sym->{info}->{dyn} );
}
if ( $sym->{info}->{lyrics} ) {
$abc .= sprintf ' lyrics=%s', _head_par( $sym->{info}->{lyrics} );
}
if ( $sym->{info}->{gchord} ) {
$abc .= sprintf ' gchord=%s', _head_par( $sym->{info}->{gchord} );
}
if ( $sym->{info}->{scale} ) {
$abc .= sprintf ' scale=%.2f', $sym->{info}->{scale};
}
# print next symbol if it is a clef
if ( ref( $c_tune->{symbols}->[ $c_sym_ix + 1 ] )
&& $c_tune->{symbols}->[ $c_sym_ix + 1 ]->{type} == ABC_T_CLEF )
{
$abc = _clef_dump( $abc, $c_tune->{symbols}->[ $c_sym_ix + 1 ] );
}
return $abc;
}
# -- return abc of voice overlay
sub _vover_to_abc {
my ( $new_abc, $sym ) = @_;
given ( $sym->{info}->{type} ) {
when (V_OVER_V) { $new_abc .= q{&}; }
when (V_OVER_S) { $new_abc .= '(&'; }
when (V_OVER_E) { $new_abc .= '&)'; }
}
return $new_abc;
}
################################### Chord.pm ################################
# -- Returns the (first) pitch at the provided scaleDegree (chordStep)
# Returns undef if none can be found.
sub get_chord_step {
my ( $sym, $chord_step, $test_root ) = @_;
if ( !$test_root ) {
$test_root = root($sym);
if ( !$test_root ) {
die "Cannot run get_chord_step without a root\n";
}
}
for my $note_ref ( _get_chord_notes($sym) ) {
my ( $d_int, $c_int ) = _notes_to_interval( $test_root, $note_ref );
my $g_int_info = _get_generic_info( $d_int->{generic} );
if ( $g_int_info->{mod7} == $chord_step ) {
return $note_ref;
}
}
return;
}
# -- Shortcut for getChordStep(5)
sub get_fifth {
my $sym = shift;
return get_chord_step($sym, 5);
}
# -- Shortcut for getChordStep(7)
sub get_seventh {
my $sym = shift;
return get_chord_step($sym, 7);
}
# -- Shortcut for getChordStep(3)
sub get_third {
my $sym = shift;
return get_chord_step($sym, 3);
}
( run in 0.677 second using v1.01-cache-2.11-cpan-9789f410c06 )