-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmode-pivot
56 lines (48 loc) · 1.65 KB
/
mode-pivot
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper::Compact qw(ddc);
use MIDI::Util qw(setup_score midi_format);
use Music::Chord::Progression ();
use Music::ModalFunction ();
my $score = setup_score();
my $pitch = 'C';
my $scale = 'ionian';
for my $i (1 .. 4) {
my $prog = Music::Chord::Progression->new(
scale_note => $pitch,
scale_name => $scale eq 'ionian' ? 'ionian' : 'aeolian',
chord_map => $scale eq 'ionian' ? ['', 'm', 'm', '', '', 'm', 'dim'] : ['m','dim','','m','m','',''],
max => 4,
flat => 1,
resolve => 0,
);
my $chords = $prog->generate;
warn "$pitch $scale => ", ddc($chords);
for my $chord (@$chords) {
$score->n('wn', midi_format(@$chord));
}
my $last_pitch = $pitch;
my $last_scale = $scale;
($pitch = $prog->phrase->[-1]) =~ s/^([A-G][b#]?).*?$/$1/;
(my $modal_pitch = $pitch) =~ s/#/s/;
$modal_pitch =~ s/b/f/;
$scale = $prog->phrase->[-1] =~ /m/ ? 'aeolian' : 'ionian';
my $chord = $scale eq 'ionian' ? 'maj' : 'min';
my $m = Music::ModalFunction->new(
chord_note => lc($modal_pitch),
chord => $chord,
mode_note => $last_pitch,
mode => $last_scale eq 'ionian' ? 'ionian' : 'aeolian',
);
my $q = $m->pivot_chord_keys;
last unless @$q;
my $result = $q->[ int rand @$q ];
$pitch = substr $result->[7], 0, 1;
(my $accidental = $result->[7]) =~ s/^[a-g]([fs]?)/$1/;
$accidental = '#' if $accidental eq 's';
$accidental = 'b' if $accidental eq 'f';
$pitch = uc($pitch) . $accidental;
$scale = $result->[8];
}
$score->write_score("$0.mid");