#!/usr/bin/env perl
use strict;
use warnings;

use Music::ScaleNote ();

my $row_offset = shift || 4; # major 3rd
my $col_offset = shift || 7; # major 5th
my $row_num    = shift || 6; # 
my $col_num    = shift || 9; # 

my $half_one = int ($col_num - 1) / 2;

my $msn = Music::ScaleNote->new(
    scale_name => 'chromatic',
    flat       => 1,
    # verbose    => 1,
);

my $note_name = 'C4';

# compute the row notes
my @notes = ($note_name);
my $name = $note_name;
for my $i (1 .. $row_num - 1) {
    my $n = $msn->get_offset(
        note_name   => $name,
        note_format => 'ISO',
        offset      => $row_offset,
    );
    $name = $n->format('ISO');
    push @notes, $name;
}

my $row = 0;
my $width = 2;

for my $note (@notes) {
    $row++;

    for my $i (-$half_one .. -1) {
        my $n = $msn->get_offset(
            note_name   => $note,
            note_format => 'ISO',
            offset      => $i * $col_offset,
        );
        printf '%-*s  ', $width, $n->format('isobase');
    }

    ($name = $note) =~ s/\d+//;
    printf '%-*s  ', $width, $name;

    for my $i (1 .. $half_one) {
        my $n = $msn->get_offset(
            note_name   => $note,
            note_format => 'ISO',
            offset      => $i * $col_offset,
        );
        printf '%-*s  ', $width, $n->format('isobase');
    }

    print "\n";
    print ' ' x ($row * $width);
}

__END__
Ab  Eb  Bb  F   C   G   D   A   E
  C   G   D   A   E   B   Gb  Db  Ab
    E   B   Gb  Db  Ab  Eb  Bb  F   C
      Ab  Eb  Bb  F   C   G   D   A   E
        C   G   D   A   E   B   Gb  Db  Ab
          E   B   Gb  Db  Ab  Eb  Bb  F   C
