App-MusicTools

 view release on metacpan or  search on metacpan

bin/atonal-util  view on Meta::CPAN

use List::Util           qw/sum/;
use Music::AtonalUtil    ();
use Music::LilyPondUtil  ();
use Music::Scala         ();
use Music::Scales        qw/get_scale_nums/;
use Music::Tempo         qw/bpm_to_ms ms_to_bpm/;
use Music::Tension::Cope ();
# untested with --tension
#use Music::Tension::PlompLevelt ();
use Parse::Range qw/parse_range/;
use Scalar::Util qw/looks_like_number/;

my %modes = (
    adjacent_interval_content => \&adjacent_interval_content,
    bark                      => \&bark,
    basic                     => \&basic,
    beats2set                 => \&beats2set,
    circular_permute          => \&circular_permute,
    combos                    => \&combos,
    complement                => \&complement,
    equivs                    => \&equivs,

bin/atonal-util  view on Meta::CPAN

    } else {
        for my $arg (@args) {
            push @freqs, split ' ', $arg;
        }
    }

    if ( @freqs < 2 ) {
        die "Usage: $0 combos [--pitches [--relative=note]] f1 f2 [f3...]\n";
    }

    # turn on pitch mode if first note looks more a note than a number
    if ( $Flag_Pitches or $freqs[0] =~ m/[a-g]/ ) {
        @freqs = map $p2f->($_), $Lyu->notes2pitches(@freqs);
    }

    for my $i ( 1 .. $#freqs ) {
        my $plus  = $freqs[0] + $freqs[1];
        my $minus = $freqs[$i] - $freqs[0];

        # (try to) Figure out MIDI pitch of combination tone, and what the
        # error is due to presumed equal temperament tuning of said MIDI

bin/atonal-util  view on Meta::CPAN


    if ( !@args or ( @args == 1 and $args[0] eq '-' ) ) {
        chomp( @args = readline *STDIN );
    }

    # Not the default, so if things persist or chain due to some rewrite,
    # would need to save the old or create a new object or whatever
    $Lyu->keep_state(1);
    $Lyu->mode('absolute');

    for my $freq ( grep looks_like_number $_, map { split ' ', $_ } @args ) {
        die "frequency '$freq' out of range" if $freq < 8 or $freq > 4200;

        my $p = $scala->freq2pitch($freq);

        # how off is the frequency from the given scale and concertfreq?
        my $pitch_freq = $scala->pitch2freq($p);
        my $error      = $freq - $pitch_freq;

        $p = $Lyu->p2ly($p) if $Flag_Lyout;

bin/atonal-util  view on Meta::CPAN

        $prev_dur = $duration;
    }
}

sub multiply {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts, 'factor|n=s' => \my $factor, )
      or print_help();
    $Lyu->chrome('flats') if $Flag_Flat;
    $factor //= 1;
    die "factor must be number\n" unless looks_like_number $factor;
    emit_pitch_set( $Atu->multiply( $factor, args2pitchset(@args) ) );
}

sub normal_form {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts ) or print_help();
    $Lyu->chrome('flats') if $Flag_Flat;
    emit_pitch_set( ( $Atu->normal_form( args2pitchset(@args) ) )[0],
        rs => $Flag_Record_Sep );
}

