Skip to content

Instantly share code, notes, and snippets.

@suntong
Created August 28, 2023 15:17
Show Gist options
  • Save suntong/e243315ebaec9ff679e824ac9eaf5fce to your computer and use it in GitHub Desktop.
Save suntong/e243315ebaec9ff679e824ac9eaf5fce to your computer and use it in GitHub Desktop.
#! /usr/bin/env -S perl -p
# -*- perl -*-
# @Author: Tong SUN, (c)2023, all right reserved
# ABC unit note length
# http://abcnotation.com/wiki/abc:standard:v2.1#lunit_note_length
my $abcL = 4;
## == Headers
## http://abcnotation.com/wiki/abc:standard:v2.1#tune_header_definition
if (/^[XCR]:/) { $_ = '' }
elsif (/^(T:)/) { $repl=$1; s/$repl/title=/; }
elsif (/^(M:)/) { $repl=$1; s/$repl//; }
elsif (/^(K:)/) { $repl=$1; s/$repl/1=/; }
elsif (/^(C:)/) { $repl=$1; s/$repl/composer=/; }
elsif (/^(Q:.*?\/)/) { $repl=$1; s/$repl/%% tempo: /; }
elsif (/^(L:.*?\/)(\d+)/) { $abcL=$2; $_ = ''; print "] abcL=$abcL\n" if 0; }
# body lyrics
elsif (/^(w: *)/) { $repl=$1; s/$repl/L: /; }
else {
## == ABC Bodies
## http://abcnotation.com/wiki/abc:standard:v2.1#tune_body_definition
# guitar chords, skip them all
s/".*?"//g;
# ABC notes
# http://abcnotation.com/wiki/abc:standard:v2.1#the_tune_body
my %abc_notes = (
C => 1, D => 2, E => 3, F => 4, G => 5, A => 6, B => 7,
c => "1'", d => "2'", e => "3'", f => "4'", g => "5'", a => "6'", b => "7'",
"c'" => "1''", "d'" => "2''", "e'" => "3''", "f'" => "4''",
"g'" => "5''", "a'" => "6''", "b'" => "7''",
"C," => "1,", "D," => "2,", "E," => "3,", "F," => "4,",
"G," => "5,", "A," => "6,", "B," => "7,",
);
# notes lengths (1/n)
my %notes_lengths = (
4 => 'XZM', 8 => 'q', 16 => 's', 32 => 'd', 64 => 'h',
);
# notes extend
my %notes_extend = (
1 => '', 2 => ' -', 3 => '. -', 4 => ' - -',
);
# https://www.debuggex.com/r/LrK7RxK0D8LVvQY5
# https://regex101.com/r/hEpgR3/5
while (/([a-g][,']*)(((\/+)(\d*))|(\d*))/gi) {
# org, note, dividing, dividing_n, multiplier
$o=$&; $n=$1; $d=$4; $dn=$5; $m=$6;
#print "'$o' note, dividing (n), multiplier: '$n' '$d($dn)' '$m'\n";
my ($jpn, $jpo) = ($abc_notes{$n}, ''); # jp note, output
my ($jpl, $jpln) = (1, ''); # note_length, length_name
if (length($d)>0) {
# Shorter notes
if (length($dn)>0) {
# Shorter notes, dividing with number
$jpl = $abcL * $dn
} else {
# shorthands: A/ = A/2, A// = A/4
$jpl = $abcL * 2 * length($d)
}
$jpln = $notes_lengths{$jpl};
$jpo = "$jpln$jpn";
} else {
# with a multiplier
if ($m == 0) { $m = 1; }
$jpln = $notes_lengths{$abcL};
$jpo = "$jpln$jpn$notes_extend{$m}";
}
#print "'$o' ($jpl) => $jpo\n";
s/$o/$jpo /;
}
s{\|\]}{}g;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment