Skip to content

Instantly share code, notes, and snippets.

@dr-kd
Created November 16, 2020 02:12
Show Gist options
  • Save dr-kd/1607c7922223df879a14a03bce4d30b4 to your computer and use it in GitHub Desktop.
Save dr-kd/1607c7922223df879a14a03bce4d30b4 to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
use warnings;
use strict;
use Array::Circular;
use Data::Dumper;
use Text::Xslate qw/mark_raw/;
use feature qw/say/;
my $tx = Text::Xslate->new(syntax => 'TTerse');
my $scale = Array::Circular->new(qw/c d e f g a b/);
# Or the hungarian minor scale
# my $scale = Array::Circular->new(qw /c d ees ges g aes b/);
# Array indexes for every mode (starting note) in the sequence.
my @scale_indexes;
foreach my $s ( 0 .. $#$scale) {
my @front = $s .. $#$scale;
my @back = 0 .. $s - 1;
push @scale_indexes, [@front, @back];
}
# generate the notes for each mode of the scale
my $steps = Array::Circular->new(
map { Array::Circular->new(@$scale[ @$_ ]) } @scale_indexes);
my @out = ();
# and for now, just print it out
for (0 .. @$steps) {
my $n = $steps->current;
my @result = line($n, sequence());
push @out, \@result;
$steps->next;
}
push @out, [line($steps->[0], seq_return())];
push @out, [line($steps->[0], chord_seq())];
render(\@out);
sub line {
my ($scale, $sequence) = @_;
$scale->reset;
my @seq;
for my $s (@$sequence) {
my $meth = $s->{action};
my $i = $s->{iv};
my $note = $scale->current;
my $dur = exists $s->{dur} ? $s->{dur} : '';
my $oct = exists $s->{oct} ? $s->{oct} : '';
push @seq, mark_raw("$note$oct$dur ");
$scale->$meth($i);
}
push @seq, $scale->current;
return @seq;
}
sub render {
say $tx->render('test.tx', {scale => $_[0],
title => 'Scale Study',
key => 'c',
mode => 'major',
author => 'Lennie Niehaus mod kd',
time => '4/4',
});
}
sub sequence {
[
# Duration and direction and interval
{ action => 'next', iv => 2, dur => 4, },
{ action => 'next', iv => 2, dur => 8, },
{ action => 'next', iv => 2},
{ action => 'prev', iv => 2, dur => 4 },
{ action => 'prev', iv => 2, dur => 8, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, dur => 4, },
# scale run up
{ action => 'next', iv => 1, dur => 8, },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'prev', iv => 2, },
# down in thirds
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, },
]
}
sub seq_return {
my $seq = sequence();
$seq->[-1]->{action} = 'prev';
$seq->[-1]->{iv} = 3;
return $seq;
}
sub chord_seq {
[
{ action => 'prev', iv => 5, oct => q|'| },
{ action => 'next', iv => 1, oct => q|,| },
{ action => 'next', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 6, },
{ action => 'next', iv => 2, oct => q|,| },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2 },
{ action => 'next', iv => 1, oct => q|,| },
{ action => 'next', iv => 1, },
## still working this bit out.
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, oct => q|,| },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, },
{ action => 'next', iv => 1, oct => q|,| },
{ action => 'next', iv => 2 , },
# { action => '', iv => 0, dur => undef },
];
}
#!/usr/bin/env perl
use warnings;
use strict;
use Array::Circular;
use Data::Dumper;
use Text::Xslate qw/mark_raw/;
use feature qw/say/;
my $tx = Text::Xslate->new(syntax => 'TTerse');
my $scale = Array::Circular->new(qw/c d e f g a b/);
# Or the hungarian minor scale
# my $scale = Array::Circular->new(qw /c d ees ges g aes b/);
# Array indexes for every mode (starting note) in the sequence.
my @scale_indexes;
foreach my $s ( 0 .. $#$scale) {
my @front = $s .. $#$scale;
my @back = 0 .. $s - 1;
push @scale_indexes, [@front, @back];
}
# generate the notes for each mode of the scale
my $steps = Array::Circular->new(
map { Array::Circular->new(@$scale[ @$_ ]) } @scale_indexes);
my @out = ();
# and for now, just print it out
for (0 .. @$steps) {
my $n = $steps->current;
my @result = line($n, sequence());
push @out, \@result;
$steps->next;
}
push @out, [line($steps->[0], seq_return())];
push @out, [line($steps->[0], chord_seq())];
render(\@out);
sub line {
my ($scale, $sequence) = @_;
$scale->reset;
my @seq;
for my $s (@$sequence) {
my $meth = $s->{action};
my $i = $s->{iv};
my $note = $scale->current;
my $dur = exists $s->{dur} ? $s->{dur} : '';
my $oct = exists $s->{oct} ? $s->{oct} : '';
push @seq, mark_raw("$note$oct$dur ");
$scale->$meth($i);
}
push @seq, $scale->current;
return @seq;
}
sub render {
say $tx->render('test.tx', {scale => $_[0],
title => 'Scale Study',
key => 'c',
mode => 'major',
author => 'Lennie Niehaus mod kd',
time => '4/4',
});
}
sub sequence {
[
# Duration and direction and interval
{ action => 'next', iv => 2, dur => 4, },
{ action => 'next', iv => 2, dur => 8, },
{ action => 'next', iv => 2},
{ action => 'prev', iv => 2, dur => 4 },
{ action => 'prev', iv => 2, dur => 8, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, dur => 4, },
# scale run up
{ action => 'next', iv => 1, dur => 8, },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'next', iv => 1 },
{ action => 'prev', iv => 2, },
# down in thirds
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, },
]
}
sub seq_return {
my $seq = sequence();
$seq->[-1]->{action} = 'prev';
$seq->[-1]->{iv} = 3;
return $seq;
}
sub chord_seq {
[
{ action => 'prev', iv => 5, oct => q|'| },
{ action => 'next', iv => 1, oct => q|,| },
{ action => 'next', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'prev', iv => 6, },
{ action => 'next', iv => 2, oct => q|,| },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2 },
{ action => 'next', iv => 1, oct => q|,| },
{ action => 'next', iv => 1, },
## still working this bit out.
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, oct => q|,| },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, },
{ action => 'next', iv => 1, },
{ action => 'next', iv => 2, },
{ action => 'next', iv => 1, oct => q|,| },
{ action => 'next', iv => 2 , },
# { action => '', iv => 0, dur => undef },
];
}
\version "2.18.2"
\header {
title = " [% title %]"
composer = "[% author %]"
}
\paper{
ragged-bottom=##t
bottom-margin=0\mm
page-count=1
}
\score {
\relative c' {
\time [% time %] \key [% key %] \[% mode %]
[% FOREACH r IN scale; %]
[% FOREACH n IN r ; n _ ' ' ; END %]
\break
[% END %]
}
\layout {}
\midi {}
}
\version "2.18.2"
\header {
title = " [% title %]"
composer = "[% author %]"
}
\paper{
ragged-bottom=##t
bottom-margin=0\mm
page-count=1
}
\score {
\relative c' {
\time [% time %] \key [% key %] \[% mode %]
[% FOREACH r IN scale; %]
[% FOREACH n IN r ; n _ ' ' ; END %]
\break
[% END %]
}
\layout {}
\midi {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment