use v6;
BEGIN { push @*INC, "lib" }
use ABC;
my @matches = $*IN.slurp.comb(m/ <ABC::tune> /, :match);
my %dg_notes = {
'g' => 1,
'a' => 1,
'b' => 1,
'c' => 1,
'd' => 1,
'e' => 1,
'^f' => 1
}
for @matches {
my %header = header_hash(.<ABC::tune><header>);
say %header<T> ~ ":";
my @notes = gather for .<ABC::tune><music><line_of_music> -> $line
{
for $line<bar> -> $bar
{
for $bar<element>
{
when .<broken_rhythm> { take .<broken_rhythm><note>[0]; take .<broken_rhythm><note>[1]; }
when .<note> { take .<note>; }
}
}
}
my %key_signature = key_signature(%header<K>);
my @trouble = @notes.map({apply_key_signature(%key_signature, .<pitch>)}).grep({!%dg_notes.exists(lc($_))});
say @trouble.perl;
}
Basically, we set up
@matches
with all the tunes in the file, and %dg_notes
with all the notes that can be played (though it's actually just the key of G for now). Then for each tune, we loop through and collect all the notes, factored into the appropriate key signature. Then we just grep against the notes that are allowed to make a list of the notes not present on a G accordion. Here are the results on my sample file:
Cuckold Come Out o' the Amrey:
["^c", "^c", "^c", "^c", "^c", "^c", "^c", "^c", "=f", "^c", "^c", "^c", "^c"]
Elsie Marley:
["=F", "=f"]
Peacock Followed the Hen. JWDM.07:
[]
So in this case, "Cuckold" has a bunch of c-sharps and an f-natural, "Elsie Marley" has a couple of f-naturals, and "Peacock" is solidly playable on a G accordion.
While this approach has been fun, I think it's time to dig in use Perl 6 grammar actions to build a smarter data structure for ABC tunes. Should be exciting...
This is great! But you're still missing a bunch of very common ABC components in Irish traditional music, like tilde for rolls and first and second endings.
ReplyDelete