#!/usr/bin/perl
# this is my first ever perl script
use strict;
# semitone offsets of major scale from C
my @Semitone = (0, 2, 4, 5, 7, 9, 11);
# mode strings to indices
my %Mode = ("" => 0, "D" => 1, "Y" => 2, "L" => 3, "M" => 4, "b" => 5, "C" => 6);
# chord inversion maps
my %Inv = (
"" => [0, 2, 4], "6" => [2, 4, 0], "64" => [4, 0, 2],
"7" => [0, 2, 4, 6], "65" => [2, 4, 6, 0], "43" => [4, 6, 0, 2], "42" => [6, 0, 2, 4],
);
# read a line
while (<>) {
# remove trailing newline
# trends page uses ".", hooktheory api uses ","
# match entire string, trim whitespace for convenience
# see somewhere at the doc for original grammar
!(/\s*^([DYLMbC])?([1-7])(7|65|43|42|64|6)?(\/([1-7]))?\s*$/) and next;
# chord cannot be both applied and borrowed
(my $applied = !!$5) and $1 and next;
# apply inversion
my @chord = @{$Inv{$3}};
# map degree indices to semitone values
for (@chord) {
# root degree + chord factor + mode shift
my $degree = $2 + $_ + $Mode{$1};
# convert to semitones
$_ = $Semitone[($degree - 1) % 7];
# transpose scale so that tonic becomes C
$_ -= $Semitone[$Mode{$1}];
# transpose applied chord relative to destination
$applied and ($_ += $Semitone[$5 - 1]);
# limit within 0 - 11
$_ %= 12;
}
# display semitones
}
}
IyEvdXNyL2Jpbi9wZXJsCgojIHRoaXMgaXMgbXkgZmlyc3QgZXZlciBwZXJsIHNjcmlwdAp1c2Ugc3RyaWN0OwoKIyBzZW1pdG9uZSBvZmZzZXRzIG9mIG1ham9yIHNjYWxlIGZyb20gQwpteSBAU2VtaXRvbmUgPSAoMCwgMiwgNCwgNSwgNywgOSwgMTEpOwojIG1vZGUgc3RyaW5ncyB0byBpbmRpY2VzCm15ICVNb2RlID0gKCIiID0+IDAsICJEIiA9PiAxLCAiWSIgPT4gMiwgIkwiID0+IDMsICJNIiA9PiA0LCAiYiIgPT4gNSwgIkMiID0+IDYpOwojIGNob3JkIGludmVyc2lvbiBtYXBzCm15ICVJbnYgPSAoCgkiIiA9PiBbMCwgMiwgNF0sICI2IiA9PiBbMiwgNCwgMF0sICI2NCIgPT4gWzQsIDAsIDJdLAoJIjciID0+IFswLCAyLCA0LCA2XSwgIjY1IiA9PiBbMiwgNCwgNiwgMF0sICI0MyIgPT4gWzQsIDYsIDAsIDJdLCAiNDIiID0+IFs2LCAwLCAyLCA0XSwKKTsKCiMgcmVhZCBhIGxpbmUKd2hpbGUgKDw+KSB7CgkjIHJlbW92ZSB0cmFpbGluZyBuZXdsaW5lCgljaG9tcDsKCSMgdHJlbmRzIHBhZ2UgdXNlcyAiLiIsIGhvb2t0aGVvcnkgYXBpIHVzZXMgIiwiCglmb3IgKHNwbGl0IC9bLiw7XS8pIHsKCQkjIG1hdGNoIGVudGlyZSBzdHJpbmcsIHRyaW0gd2hpdGVzcGFjZSBmb3IgY29udmVuaWVuY2UKCQkjIHNlZSBzb21ld2hlcmUgYXQgdGhlIGRvYyBmb3Igb3JpZ2luYWwgZ3JhbW1hcgoJCSEoL1xzKl4oW0RZTE1iQ10pPyhbMS03XSkoN3w2NXw0M3w0Mnw2NHw2KT8oXC8oWzEtN10pKT9ccyokLykgYW5kIG5leHQ7CgkJIyBjaG9yZCBjYW5ub3QgYmUgYm90aCBhcHBsaWVkIGFuZCBib3Jyb3dlZAoJCShteSAkYXBwbGllZCA9ICEhJDUpIGFuZCAkMSBhbmQgbmV4dDsKCQkjIGFwcGx5IGludmVyc2lvbgoJCW15IEBjaG9yZCA9IEB7JEludnskM319OwoJCSMgbWFwIGRlZ3JlZSBpbmRpY2VzIHRvIHNlbWl0b25lIHZhbHVlcwoJCWZvciAoQGNob3JkKSB7CgkJCSMgcm9vdCBkZWdyZWUgKyBjaG9yZCBmYWN0b3IgKyBtb2RlIHNoaWZ0CgkJCW15ICRkZWdyZWUgPSAkMiArICRfICsgJE1vZGV7JDF9OwoJCQkjIGNvbnZlcnQgdG8gc2VtaXRvbmVzCgkJCSRfID0gJFNlbWl0b25lWygkZGVncmVlIC0gMSkgJSA3XTsKCQkJIyB0cmFuc3Bvc2Ugc2NhbGUgc28gdGhhdCB0b25pYyBiZWNvbWVzIEMKCQkJJF8gLT0gJFNlbWl0b25lWyRNb2RleyQxfV07CgkJCSMgdHJhbnNwb3NlIGFwcGxpZWQgY2hvcmQgcmVsYXRpdmUgdG8gZGVzdGluYXRpb24KCQkJJGFwcGxpZWQgYW5kICgkXyArPSAkU2VtaXRvbmVbJDUgLSAxXSk7CgkJCSMgbGltaXQgd2l0aGluIDAgLSAxMQoJCQkkXyAlPSAxMjsKCQl9CgkJIyBkaXNwbGF5IHNlbWl0b25lcwoJCXByaW50ICRfLCAiIC0+ICIsIGpvaW4oIiwiLCBAY2hvcmQpLCAiXG4iOwoJfQoJcHJpbnQgIlxuIjsKfQo=
D47 -> 5,9,0,3
L27 -> 2,6,9,0
b7 -> 10,2,5
565/2 -> 1,4,7,9
1 -> 0,4,7
364 -> 11,4,7
6 -> 9,0,4
164 -> 7,0,4
4 -> 5,9,0
16 -> 4,7,0
265 -> 5,9,0,2
57 -> 7,11,2,5
1 -> 0,4,7