bin/atonal-util  view on Meta::CPAN

    my $tempo    = 60;
    my $fraction = 1;
    GetOptionsFromArray(
        \@args,
        'beats=i'    => \$beats,
        'ms!'        => \my $in_ms,
        'tempo=i'    => \$tempo,
        'fraction=s' => \$fraction,
    ) or print_help();

    if ( !looks_like_number($fraction) ) {
        if ( $fraction =~ m#^(\d+)/(\d+)$# ) {
            $fraction = $1 / $2;
        } else {
            die "unknown fraction: $fraction (expect 2/3 or such)\n";
        }
    }

    my @durations;
    for my $notespec ( map { split ' ' } @args ) {
        if ( $notespec =~

bin/atonal-util  view on Meta::CPAN

    }

    if ( !@args or ( @args == 1 and $args[0] eq '-' ) ) {
        chomp( @args = readline *STDIN );
    }

    # If pitch must int() it, otherwise feed to lilypond for conversion so
    # do not first need to call ly2pitch on the input.
    my @ret;
    for my $pitch (
        map { looks_like_number $_ ? int $_ : $Lyu->notes2pitches($_) }
        map { split ' ', $_ } @args
    ) {
        die "pitch '$pitch' out of range\n" if $pitch < 0 or $pitch > 108;
        if ($emit) {
            printf "%d\t%.2f\n", $pitch, $p2f->($pitch);
        } else {
            push @ret, $p2f->($pitch);
        }
    }
    return \@ret unless $emit;

bin/atonal-util  view on Meta::CPAN

    emit_pitch_set( $Atu->retrograde( args2pitchset(@args) ),
        rs => $Flag_Record_Sep );
}

sub rotate {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts, 'rotate|n=s' => \my $r, )
      or print_help();
    $Lyu->chrome('flats') if $Flag_Flat;
    $r //= 0;
    die "rotate must be number\n" unless looks_like_number $r;
    emit_pitch_set( $Atu->rotate( $r, args2pitchset(@args) ),
        rs => $Flag_Record_Sep );
}

sub set2beats {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts, 'scaledegrees|sd=i' => \my $sd, )
      or print_help();
    if ($sd) {
        $Atu = Music::AtonalUtil->new( DEG_IN_SCALE => $sd );

bin/atonal-util  view on Meta::CPAN

    my (@args) = @_;
    my $beats  = 4;
    my $tempo  = 60;
    GetOptionsFromArray(
        \@args,
        'beats=i' => \$beats,
        'tempo=i' => \$tempo,
    ) or print_help();

    for my $durms (@args) {
        die "argument $durms not a number\n" if !looks_like_number $durms;
        my $dur = 1 / ( ms_to_bpm( $durms, $beats ) / $tempo );
        # Cheat with lilypond multiplier syntax; breaking things down into c4~ c16.
        # would of course be more work.
        $dur = 100 * sprintf "%.2f", $dur;
        print "c$beats*$dur/100\n";
    }

    if ( @args > 1 ) {
        my $total_ms = sum(@args);
        my $dur      = 1 / ( ms_to_bpm( $total_ms, $beats ) / $tempo );

bin/atonal-util  view on Meta::CPAN

sub transpose {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts, 'transpose|n=s' => \my $t, )
      or print_help();
    $Lyu->chrome('flats') if $Flag_Flat;
    $t //= 0;

    my $pset = args2pitchset(@args);

    # if a number, transpose by that; if note, transpose to that note
    if ( !looks_like_number($t) ) {
        $t = $Lyu->notes2pitches($t) - $pset->[0];
    }
    emit_pitch_set( $Atu->transpose( $t, $pset ), rs => $Flag_Record_Sep );
}

sub transpose_invert {
    my (@args) = @_;
    GetOptionsFromArray(
        \@args, @Std_Opts,
        'axis|a=s'      => \my $axis,
        'transpose|t=s' => \my $t,
    ) or print_help();
    $Lyu->chrome('flats') if $Flag_Flat;

    my $pset = args2pitchset(@args);

    $axis = defined $axis ? $Lyu->notes2pitches($axis) : 0;

    # if a number, transpose by that; if note, transpose to that note
    $t //= 0;
    if ( !looks_like_number($t) ) {
        $t = $Lyu->notes2pitches($t) - $pset->[0];
    }

    emit_pitch_set( $Atu->transpose_invert( $t, $axis, $pset ),
        rs => $Flag_Record_Sep );
}

sub variances {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts ) or print_help();



( run in 0.453 second using v1.01-cache-2.11-cpan-64827b87656 )