App-MusicTools

 view release on metacpan or  search on metacpan

bin/atonal-util  view on Meta::CPAN


    for my $i ( 0 .. $Atu->scale_degrees - 1 ) {
        my $set = ( $Atu->normal_form( $Atu->transpose( $i, $pset ) ) )[0];
        if ( !$seen{"@$set"}++ ) {
            push @transpose, $set;
            my $iset =
              ( $Atu->normal_form( $Atu->transpose_invert( $i, 0, $pset ) ) )[0];
            push @transpose_invert, $iset if !$seen{"@$iset"}++;
        }
    }

    emit_pitch_set( \@transpose )        if @transpose;
    emit_pitch_set( \@transpose_invert ) if @transpose_invert;
}

sub findall {
    my (@args) = @_;
    GetOptionsFromArray(
        \@args, @Std_Opts,
        'exclude=s' => \my $excludes,
        'fn=s'      => \my $desired_forte_nums,
        'root=s'    => \my $root_pitch
    );
    $Lyu->chrome('flats') if $Flag_Flat;

    my $desired = args2pitchset(@args);
    my %excludes;
    @excludes{ $Lyu->notes2pitches( split /[, ]+/, $excludes ) } = ()
      if defined $excludes;
    $root_pitch = $Lyu->notes2pitches($root_pitch) if defined $root_pitch;
    my $fn_re;
    if ( defined $desired_forte_nums ) {
        $fn_re = '^[' . join( '', parse_range($desired_forte_nums) ) . ']$';
    }

    my $fnums = $Atu->fnums;
    for my $fnum ( sort keys %$fnums ) {
        if ( defined $desired_forte_nums ) {
            ( my $prefix = $fnum ) =~ s/[-].+//;
            next if $prefix !~ m/$fn_re/;
        }
        _findps( $fnums->{$fnum}, $desired, $root_pitch, \%excludes, $fnum );
    }
}

sub findin {
    my (@args) = @_;
    GetOptionsFromArray(
        \@args, @Std_Opts,
        'exclude=s'    => \my $excludes,
        'pitchset|P=s' => \my @base_input,
        'root=s'       => \my $root_pitch
    ) or print_help();

    die "error: atonal-util findin needs --pitchset=... option\n"
      unless @base_input;

    $Lyu->chrome('flats') if $Flag_Flat;

    for my $bi (@base_input) {
        say "PS $bi" if @base_input > 1;

        my $ps_base;
        if ( $bi =~ m/^\d-/ ) {
            $ps_base = $Atu->forte2pcs($bi);
            die "unknown Forte Number '$bi'\n" if !defined $ps_base;
        } else {
            $ps_base = args2pitchset( split /[ ,]/, $bi );
        }
        my $desired = args2pitchset(@args);
        my %excludes;
        @excludes{ $Lyu->notes2pitches( split /[, ]+/, $excludes ) } = ()
          if defined $excludes;
        $root_pitch = $Lyu->notes2pitches($root_pitch) if defined $root_pitch;

        if ( @$desired > @$ps_base ) {
            die "cannot desire more than is present\n";
        }

        _findps( $ps_base, $desired, $root_pitch, \%excludes );
    }
}

sub _findps {
    my ( $ps_base, $desired, $root_pitch, $excludes, $fnum ) = @_;
    $fnum     //= '-';
    $excludes //= {};

    _init_tension() if $Flag_Tension;

    my $ps_width = 24 - ( $Flag_Lyout ? 0 : 6 );

  TRANS: for my $i ( 0 .. $Atu->scale_degrees - 1 ) {
        my %tps;
        @tps{ @{ $Atu->transpose( $i, $ps_base ) } } = ();
        if ( all { exists $tps{$_} } @$desired ) {
            my @pitches = @{ $Atu->transpose( $i, $ps_base ) };
            next if defined $root_pitch and $pitches[0] != $root_pitch;
            if (%$excludes) {
                for my $p (@pitches) {
                    next TRANS if exists $excludes->{$p};
                }
            }

            my $tstr = '';
            if ($Flag_Tension) {
                $tstr = sprintf "\t%.03f  %.03f  %.03f", $Tension->vertical( \@pitches );
            }

            @pitches = $Lyu->p2ly(@pitches) if $Flag_Lyout;

            my $s = sprintf "%s\tT(%d)\t%-${ps_width}s%s", $fnum, $i,
              join( ',', @pitches ), $tstr;
            $s =~ s/\s+$//;
            say $s;
        }
    }

  TRANSINV: for my $i ( 0 .. $Atu->scale_degrees - 1 ) {
        my %ips;
        @ips{ @{ $Atu->transpose_invert( $i, 0, $ps_base ) } } = ();
        if ( all { exists $ips{$_} } @$desired ) {
            my @pitches = @{ $Atu->transpose_invert( $i, 0, $ps_base ) };
            next if defined $root_pitch and $pitches[0] != $root_pitch;
            if (%$excludes) {
                for my $p (@pitches) {
                    next TRANSINV if exists $excludes->{$p};
                }
            }

            my $tstr = '';
            if ($Flag_Tension) {
                $tstr = sprintf "\t%.03f  %.03f  %.03f", $Tension->vertical( \@pitches );
            }

            @pitches = $Lyu->p2ly(@pitches) if $Flag_Lyout;

            my $s = sprintf "%s\tTi(%d)\t%-${ps_width}s%s", $fnum, $i,
              join( ',', @pitches ), $tstr;
            $s =~ s/\s+$//;
            say $s;
        }
    }
}

sub fnums {
    my (@args) = @_;
    GetOptionsFromArray( \@args, @Std_Opts ) or print_help();
    _init_tension('cope') if $Flag_Tension;

    my $fns = $Atu->fnums;
    for my $fn ( sort keys %$fns ) {
        my $pset = $fns->{$fn};
        my $icc  = $Atu->interval_class_content($pset);

        my $tstr = '';
        if ($Flag_Tension) {
            $tstr = sprintf "\t%.03f  %.03f  %.03f", $Tension->vertical($pset);
        }

        my $s = sprintf "%s\t%-16s\t%-8s%s", $fn, join( ',', @$pset ),
          join( '', @$icc ), $tstr;
        $s =~ s/\s+$//;
        say $s;
    }
}

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

    emit_pitch_set( $Atu->forte2pcs( $args[0] ), rs => $Flag_Record_Sep );
}

sub freq2pitch {
    my (@args) = @_;
    my $mode = 'absolute';
    GetOptionsFromArray(
        \@args,
        @Std_Opts,
        'concertfreq|cf=s'  => \my $concert_freq,
        'concertpitch|cp=s' => \my $concert_pitch,
        'relative=s'        => \my $relative,
        'scala=s'           => \my $scala_file,
    ) or print_help();

    my ( $scala, $p2f ) = _init_scala( $concert_freq, $concert_pitch, $scala_file );

    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;

        my $percent = abs($error) / $pitch_freq * 100;

        printf "%.2f\t%s\t%+.2f\t%.2f%%\n", $freq, $p, $error, $percent;
    }
}

sub gen_melody {
    my (@args) = @_;
    $Flag_Record_Sep = ' ';    # for easier feeding to ly-fu
    GetOptionsFromArray( \@args, @Std_Opts ) or print_help();
    $Lyu->chrome('flats') if $Flag_Flat;
    emit_pitch_set( $Atu->gen_melody, rs => $Flag_Record_Sep );
}

sub half_prime_form {
    my (@args) = @_;



( run in 0.765 second using v1.01-cache-2.11-cpan-d7f47b0818f )